webpack4实践笔记8 关于SplitChunksPlugin
本系列代码放在 github 上:
webpack4系列实践代码如果本系列实践教程对你有帮助,欢迎给个
github star
哦!
1.SplitChunksPlugin 介绍
从 webpack4 开始,用 SplitChunksPlugin 插件替换了 CommonsChunkPlugin 插件。
相对于 CommonsChunkPlugin ,SplitChunksPlugin 的使用更加方便和清晰。
SplitChunksPlugin 是 webpack4 内置的开箱即用的代码块分离插件,webpack4 会根据你配置好 optimization.splitChunks 规则,进行代码分割,打包成不同的代码块。这样的好处在于避免代码重复引用,减少代码体积,按需加载,从而使浏览器资源加载速度快,并且减少服务器的压力和带宽。
SplitChunksPlugin 文档:https://www.webpackjs.com/plugins/split-chunks-plugin/
2.splitChunks参数配置
- chunks (默认是async) :
initial
、async
和all
- minSize (默认是30000):新代码块最小体积(压缩之前),单位:字节(b)
- minChunks(默认是1):代码块至少被引用的次数
- maxInitialRequests (默认是3):入口处的最大并行请求数
- maxAsyncRequests (默认是5):按需加载时最大的并行请求数
- test (默认所有模块): 匹配需要处理的模块, 可以传的值类型: RegExp、String和Function
- automaticNameDelimiter (默认是’~’): 打包分隔符
- priority:缓存组打包的先后优先级
属性优先级 minSize > maxSize > maxAsyncRequests > maxInitialRequest
这里重要介绍一下 chunks 的三个属性 initial
、async
和 all
。
- async 只对对动态(异步)导入的模块进行分离
- initial 对所有模块进行分离,如果一个模块既被异步引用,也被同部引用,那么会生成两个包
- all 对所有模块进行分离,如果一个模块既被异步引用,也被同部引用,那么只会生成一个共享包
具体可以参考这篇文章: Webpack 4 Mysterious SplitChunks Plugin
3.安装相关依赖
通过 html-webpack-plugin 自动生成 index.html
1 | npm install -D html-webpack-plugin |
3.目录结构
1 | // `--` 代表目录, `-` 代表文件 |
src/module1.js1
export const module1 = 'module1';
src/module2.js1
export const module2 = 'module2';
src/module3.js1
export const module3 = 'module3';
src/app1.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import { module1 } from './module1';
import { module2 } from './module2';
// module1 module2 属于同步加载
console.log('app1: ', module1);
console.log('app1: ', module2);
// 通过require.ensure对module3.js进行加载调用(此写法在ts模式支持)
setTimeout(() => {
require.ensure(
[],
function () {
const module3 = require("./module3");
console.log('app1: ', module3.module3);
},
"module3"
);
}, 3000);
// // 异步加载的另一种写法(此写法在ts模式下不支持)
// setTimeout(() => {
// import(/* webpackChunkName: 'module3'*/ "./module3").then(function (module3) {
// console.log(module3.module3);
// });
// }, 3000);
src/app2.js1
2
3
4
5
6
7
8import { module1 } from './module1';
import { module2 } from './module2';
import { module3 } from './module3';
// module1 module2 module3 都属于同步加载(注意对比app1.js)
console.log('app2: ', module1);
console.log('app2: ', module2);
console.log('app2: ', module3);
4.编写 webpack 配置文件
webpack.config.js
1 | const path = require("path"); |
5.执行打包命令
(默认你已经安装了全局 webpack 以及 webpack-cli )
1 | webpack |
打包成功后,结果输出在 demo08 的dist目录下
在浏览器运行 dist/index.html,打开控制台可以观察异步加载模块的效果。
6.调试参数并验证输出结果
这里可以通过修改以上参数(比如 chunks
, minChunks
, minSize
)的值来查看不同的输出结果。
如上 webpack.config.js 配置文件,设置 minSize
为 0
,以及 minChunks
为 1
以确保满足一个新块的条件。
当设置 chunks
为 async
时
webpack只对异步加载的模块进行分离,所以输出结果为:1
2
3app1.bundle.js
app2.bundle.js
modules~module3.chunk.js
(注意以上例子中有两个入口文件 app1.js app2.js)
app1.js相关:1
2app1.bundle.js ( app1 主模块,并且包含 module1.js 和 module2.js)
modules~module3.chunk.js
app2.js相关:1
app2.bundle.js ( app2 主模块,并且包含 module1.js、module2.js 和 module3.js)
当设置 chunks
为 initial
时
webpack对所有模块进行分离,如果一个模块既被异步引用,也被同部引用,那么会生成两个包,所以输出结果为:1
2
3
4
5
6app1.bundle.js
app2.bundle.js
module3.chunk.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2.chunk.js
app1.js相关:1
2
3
4app1.bundle.js (app1主模块)
module3.chunk.js (包含 module3.js 异步加载模块)
modules~app1.chunk.js (包含app1独有的模块: 这里暂时没有)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
app2.js相关:1
2
3app2.bundle.js (app2主模块)
modules~app2.chunk.js (包含app2独有的模块: 这里是module3.js)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
当设置 chunks
为 all
时
webpack对所有模块进行分离,如果一个模块既被异步引用,也被同部引用,那么只会生成一个共享包,所以输出结果为:1
2
3
4
5app1.bundle.js
app2.bundle.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2~module3.chunk.js
app1.js相关:1
2
3
4app1.bundle.js ( app1 主模块)
modules~app1.chunk.js (包含 app1 独有的模块: 这里暂时没有)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
modules~app2~module3.chunk.js (包含 module3.js 模块,虽然名字没有 app1 ,但是可以通过测试知道,app1 是依赖此模块的,比如把此模块删除,然后在 index.html 中引入上面三个文件,查看控制台就能知道 app1 依赖此模块)
app2.js相关:1
2
3app2.bundle.js ( app2 主模块)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
modules~app2~module3.chunk.js (包含 module3.js )
7.bundle vs chunk
不知你注意到没有,以上打包结果中,app1 的主模块(app1.bundle.js)和app2的主模块(app2.bundle.js)的文件名包含的是 bundle,而其他模块包含的是 chunk。
bundle 表明该代码块包含有 webpack 运行时 的代码。而 chunk 则没有。
那你可能会问,这样 app1.bundle.js 和 app2.bundle.js 就包含了同样的 webpack 运行时代码,可以把这份 webpack 运行时的代码单独分离出来作为一个单独的块吗?
答案是可以的。
在 webpack.config.js 配置文件中添加以下属性即可:1
runtimeChunk: "single"
这样在以上 chunks 为 all 的示例中,输出的结果为:1
2
3
4
5
6app1.chunk.js
app2.chunk.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2~module3.chunk.js
runtime.bundle.js ( webpack 运行时模块)
8.源码地址
demo 代码地址: https://github.com/SimpleCodeCX/simple-webpack-demos/tree/master/demo08-SplitChunksPlugin
仓库代码地址(及目录): https://github.com/SimpleCodeCX/simple-webpack-demos
参考文档:
本文作者 : Simple
原文链接 : https://simplecodecx.github.io/blog/20190311/ca3604dd.html
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!