webpack4利用代码分割优化打包

背景

Webpack 4引入了SplitChunksPlugin插件来取代之前的CommonsChunksPlugin插件。代码分割是将一个文件分成多个文件,如果进行了合理的分割,浏览器的缓存利用率将会提供,对性能有极大的提升。通常我们在以下几个方面做代码分割:

  1. 为 Vendor(三方的库或者公共的基础组件) 单独打包,vendor基本不会有什么变换,缓存能带来极大提升。
  2. 为不同入口的公共业务代码打包。
  3. 异步加载的代码通常也可以单独打一个包。
  4. 为 Manifest (Webpack 的 Runtime 代码)单独打包。

    默认规则

    Webpack4会基于内置规则自动拆分代码。内置规则有:

  5. 新 bundle 被两个及以上模块引用,或者来自 node_modules
  6. 压缩之前新 bundle 大于 30kb
  7. 异步加载并发加载的 bundle 数不能大于 5 个
  8. 初始加载的 bundle 数不能大于 3 个
    基本上只要是大于30kb的公共包,webpack都会自动分割。

自定义需求

Webpack 4 的 optimization.splitChunks API用于自定义配置代码分割。

配置项

module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {}
}
}
}

  • chunks: 表示哪些代码需要优化,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为async
  • minSize: 表示在压缩前的最小模块大小,默认为30000
  • maxSize:表示抽取出来的文件在压缩前的最大大小,默认为 0,表示不限制最大大小;
  • minChunks: 表示被引用次数,默认为1
  • maxAsyncRequests: 按需加载时候最大的并行请求数,默认为5
  • maxInitialRequests: 一个入口最大的并行请求数,默认为3
  • automaticNameDelimiter: 命名连接符
  • name:抽取出来文件的名字,默认为 true,表示自动生成文件名
  • cacheGroups: 缓存组。缓存组的属性除上面所有属性外,还有test, priority, reuseExistingChunk

    • test: 用于控制哪些模块被这个缓存组匹配到
    • priority: 缓存组打包的先后优先级
    • reuseExistingChunk: 如果当前代码块包含的模块已经有了,就不在产生一个新的代码块

我们的重点在cacheGroups, 缓存组会继承splitChunks的配置,但是test、priorty和reuseExistingChunk只能用于配置缓存组。

chunks的取值是有initial、async、 all。initial, all模式会将所有来自node_modules的模块分配到一个叫vendors的缓存组;所有重复引用至少两次的代码,会被分配到default的缓存组。initial模式下会分开优化打包异步和非异步模块。而all会把异步和非异步同时进行优化打包。也就是说moduleA在indexA中异步引入,indexB中同步引入,initial下moduleA会出现在两个打包块中,而all只会出现一个。_

常见优化场景—分离三方库示列

optimization: {
runtimeChunk: process.env.NODE_ENV === 'production' ? { name: 'manifest' } : false,
splitChunks: {
automaticNameDelimiter: '--',
cacheGroups: {
vendors: {
name: 'vendors',
chunks: 'initial',
test: /[\/]node_modules[\/]/,
priority: 2
},
vue: {
name: 'vue-common',
test: (module) => {
return /vue|axios/g.test(module.context)
},
chunks: 'initial',
priority: 10
},
'<%= options['ui - framework'] %>': {
name: '<%= options['ui- framework'] %>',
test: module => /<%= options['ui-framework'] %>/g.test(module.context),
chunks: 'initial',
priority: 10
},
echarts: {
name: 'echarts',
test: module => /echarts/g.test(module.context),
chunks: 'initial',
priority: 10
}
}
}

Last modification:July 6, 2021
如果觉得我的文章对你有用,请随意赞赏