从 webpack4 开始,用 SplitChunksPlugin 插件替换了 CommonsChunkPlugin 插件。 相对于 CommonsChunkPlugin ,SplitChunksPlugin 的使用更加方便和清晰。javascript
SplitChunksPlugin 是 webpack4 内置的开箱即用的代码块分离插件,webpack4 会根据你配置好 optimization.splitChunks 规则,进行代码分割,打包成不一样的代码块。这样的好处在于避免代码重复引用,减小代码体积,按需加载,从而使浏览器资源加载速度快,而且减小服务器的压力和带宽。html
SplitChunksPlugin 文档:www.webpackjs.com/plugins/spl…java
initial
、async
和 all
属性优先级 minSize > maxSize > maxAsyncRequests > maxInitialRequestwebpack
这里重要介绍一下 chunks 的三个属性 initial
、async
和 all
。git
具体能够参考这篇文章: Webpack 4 Mysterious SplitChunks Plugingithub
经过 html-webpack-plugin 自动生成 index.htmlweb
npm install -D html-webpack-plugin
npm install -D webpack // html-webpack-plugin 依赖于 webpack
复制代码
// `--` 表明目录, `-` 表明文件
--demo08
--src
-app1.js
-app2.js
-module1.js
-module2.js
-module3.js
-index.html
-webpack.config.js
复制代码
src/module1.jsnpm
export const module1 = 'module1';
复制代码
src/module2.js浏览器
export const module2 = 'module2';
复制代码
src/module3.js缓存
export const module3 = 'module3';
复制代码
src/app1.js
import { 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.js
import { 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);
复制代码
webpack.config.js
const path = require("path");
module.exports = {
mode: 'production' || 'development',
entry: {
app1: "./src/app1.js",
app2: "./src/app2.js"
},
output: {
publicPath: __dirname + "/dist/", // 打包后资源文件的引用会基于此路径
path: path.resolve(__dirname, "dist"), // 打包后的输出目录
filename: "[name].bundle.js",
chunkFilename: "[name].chunk.js"
},
optimization: {
// runtimeChunk: "single", // 使用single模式,能够避免每个包都包含webpack的运行文件
splitChunks: {
cacheGroups: {
modules: {
chunks: "async" || "initial" || "all", // 三选一
minChunks: 1, // 代码块至少被引用的次数
maxInitialRequests: 3, // 设置最大的请求数
minSize: 0, // 设置每一个chunk最小的大小,只有大于这个值,才会被打包进一个chunk
automaticNameDelimiter: '~'
}
}
}
}
};
复制代码
(默认你已经安装了全局 webpack 以及 webpack-cli )
webpack
复制代码
打包成功后,结果输出在 demo08 的dist目录下
在浏览器运行 dist/index.html,打开控制台能够观察异步加载模块的效果。
这里能够经过修改以上参数(好比 chunks
, minChunks
, minSize
)的值来查看不一样的输出结果。
如上 webpack.config.js 配置文件,设置 minSize
为 0
,以及 minChunks
为 1
以确保知足一个新块的条件。
chunks
为 async
时webpack只对异步加载的模块进行分离,因此输出结果为:
app1.bundle.js
app2.bundle.js
modules~module3.chunk.js
复制代码
(注意以上例子中有两个入口文件 app1.js app2.js)
app1.js相关:
app1.bundle.js ( app1 主模块,而且包含 module1.js 和 module2.js)
modules~module3.chunk.js
复制代码
app2.js相关:
app2.bundle.js ( app2 主模块,而且包含 module1.js、module2.js 和 module3.js)
复制代码
chunks
为 initial
时webpack对全部模块进行分离,若是一个模块既被异步引用,也被同部引用,那么会生成两个包,因此输出结果为:
app1.bundle.js
app2.bundle.js
module3.chunk.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2.chunk.js
复制代码
app1.js相关:
app1.bundle.js (app1主模块)
module3.chunk.js (包含 module3.js 异步加载模块)
modules~app1.chunk.js (包含app1独有的模块: 这里暂时没有)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
复制代码
app2.js相关:
app2.bundle.js (app2主模块)
modules~app2.chunk.js (包含app2独有的模块: 这里是module3.js)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
复制代码
chunks
为 all
时webpack对全部模块进行分离,若是一个模块既被异步引用,也被同部引用,那么只会生成一个共享包,因此输出结果为:
app1.bundle.js
app2.bundle.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2~module3.chunk.js
复制代码
app1.js相关:
app1.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相关:
app2.bundle.js ( app2 主模块)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
modules~app2~module3.chunk.js (包含 module3.js )
复制代码
不知你注意到没有,以上打包结果中,app1 的主模块(app1.bundle.js)和app2的主模块(app2.bundle.js)的文件名包含的是 bundle,而其余模块包含的是 chunk。
bundle 代表该代码块包含有 webpack 运行时 的代码。而 chunk 则没有。 那你可能会问,这样 app1.bundle.js 和 app2.bundle.js 就包含了一样的 webpack 运行时代码,能够把这份 webpack 运行时的代码单独分离出来做为一个单独的块吗? 答案是能够的。
在 webpack.config.js 配置文件中添加如下属性便可:
runtimeChunk: "single"
复制代码
这样在以上 chunks 为 all 的示例中,输出的结果为:
app1.chunk.js
app2.chunk.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2~module3.chunk.js
runtime.bundle.js ( webpack 运行时模块)
复制代码
demo 代码地址: github.com/SimpleCodeC…
仓库代码地址(及目录): github.com/SimpleCodeC…
参考文档: