之前写的《webpack性能优化(0):webpack性能优化概况-优化构建速度》、《webpack性能优化(1):分隔/分包/异步加载+组件与路由懒加载》
如果使用vue-cli,默认生成的vendor.js文件会非常大。这个时候需要进行拆包。其实打包输出后,都可以用如下工具瞧瞧包依赖情况。
第二是通过 Chrome 的 Instrument converge 功能查看 js,css 的资源使用率:https://developers.google.com/web/tools/chrome-devtools/coverage
优化输出与分包,原来熟悉的配方 new webpack.optimize.CommonsChunkPlugin({}),现在可直接配置optimization项目
在研究splitChunks之前,我们必须先弄明白 module、chunk和bundle 这三个名词是什么意思:
代码分离是 webpack 中最引人注目的特性之一。此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。
有三种常用的代码分离方法:
其实我们一帮需要做的是optimization.splitChunks。以下是生产环境默认配置(webpack版本 4.29.5)
?splitChunks:?{
????hidePathInfo:?true,
????chunks:?'all',
????minSize:?30000,
????minChunks:?1,
????maxAsyncRequests:?5,
????automaticNameDelimiter:?'~',
????maxInitialRequests:?3,
????name:?true,
????cacheGroups:?{
????????default:?{
????????????reuseExistingChunk:?true,
????????????minChunks:?2,
????????????priority:?20
????????},
????????vendors:?{
????????????automaticNamePrefix:?'vendors',
????????????test:?/[\\\/]node_modules[\\\/]/,
????????????priority:?-10
????????}
????}}
splitChunks就算你什么配置都不做它也是生效的,源于webpack有一个默认配置,这也符合webpack4的开箱即用的特性。
我们需要在整个基础上进行优化,所以需要熟悉里面的配置
配置项也是蛮多,这里抽取一些重点说明,更加详细还是看文档。
maxInitialRequests是splitChunks里面比较难以理解的点之一,它表示允许入口并行加载的最大请求数,之所以有这个配置也是为了对拆分数量进行限制,不至于拆分出太多模块导致请求数量过多而得不偿失。
这里需要注意几点:
具体参考《理解webpack4.splitChunks之maxInitialRequests》
maxAsyncRequests和maxInitialRequests有相似之处,它俩都是用来限制拆分数量的。
这其中要注意以下几点:
具体参看《理解webpack4.splitChunks之maxAsyncRequests》
这个配置表示 split 前单个非按需导入的 module 的并行数的最低下限。
注:只对 import 或 require 直接引入的 module 有效。
简单来讲,假如 minChunks 设置为 n,那么某个 module 想要被拆分出去,那么它的共享次数(或者说并行请求次数必须 >= n):
但是,有个特例
我们注意到拆分出来的那个 bundle 包含了打印字符串的部分,那么如果入口点中仅仅包含了打印字符串的部分,没有引入 module,结果是怎样呢,结果就是打印的那部分代码被单独拆分出来了。所以当 minChunks 被设为 1 时,被拆分出来的某个 bundle 一定包含非引入模块代码,如果非引入模块代码存在的话,而当值设为大于 1 的数值时,则不会出现这种情况。
最后,还有一个点需要注意,minChunks 不能设为 0,其值为 >= 1 的正整数,不然为报错。
搞懂了minChunks的number属性,Infinity属性就很好理解了。Infinity是不会把任何依赖的模块提取出来打包公用。
minSize限制拆分包的最小值(达到这个值,就拆出新包)
maxSize限制每个拆分出来的包的最大文件体积(超过这个大小,再做包拆分
cacheGroups其实是splitChunks里面最核心的配置,一开始我还认为cacheGroups是可有可无的,这是完全错误的,splitChunks就是根据cacheGroups去拆分模块的,包括之前说的chunks属性和之后要介绍的种种属性其实都是对缓存组进行配置的。
缓存组可以继承重写SplitChunks中的任何属性;但是test、priority和ReuseExistingChunk只能在缓存组级别配置 . 也就是说真正起作用的是cacheGroups, SplitChunks中设置属性仅仅是基本配置而已。
CacheGroups之外设置的约束条件比如说默认配置里面的chunks、minSize、minChunks等等都会作用于cacheGroups,除了test, priority and reuseExistingChunk,这三个是只能定义在cacheGroup这一层的。 因为默认的minChunks=1,这个属性会作用于所有的cacheGroups,但是cacheGroups也可以将上面的所有属性都重新定义,就会覆盖外面的默认属性,比如default这个缓存组就设置了minChunks=2,他会覆盖掉默认值1。
splitChunks默认有两个缓存组:vender(webpack5 默认为defaultVendors)和default,
优化持久化缓存的, runtime 指的是 webpack 的运行环境(具体作用就是模块解析, 加载) 和 模块信息清单,?
模块信息清单在每次有模块变更(hash 变更)时都会变更, 所以我们想把这部分代码单独打包出来, 配合后端缓存策略, 这样就不会因为某个模块的变更导致包含模块信息的模块(通常会被包含在最后一个 bundle 中)缓存失效.
optimization.runtimeChunk 就是告诉 webpack 是否要把这部分单独打包出来.
形如import('abc').then(res=>{})这种异步加载的代码,在webpack中即为运行时代码。
设置runtimeChunk是将包含chunks 映射关系的 list单独从 app.js里提取出来,因为每一个 chunk 的 id 基本都是基于内容 hash 出来的,所以每次改动都会影响它,如果不将它提取出来的话,等于app.js每次都会改变。缓存就失效了。设置runtimeChunk之后,webpack就会生成一个个runtime~xxx.js的文件。 然后每次更改所谓的运行时代码文件时,打包构建时app.js的hash值是不会改变的。如果每次项目更新都会更改app.js的hash值,那么用户端浏览器每次都需要重新加载变化的app.js,如果项目大切优化分包没做好的话会导致第一次加载很耗时,导致用户体验变差。 现在设置了runtimeChunk,就解决了这样的问题。所以这样做的目的是避免文件的频繁变更导致浏览器缓存失效,所以其是更好的利用缓存。提升用户体验。
runtimeChunk作用是为了线上更新版本时,充分利用浏览器缓存,使用户感知的影响到最低。
具体参看《webpack之optimization.runtimeChunk作用》
下面是一个参考配置:
//?当我们运行项目并且打包的时候,会发现chunk-vendors.js这个文件非常大,那是因为webpack将所有的依赖全都压缩到了这个文件里面,这时我们可以将其拆分,将所有的依赖都打包成单独的js。
config.optimization?=?{
??mergeDuplicateChunks:?true,?//?合并相同的?chunk
??//?runtimeChunk:?'manifest',
??//?runtimeChunk:?'single',
??splitChunks:?{
????chunks:?'async',//表示将选择哪些块进行优化。提供字符的有效值为all、async和initial,默认是仅对异步加载的块进行分割。
????minSize:?100?*?1024,//模块大于minSize时才会被分割出来。默认100k
????maxSize:?0,//生成的块的最大大小,如果超过了这个限制,大块会被拆分成多个小块。
????minChunks:?1,//拆分前必须共享模块的最小块数。
????maxAsyncRequests:?5,//按需加载时并行请求的最大数目。
????maxInitialRequests:?3,//入口点的最大并行请求数
????automaticNameDelimiter:?'~',//默认情况下,webpack将使用块的来源和名称(例如vendors~main.js)生成名称。此选项允许您指定要用于生成的名称的分隔符。
????automaticNameMaxLength:?30,//允许为SplitChunksPlugin生成的块名称的最大长度
????name:?true,
????cacheGroups:?{
??????elementUI:?{
????????priority:?20,
????????name:?'element-ui',
????????test:?/element-ui/,
????????reuseExistingChunk:?true
??????},
??????vendor:?{
????????name:?`chunk-vendors`,
????????test:?/[\\/]node_modules[\\/]/,//控制此缓存组选择的模块。省略它将选择所有模块。它可以匹配绝对模块资源路径或块名称。匹配块名称时,将选择块中的所有模块。
????????minChunks:?1,
????????//?maxInitialRequests:?12,
????????maxAsyncRequests:?5,
????????minSize:?100?*?1024,
????????maxSize:?5?*?1000?*?1024,
????????priority:?-10//一个模块可以属于多个缓存组,模块出现在优先级最高的缓存组中
??????},
??????common:?{
????????name:?`chunk-common`,
????????minChunks:?2,
????????priority:?-20,
????????chunks:?'initial',
????????reuseExistingChunk:?true//如果当前块包含已经从主包中分离出来的模块,那么该模块将被重用,而不是生成新的模块
??????}
????}
??}
}
如果有更好的办法,请赐教。
启用CDN,提高缓存效率与打包分析,具体参看《webpack性能优化(0):webpack性能优化概况-优化构建速度?》
分组修改方法如下:
const?Role?=?()?=>?import(/*?webpackChunkName:?"group-role"?*/'./views/system/Role.vue')
const?AddRole?=?()?=>?import(/*?webpackChunkName:?"group-role"?*/'./views/system/AddRole.vue')
const?EditRole?=?()?=>?import(/*?webpackChunkName:?"group-role"?*/'./views/system/EditRole.vue')
const?User?=?()?=>?import(/*?webpackChunkName:?"group-user"?*/'./views/system/User.vue')
const?AddUser?=?()?=>?import(/*?webpackChunkName:?"group-user"?*/'./views/system/AddUser.vue')
const?EditUser?=?()?=>?import(/*?webpackChunkName:?"group-user"?*/'./views/system/EditUser.vue')
const?UserAllotRole?=?()?=>?import(/*?webpackChunkName:?"group-user"?*/'./views/system/UserAllotRole.vue')
每个功能模块打包后的 js 大概有十几kb,文件数量也大大减少。
这些限制告诉webpack如何/何时拆分块,它们仅定义了限制值,在限制值以上,警告在控制台中显示,仅此而已。
entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
performance:?{
????maxEntrypointSize:?512000,
????maxAssetSize:?512000
}
参考文章:
webpack4 之 splitChunks.minChunks https://zhuanlan.zhihu.com/p/110175375
理解webpack4.splitChunks https://www.cnblogs.com/kwzm/p/10314438.html
vuecli3项目中webpack4配置(三)代码分割 https://juejin.im/post/6844903879046332424
转载本站文章《webpack性能优化(2):splitChunks用法详解》, 请注明出处:https://www.zhoulujun.cn/html/tools/Bundler/webpackTheory/8554.html
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。