代码分割Code Splitting
通常来讲,我们写项目的时候可以分为两部分,一部分是引用的类库,另一部分是我们写的业务逻辑代码。这两部分打包后会合并到一个js文件中。
这样方式的缺点是:
一、打包生成的main.js
可能会很大,首次访问时会慢
二、当页面业务逻辑发生变化时,又要加载全部的内容
解决方式:使用代码分割,将类库的代码打包成一个js文件,将业务逻辑代码打包成一个文件。
这种方式的优点:
一、分为两个js文件,文件体积较小,可以并行加载,提升加载速度
二、当业务逻辑代码发生变化时,只需要加载业务逻辑代码的js文件即可(用户浏览器有缓存)
方式一 手动分割
以lodash类库为例
lodash.js
import _ from 'lodash';
window._ = _;
webpack.config.js
entry: {
lodash: './src/lodash.js',
main: './src/index.js'
}
方式二 webpack
1、同步代码:配置optimization
optimization: {
splitChunks: {
chunks: 'all'
}
}
2、异步代码:无需配置,自动分割
npm install babel-plugin-dynamic-import-webpack --save-dev
.babelrc
{
presets: [
[
"@babel/preset-env", {
targets: {
chrome: "67",
},
useBuiltIns: 'usage'
}
]
],
plugins: ["dynamic-import-webpack"]
}
异步代码
function getComponent() {
return import('lodash').then(({ default: _ }) => {
var element = document.createElement('div');
element.innerHTML = _.join(['Dell', 'Lee'], '-');
return element;
})
}
getComponent().then(element => {
document.body.appendChild(element);
});
es7写法与懒加载
async function getComponent() {
const { default: _ } = await import(/* webpackChunkName:"lodash" */ 'lodash');
const element = document.createElement('div');
element.innerHTML = _.join(['Dell', 'Lee'], '-');
return element;
}
document.addEventListener('click', () =>{
getComponent().then(element => {
document.body.appendChild(element);
});
})
修改异步代码打包文件名
魔法注释:将异步打包的文件命名为lodash
import(/* webpackChunkName:"lodash" */ 'lodash');
之前的动态引入模块插件是非官方的,不支持这种语法,需要更换插件
npm install --save-dev @babel/plugin-syntax-dynamic-import
.babelrc
{
presets: [
[
"@babel/preset-env", {
targets: {
chrome: "67",
},
useBuiltIns: 'usage'
}
]
],
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}
SplitChunksPlugin 参数配置
对同步代码和异步代码分割都有作用
异步代码
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: false, // 不使用vendors,异步代码分割前缀不加'vendors~'
default: false
}
}
}
同步代码
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 类库是从node_modules中引入的话就进行代码分割
priority: -10,
filename: 'vendor.js', // 重命名分割文件
},
default: false
}
}
}
配置解析
optimization: {
splitChunks: {
chunks: 'async', // async 只对异步代码生效, all同步异步都生效, initial同步生效
minSize: 30000, // 体积大于30KB的模块才会代码分割
maxSize: 0, // 一般不需要,对大于一定体积的模块尝试进行再次分割
minChunks: 1, // 当一个模块至少被引用了几次后才做代码分割
maxAsyncRequests: 5, // 最多分割几个js文件,超出后后面的不会再进行分割
maxInitialRequests: 3, // 入口文件引入的库最多能分割成几个包
automaticNameDelimiter: '~', // 生成文件名字中间的连接符
automaticNameMaxLength: 30,
name: true, // 使cacheGroups中设置的文件名有效
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 从node_modules中引入的模块进行代码分割
priority: -10 // 优先级,同时满足vendors和default,使用优先级高的
},
default: {
// 没有设置test参数,所有的都符合
minChunks: 2,
priority: -20,
reuseExistingChunk: true // 如果引入的模块已经被打包,复用,不再打包
}
}
}
}
文档
babel-plugin-syntax-dynamic-import
split-chunks-plugin
网站导航
网站导航