webpack4入门教程

Webpack4入门

webpack4已经出来很久了,本人直接跳过了Webpack3就来学4了,本教程Webpack版本直接是使用的目前最新的v4.33.0,Webpack是什么我这就不过多介绍了,我们直接开始码起来吧!

安装webpack

  • 需要先在项目文件夹中npm init初始化一下,填一下配置参数,有的默认即可,然后生成package.json。
  • 建议node版本安装到8.2以上
// webpack4中除了正常安装webpack之外,需要再单独安一个webpack-cli

npm i webpack webpack-cli -D

// npm 安装有点慢,想要快的换可以使用淘宝镜像 cnpm

注意: npm i xxx -D 是 npm install xxx --save-dev 的简写,是指安装模块并保存到package.json 的 devDependencies中,主要在开发环境中的依赖包。

Webpack是基于Node的,其运行环境是NodeJS

在项目根目录下创建一个 webpack.config.js (默认,可修改)文件来配置webpack

module.exports = {
    entry: '',               // 入口文件
    output: {},              // 出口文件
    module: {},              // 处理对应模块
    plugins: [],             // 对应的插件
    devServer: {},           // 开发服务器配置
    mode: 'development'      // 模式配置
}

以上就是webpack的正常配置模块

★ 启动devServer需要安装一下webpack-dev-server

npm i webpack-dev-server -D

配置执行文件

工作当中我们打包编译的时候一般都执行 npm run dev 这样的命令,既然是通过npm 执行的命令,我们就应该找到 package.json 里的执行脚本去配置一下命令,这里如下图所示
在这里插入图片描述
npm run build 就是我们打包后的文件,这是生产环境下,上线需要的文件

npm run dev 是我们开发环境下打包的文件,当然由于devServer帮我们把文件放到内存中了,所以并不会输出打包后的dist文件夹

通过npm run build之后会生成一个dist目录文件夹

开始项目

在根目录下见一个src文件夹,文件夹内建一个index.js文件
在这里插入图片描述
按照项目的结构,我们就从0开始去写一下配置吧

// webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/index.js',    // 入口文件
    output: {
        filename: 'bundle.js',      // 打包后的文件名称
        path: path.resolve('dist')  // 打包后的目录,必须是绝对路径
    }
    // ...
}

然后运行 npm run build 即可完成一个简单的打包
在这里插入图片描述

多入口文件

多个入口可以有两种实现方式进行打包

  • 一种是没有关系的但是要打包到一起去的,可以写一个数组,实现多个文件打包
  • 另一种就是每一个文件都单独打包成一个文件的,写一个对象,实现多文件一对一打包,注意模式下不可打包至一个文件,否则会报错

下面就来看看这两种方式的写法

let path = require('path');

module.exports = {
    // 1.写成数组的方式就可以打出多入口文件,不过这里打包后的文件都合成了一个
    // entry: ['./src/index.js', './src/login.js'],
    
    // 2.真正实现多入口和多出口需要写成对象的方式
    entry: {
        index: './src/index.js',
        login: './src/login.js'
    },
    output: {
        // 1. filename: 'bundle.js',
        
        // 2. [name]就可以将出口文件名和入口文件名一一对应
        filename: '[name].js',  // 打包后会生成index.js和login.js文件
        path: path.resolve('dist')
    },
    // ...
}

这时候执行 npm run build 后,会生成打包好的两个js文件,如图所示
在这里插入图片描述

配置Html模板

文件都打包好了,但是我们在使用的时候不能在dist目录下去创建一个html文件,然后去引用打包后的js吧,这不合理,实际开发中也不会这样。

我们需要实现html打包功能,可以通过一个模板实现打包出引用好路径的html来。

这就需要用到一个常用的插件了,html-webpack-plugin,用之前我们来安装一下它。

npm i html-webpack-plugin -D

因为是个插件,所以需要在config.js里引用一下的

let path = require('path');
// 插件都是一个类,所以我们命名的时候尽量用大写开头
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        // 添加hash可以防止文件缓存,每次都会生成4位的hash串
        filename: 'bundle.[hash:4].js',   
        path: path.resolve('dist')
    },
    plugins: [
        // 通过new一下这个类来使用插件
        new HtmlWebpackPlugin({
            // 用哪个html作为模板
            // 在src目录下创建一个index.html页面当做模板来用
            template: './src/index.html',
            hash: true, // 会在打包好的bundle.js后面加上hash串
        })
    ],
    // ...
}

在src目录下创建一个index.html
在这里插入图片描述
通过上面的配置后,我们再 npm run build 打包看一下现在是个什么样子了
在这里插入图片描述

多页面开发,怎么配置多页面

如果开发的时候不只一个页面,我们需要配置多页面,那么需要怎么来搞呢?不用担心,html-webpack-plugin插件自有办法,我们来观望一下

let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    // 多页面开发,怎么配置多页面
    entry: {
        index: './src/index.js',
        login: './src/login.js'
    },
    // 出口文件  
    output: {                       
        filename: '[name].js',
        path: path.resolve('dist')
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',   
            filename: 'index.html',
            chunks: ['index']   // 对应关系,index.js对应的是index.html
        }),
        new HtmlWebpackPlugin({
            template: './src/login.html',
            filename: 'login.html',
            chunks: ['login']   // 对应关系,login.js对应的是login.html
        })
    ],
    // ...
}

继续 npm run build 看打包后的样子
在这里插入图片描述
上面基本介绍完了html和js的打包配置了,现在我们还缺一个好兄弟css,webpack对css的解析需要用到loader,所以我们先提前安装好,待会好方便使用

引用CSS文件

可以在src/index.js里引入css文件,到时候直接打包到生产目录下

需要下载一些解析css样式的loader

说明:

  • css-loader 的作用是解析入口js文件中import引入的css文件
  • style-loader 的作用是将css-loader解析的css文件以<style></style>标签的形式注入到HTML中。
npm i style-loader css-loader -D

// 引入less文件的话,也需要安装对应的loader
npm i less less-loader -D

src目录下新建 css/style.css 和 less/style.less
在这里插入图片描述
在这里插入图片描述
下面我们来看一下如何配置css文件的解析

// index.js
import './css/style.css';   // 引入css
import './less/style.less'; // 引入less

// ...
// webpack.config.js

// ...

module.exports = {
    entry: {
        index: './src/index.js'
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve('dist')
    },
    module: {
        rules: [
            {
                test: /\.css$/,     // 解析css
                use: ['style-loader', 'css-loader'] // 从右向左解析
                /* 
                    也可以这样写,这种方式方便写一些配置参数
                    use: [
                        {loader: 'style-loader'},
                        {loader: 'css-loader'}
                    ]
                */
            },
            {
                test: /\.less$/,     // 解析css
                use: ['style-loader', 'css-loader', 'less-loader'] // 从右向左解析
            }
        ]
    },
    // ...
}

在这里插入图片描述

  • css样式是打包在bundle.js中的,只用js执行后index.html中才会有css代码
  • 此时打包后的css文件是以行内样式style的标签写进打包后的html页面中,如果样式很多的话,我们更希望直接用link的方式引入进去,这时候需要把css拆分出来
  • extract-text-webpack-plugin插件相信用过的人都知道它是干什么的,它的功效就在于会将打包到js里的css文件进行一个拆分

拆分CSS

// @next表示可以支持webpack4版本的插件
npm i extract-text-webpack-plugin@next -D
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
// 拆分css样式的插件
let ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        fileneme: 'bundle.js',
        path: path.resolve('dist')
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ExtractTextWebpackPlugin.extract({
                    // 将css用link的方式引入就不再需要style-loader了
                    use: 'css-loader'       
                })
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
        }),
        // 拆分后会把css文件放到dist目录下的css/style.css
        new ExtractTextWebpackPlugin('css/style.css')  
    ],
    // ...
}

此时拆分完css后,打包的html页面就以link的方式去引入css了,这样很好
在这里插入图片描述
当然大家很多都说另外一个插件也是可以办到的,那就是mini-css-extract-plugin,是的可以说它是为webpack4而生的,而之所以上来就没有介绍是因为还不成熟,还有很多bug需要去解决的

不过既然大家都知道它,那就顺便也提一下吧

npm i mini-css-extract-plugin -D

使用起来和上面的插件是差不多的

// ...
let MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/a.css'   // 指定打包后的css
        })
    ],
    // ...
}

拆分成多个css

这里要着重说一下上面两个插件的区别了,我个人还是建议用extract-text-webpack-plugin的,毕竟从之前的版本承接下来的,虽然在安包的时候需要@next,但是还是值得信赖的

而且现在的extract-text-webpack-plugin也支持了拆分成多个css,而目前mini-css-extract-plugin还不支持此功能

let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
// 拆分css样式的插件
let ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
// 正常写入的less
let styleLess = new ExtractTextWebpackPlugin('css/style.css');
// reset
let resetCss = new ExtractTextWebpackPlugin('css/reset.css');

module.exports = {
    entry: './src/index.js',
    output: {
        fileneme: 'bundle.js',
        path: path.resolve('dist')
    },
    module: {
        rules: [
            {
                test: /\.css$/, // 解析css
                use: resetCss.extract({
                    use: 'css-loader'
                })
            },
            {
                test: /\.less$/,
                use: styleLess.extract({
                    use: ['css-loader', 'less-loader']
                })
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
        }),
        styleLess,
        resetCss 
    ],
    // ...
}

通过这样操作后可以打包成两个不同的css文件,如下图
在这里插入图片描述

引用图片

处理图片方面,也需要loader

说明:

  • file-loader 的作用是将入口js文件上的import / require引入图片解析为url,并将该文件映射到输出目录中。
  • url-loader 的作用是将url()引入文件转换成base64 uriwebpack加载程序。
  • url-loader依赖file-loader
  • 当使用url-loader加载图片,图片大小小于上限值,则将图片转base64字符串;否则使用file-loader加载图片,都是为了提高浏览器加载图片速度。
  • 使用url-loader加载图片比file-loader更优秀
npm i file-loader url-loader -D

css 中引入背景图片
在这里插入图片描述
如果是在css文件里引入的如背景图之类的图片,就需要指定一下相对路径

// ...
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.css$/, // 解析css
                use: resetCss.extract({
                    use: 'css-loader',
                    publicPath: '../'
                })
            },
            {
                test: /\.less$/,
                use: styleLess.extract({
                    use: ['css-loader', 'less-loader']
                })
            },
            {
                test: /\.(jpe?g|png|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192,    // 小于8k的图片自动转成base64格式,并且不会存在实体图片
                            outputPath: 'images/'   // 图片打包后存放的目录
                        }
                    }
                ]
            }
        ]
    },
    // ...
}

在css中指定了publicPath路径这样就可以根据相对路径引用到图片资源了,如下图所示
在这里插入图片描述

注意:

不管是使用ExtractTextWebpackPlugin插件还是MiniCssExtractPlugin时,都需要配置publicPath: "../",不配置时css文件中背景图默认地址会在css文件夹下查找图片资源,导致项目图片路径不正确

页面img引用图片

页面中经常会用到img标签,img引用的图片地址也需要一个loader来帮我们处理好

npm i html-withimg-loader -D

在这里插入图片描述

// ...
module.exports = {
	// ...
    module: {
        rules: [
            {
                test: /\.(htm|html)$/,
                use: 'html-withimg-loader'
            }
        ]
    },
    // ...
}

这样再打包后的html文件下img就可以正常引用图片路径了
在这里插入图片描述

注意:

如果出现<img src={"default":"389a66a25c539a9fd3524d58c43e2560.png"}>这种错误,可在进行如下处理:

{
    test: /\.(jpe?g|png|gif)$/,
    use: [
        {
            loader: 'url-loader',
            options: {
            	esModule: false, //此处加一个esModule: false
                limit: 8192,    // 小于8k的图片自动转成base64格式,并且不会存在实体图片
                outputPath: 'images/'   // 图片打包后存放的目录
            }
        }
    ]
}

引用字体图片和svg图片

字体图标和svg图片都可以通过file-loader来解析

// ...
module.exports = {
	// ...
    module: {
        rules: [
            {
                test: /\.(eot|ttf|woff|svg)$/,
                use: 'file-loader'
            }
        ]
    },
    // ...
}

添加CSS3前缀

通过postcss中的autoprefixer可以实现将CSS3中的一些需要兼容写法的属性添加响应的前缀,这样省去我们不少的时间

由于也是一个loader加载器,我们也需要先安装一下

npm i postcss-loader autoprefixer -D

安装后,我们还需要像webpack一样写一个config的配置文件,在项目根目录下创建一个postcss.config.js文件,配置如下:

module.exports = {
    plugins: [require('autoprefixer')]  // 引用该插件即可了
}

然后在webpack里配置postcss-loader

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/, // 解析css
                use: resetCss.extract({
                    use: ['css-loader', 'postcss-loader'],
                    publicPath: '../'
                })
            },
            {
                test: /\.less$/,
                use: styleLess.extract({
                    use: ['css-loader', 'less-loader', 'postcss-loader']
                })
            },
            // ...
        ]
    }
}

添加几个需要autoprefixer的CSS3样式
在这里插入图片描述
注意:完成以上操作autoprefixer还是不会生效的,需要在package.json中加上以下代码

"browserslist": [
    "defaults",
    "> 1%",
    "last 2 versions",
    "not ie <= 8",
    "ios > 7"
]

loader后就是以下
在这里插入图片描述

转义ES6

在实际开发中,我们在大量的使用着ES6及之后的api去写代码,这样会提高我们写代码的速度,不过由于低版本浏览器的存在,不得不需要转换成兼容的代码,于是就有了常用的Babel了

Babel会将ES6的代码转成ES5的代码

那么不再多说,既然要使用它,就先来安一下,试了很多种npm方法,发现build时都是报错,最后找到下面这种方法是可行的

npm i @babel/cli @babel/core babel-loader @babel/preset-env -D

当把这些都安好后,我们就开始配置,由于要兼容的代码不仅仅包含ES6还有之后的版本和那些仅仅是草案的内容,所以我们可以通过一个.babelrc文件来配置一下,对这些版本的支持

// .babelrc
{
    "presets": ["@babel/preset-env"]   // 从右向左解析
}

我们再在webpack里配置一下babel-loader既可以做到代码转成ES5了

module.exports = {
    module: {
        rules: [
            {
                test:/\.js$/,
                use: 'babel-loader',
                include: /src/,          // 只转化src目录下的js
                exclude: /node_modules/  // 排除掉node_modules,优化打包速度
            }
        ]
    }
}

在我们每次npm run build的时候都会在dist目录下创建很多打好的包,如果积累过多可能也会混乱

所以应该在每次打包之前将dist目录下的文件都清空,然后再把打好包的文件放进去

这里提供一个clean-webpack-plugin插件

npm i clean-webpack-plugin -D
// 注意:此处必须使用解构赋值法,否则会报错
let { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    plugins: [
        // 打包前先清空
        // new CleanWebpackPluin({...}) 只接受对象
        // CleanWebpackPluin的具体使用参考
        // https://github.com/johnagan/clean-webpack-plugin#options-and-defaults-optional
        new CleanWebpackPlugin()  
    ]
}

静态资源拷贝

当我们需要拷贝一些静态资源的话,我们需要用到copy-webpack-plugin插件

npm i copy-webpack-plugin -D
let CopyWebpackPlugin= require('copy-webpack-plugin');

module.exports = {
    plugins: [
        // CopyWebpackPlugin的具体使用参考
        // https://www.webpackjs.com/plugins/copy-webpack-plugin/
        new CopyWebpackPlugin([{
      		from: '**/*.json',
      		// 为空或删除该属性表示拷贝至output的根目录下,例如dist/
      		to: ''
    	}], {
    		// context用来解释上面from中的**,相当于'src/*.json'
      		context: 'src/'
    	})
    	// 也可这样使用
    	//new CopyWebpackPlugin([{
      	//	from: 'src/*.json',
      	//	// 为空或删除该属性表示拷贝至output的根目录下,例如dist/
      	//	to: ''
    	//}])
    ]
}

启动静态服务器

启动一个静态服务器,默认会自动刷新,就是说你对html,css,js文件做了修改并保存后,浏览器会默认刷新一次展现修改后的效果

正常情况下我们都是在开发环境中开发项目,所以之前配置的脚本"dev"可以派上用场了,在执行npm run dev命令后,会启动静态服务器,我们访问localhost:3000端口就可以看到开发的页面内容了

如果devServer里open设为true后,会自动打开浏览器

module.exports = {
    devServer: {
        contentBase: './dist',
        host: 'localhost',      // 默认是localhost
        port: 3000,             // 端口
        open: true,             // 自动打开浏览器
        hot: true               // 开启热更新
    }
}

当然在npm run dev命令下,打包的文件存在于内存中,并不会产生在dist目录下

总结

以上内容只是介绍了Webpack的一些常用功能,Webpack非常的强大,对于工程化项目来说。想深入了解的话可以去砍官网文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值