众所周知,webpack 进入第 4 个大版本已经有 2 个月的时间了,而且 webpack 团队升级更新的速度也是非常的惊人

在写下如下内容的时候 webpack 已经出到了 4.6 的版本了,剑指 5.0 应该是指日可待了,当然这些都是个人的臆想,并不代表任何意见

既然我们已经迎接了 webpack4 的到来了,那么就一起来使用一下,即使你没用过之前的版本,没关系,我们重新出发,将工作中常用到的配置写给大家来看

非友情提示:由于 webpack 使用起来并不能仅看代码就方便理解,所以有图有真相的才是正解,于是乎本文配图很多,真的是很多

首先,既来之,则安之

安装 webpack

  • 需要先在项目中 npm init 初始化一下,生成 package.json

  • 建议 node 版本安装到 8.2 以上

webpack4 中除了正常安装 webpack 之外,需要再单独安一个 webpack-cli

1
npm i webpack webpack-cli -D

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

0 配置了什么

webpack4 可以支持 0 配置打包,这里所说的 0 配置又是什么呢?当然在开发者眼中 0 配置的东西,那根本是无法用的,因为不够智能,那么我们就来看看做到了哪些 0 配置

在使用 webpack 进行打包的时候,默认情况下会将 src 下的入口文件 (index.js) 进行打包

node v8.2 版本以后都会有一个 npx
npx 会执行 bin 里的文件

1
2
npx webpack     // 不设置 mode 的情况下 打包出来的文件自动压缩
npx webpack –mode development // 设置 mode 为开发模式,打包后的文件不被压缩

当执行 npx webpack 命令的时候,webpack 会自动查找项目中 src 目录下的 index.js 文件,然后进行打包,生成一个 dist 目录并存在一个打包好的 main.js 文件
这些算是 0 配置的操作了,名字都是定义好的,不能变,想想也很鸡肋

webpack 的使用还是在我们的配置方面,下面就进入我们的常规操作环节

webpack 是基于 Node 的

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

1
2
3
4
5
6
7
8
module.exports = {
entry: ‘’, // 入口文件
output: {}, // 出口文件
module: {}, // 处理对应模块
plugins: [], // 对应的插件
devServer: {}, // 开发服务器配置
mode: ‘development’ // 模式配置
}

以上就是 webpack 的正常配置模块
★ 启动 devServer 需要安装一下 webpack-dev-server
npm i webpack-dev-server -D

按照项目的结构,我们就从 0 开始去写一下配置吧

// webpack.config.js

1
2
3
4
5
6
7
8
9
const path = require(‘path’);

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

上面就可以说是实现了最简单的 webpack 配置了,那接下来就打包一下看看

配置执行文件

工作当中我们打包编译的时候一般都执行 npm run dev 这样的命令,既然是通过 npm 执行的命令,我们就应该找到 package.json 里的执行脚本去配置一下命令,这里如下图所示

npm run build 就是我们打包后的文件,这是生产环境下,上线需要的文件

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

通过 npm run build 之后会生成一个 dist 目录文件夹,就和上面打包后的样子一样了
多入口文件
多个入口可以有两种实现方式进行打包

一种是没有关系的但是要打包到一起去的,可以写一个数组,实现多个文件打包
另一种就是每一个文件都单独打包成一个文件的
下面就来看看这两种方式的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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,用之前我们来安一下它

1
npm i html-webpack-plugin -D

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 串
})
]
}

通过上面的配置后,我们再 npm run build 打包看一下现在是个什么样子了

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

1
npm i style-loader css-loader -D

引入 less 文件的话,也需要安装对应的 loader

1
npm i less less-loader -D

下面我们来看一下如何配置 css 文件的解析
// index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import ‘./css/style.css’;   // 引入 css
import ‘./less/style.less’; // 引入 less

console.log(‘这里是打包文件入口 -index.js’);

// 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’}
]
/
}
]
}
}

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

拆分 CSS

// @next 表示可以支持 webpack4 版本的插件

1
npm i extract-text-webpack-plugin@next -D
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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: {
filaneme: ‘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 需要去解决的
不过既然大家都知道它,那就顺便也提一下吧

1
npm i mini-css-extract-plugin -D

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 还不支持此功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 正常写入的 less
let styleLess = new ExtractTextWebpackPlugin(‘css/style.css’);
// reset
let resetCss = new ExtractTextWebpackPlugin(‘css/reset.css’);

module.exports = {
module: {
rules: [
{
test: /.css$/,
use: resetCss.extract({
use: ‘css-loader’
})
},
{
test: /.less$/,
use: styleLess.extract({
use: ‘css-loader’
})
}
]
},
plugins: [
styleLess,
resetCss
]
}

通过这样操作后可以打包成两个不同的 css 文件,如下图

引用图片

处理图片方面,也需要 loader

1
npm i file-loader url-loader -D

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
module.exports = {
module: {
rules: [
{
test: /.css$/,
use: ExtractTextWebpackPlugin.extract({
use: ‘css-loader’,
publicPath: ‘../‘
})
},
{
test: /.(jpe?g|png|gif)$/,
use: [
{
loader: ‘url-loader’,
options: {
limit: 8192, // 小于 8k 的图片自动转成 base64 格式,并且不会存在实体图片
outputPath: ‘images/‘ // 图片打包后存放的目录
}
}
]
}
]
}
}

在 css 中指定了 publicPath 路径这样就可以根据相对路径引用到图片资源了.

页面 img 引用图片

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

1
npm i html-withimg-loader -D
1
2
3
4
5
6
7
8
9
10
module.exports = {
module: {
rules: [
{
test: /.(htm|html)$/,
use: ‘html-withimg-loader’
}
]
}
}

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

本文地址 //haozigan.com/2018-05/webpack4-0.html

#webpack

本文地址 https://laoona.com/post/bf6eb9ab.html