webpack4.0(三):codeSplitting
代码分离是 webpack 中最引人注目的特性之一。此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。
当我们在做项目的时候,都会引入一些第三方的库来帮助我们开发,例如:lodash、underscore等等,但是这些库在我们打包的时候,会被默认打包到bundle.js中,极大的增加了js的体积,如下图:
直接把我们的js体积提升到了2.4M,这时我们需要将其从main.js中分割出来,减小main.js的体积。
常见的有三种方式进行代码分割:
- 在entry手动的配置代码分割。
- 使用
SplitChunksPlugin
进行公共代码提取和分割。 - 动态导入。
entry手动分割
entry: {
index:'./index.js',
math:'./math.js'
},
执行打包之后,会被打包成不同的文件。
缺点:
- 如果不同的模块中引入有重复的模块,那么重复的模块就会被多次打包。
- 不够灵活,不能将核心逻辑进行动态的拆分。
SplitChunksPlugin
SplitChunksPlugin
插件可以将相同的模块提取到一起,并且还可以将我们使用的第三方插件单独提取出来,优化打包之后的bundle.js的体积。
具体使用:具体配置请查看官方文档。
optimization: {
splitChunks: {
chunks: "all",//进行代码分割的时候,all:针对所有的导入 async:只针对异步导入 initial:针对同步代码导入。
minSize: 30000,//设置最小阀值,只有大于该阀值,才会进行代码分割。
minChunks: 1,//在分割模块之前共享一个模块的最小块数(设置代码最少被引用次数)
maxAsyncRequests: 5,//按需加载时的最大并行请求数 超过就不会在做代码分割打包
maxInitialRequests: 3,//一个入口点的最大并行请求数 超过就不会做代码分割
automaticNameDelimiter: '~',//打包生成之后,默认情况下,webpack将使用块的来源和名称来生成名称,比如vendor ~main.js。
name: true,//使得cacheGroups中打包生成的文件名称
cacheGroups: {//缓存组 打包分组
vendors: {//配置同步导入
test: /[\\/]node_modules[\\/]/,//只有node_module中的才会进入
priority: -10,//值越大 优先级越高
filename: 'vendors.js'
},
default: {
// minChunks: 2,
priority: 0,
reuseExistingChunk: true,// 如果模块已经被打包了,在此遇到的时候 直接忽略,直接使用以打包好的模块。
filename:'default.js'
}
}
}
}
动态导入
动态导入有两种方式:
- 使用ECMAScript提案的import()语法
- 使用webpack特定的语法:require.ensure()
第一种方式:使用webpackChunkName
function getComponent(){
return import(/* webpackChunkName:"lodash" */ "lodash").then(({ default:_ }) => {
let div = document.createElement('div');
div.innerHTML = _.join(['hello','world','lodash']);
return div;
})
};
getComponent().then((ele) => {
document.body.appendChild(ele)
})
打包之后,会在dist目录下生成一个vendors~lodash.js
文件,表示它是vendors下面的一个文件。之所以前面会带一个vendors,这是因为cacheGroup有一个默认配置,如果想要去除,将vendors和default配置为false即可。
由于 import()
会返回一个 promise,因此它可以和 async
函数一起使用。但是,需要使用像 Babel 这样的预处理器和Syntax Dynamic Import Babel Plugin。