最初,chunks(以及内部导入的模块)是通过内部 webpack 图谱中的父子关系关联的。
CommonsChunkPlugin
曾被用来避免他们之间的重复依赖,但是不可能再做进一步的优化。——摘自 webpack
从 webpack v4 开始,移除了 CommonsChunkPlugin
,取而代之的是 optimization.splitChunks
。
而关于 optimization.splitChunks
中的chunks
,webpack 官方文档却没有很好的进行举例解释,只说明了 async
是默认的选项。
今天我们将来探讨一下这三者的区别。
单个入口文件情况
//app.js
import { findIndex } from "lodash";
if(some_condition_is_true){
import ("dayjs").then((e) => {console.log(e)})
}
findIndex([1, 2, 3]);
console.log("My app is running");
async模式
bundle.js: lodash + app.js
async: dayjs.js
initial模式
bundle.js: app.js
1.js: lodash
async: dayjs.js
all 模式
bundle.js: app.js
1.js: lodash
async: dayjs.js
结论
在单入口的情况下 initial 和 all 模式是一样的,async 只会单独打包异步部分。
多个入口文件情况
以以下两个为例:
//a.js
import { findIndex } from "lodash";
if(some_condition_is_true){
import ("dayjs").then((e) => {console.log(e)})
}
findIndex([1, 2, 3]);
console.log("My app is running");
//b.js
import { findIndex } from "lodash";
import dayjs from "dayjs";
dayjs(new Date());
findIndex([1, 2, 3]);
console.log("My app is running");
async模式
...
entry: {
a: "./src/a.js",
b: "./src/b.js",
},
optimization: {
splitChunks: {
chunks: "async"
}
}
...
最终输出结果:
b.bundle.js: lodash + dayjs + app.js
a.bundle.js: lodash + app.js
2.js: dayjs~a.js
由于 async 模式只会处理异步的方式,因此在 a、b bundle 中 lodash 都被打包进去了。
initial模式
...
entry: {
a: "./src/a.js",
b: "./src/b.js",
},
optimization: {
splitChunks: {
chunks: "initial"
}
}
...
最终输出结果:
b.bundle.js: dayjs + app.js
a.bundle.js: app.js
3.js: dayjs~a.js
vendorsab.js: lodash
initial 模式可以处理异步或者同步,但是没办处理同时存在异步和同步的情况,比如在 a 中异步引入了 dayjs,在b 中同步引入了 dayjs ,他没有办法处理。
all 模式
...
entry: {
a: "./src/a.js",
b: "./src/b.js",
},
optimization: {
splitChunks: {
chunks: "initial"
}
}
...
最终输出结果:
b.bundle.js: app.js
a.bundle.js: app.js
1.js: dayjs
vendorsab.js: lodash
all 模式可以同时处理异步或者同步,比如在 a 中异步引入了 dayjs,在b 中同步引入了 dayjs ,他也可以单独把 dayjs 提取出来作为复用。
结论
all 模式 yyds!!