webpack4中 splitChunks配置
虽然webpack5已经发布两年了,然而公司内部还有许多个项目仍然使用的是webpack4,最近一个小需求却导致打包结果发生了很大变化,于是重新研究了下splitChunks配置。
默认配置
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
automaticNameMaxLength: 30,
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
chunks: 'async'
代表仅对异步加载的chunk拆分
异步加载的chunk可以是通过
import('./module')
加载的路由组件,在没有做任何splitChunks的情况下每个路由组件最终都会成独立的chunk,也就是独立的js文件。和异步加载的chunk对应的是webpack entry 对应的文件生成的同步chunk。
name:true
true意味着根据chunk来生成名字。通过import()
生成的chunk没有chunkName,最后会根据chunks和分组的key来生成文件名字,比如:7.2a8e96d850daca1383cf.chunk.js
;
设置为false在实际的使用中没有发现影响;
设置为字符串,如果匹配到多个module,这些module最后会合并到一个文件;
使用函数的话,就可以根据模块来定制最后chunk的名字,一般来说没必要,为了容易调试的情况下可以如此做;
maxAsyncRequests字段
maxAsyncRequests用来配置按需加载异步chunk数量的最大值;
比如有的页面异步chunks的数量大于了maxAsyncRequests,导致其引用的原本应该拆分出来的多个npm包被合并到同一个文件中;
同样有些页面异步chunks没有大于maxAsyncRequests,引用的npm包分别拆分到独自文件中;
如果一个npm模块a被多个页面使用,有的页面的异步chunks大于maxAsyncRequests,有些小于maxAsyncRequests,这样就会出现这个a模块既被单独拆分成了一个js文件,又作为一个模块存在于另一个js文件中
所以合理设置maxAsyncRequests的大小对最终splitChunks的效果影响非常大,在实际工作中,甚至出现了因为maxAsyncRequests过小,一个2m大小的npm模块分散到使用它的16个chunk中,导致模块最后的bundle的总大小增加了一倍;
记录一个很有意思的例子:项目希望能够将npm包拆分成独立js,但是实际并没有,将项目中
resolve.mainFields:['main']
改为resolve.mainFields:['']
就可以了,猜测是因为许多npm包的main字段指向的是commonjs模块或者umd模块,模块无法被treeShaking优化,导致最终页面的异步chunk变多,于是许多npm模块没有拆分成独立成js文件。改成module
之后,一些第三方模块被treeShake掉, 满足了maxAsyncRequests,结果按照期望拆分了。
minSize:30000
用来限制拆分中模块的大小,大于这个值的模块才会参与到拆分中。这个30000值其实是有些小的,因为这是原始文件的大小,如果经过前端压缩和gzip
压缩之后,通过网络的传输会减小80%以上,所以可以适当调大一些。
cacheGroups.
在这里可以设置拆分chunk的规则,这里的key并不是生成的chunk文件的名字,而是作为规则的一种描述;
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
比如上面的意思是将node_modules下的模块拆分成独立的chunk,vendors(翻译:厂商、第三方)只是描述这个规则是为了拆分第三方库,因为没有定义这些第三方库的chunkName,结果由webpack根据自己来决定。
cacheGroups.{key}.enforce
刚开始使用splitChunk的时候,不知道是什么原因(后来才知道因为maxAsyncRequests的缘故),无法把第三方模块打包出来;这个时候使用enforce:true
之后就成功打包出来了,了解到这样配置可以无视minSize
, minChunks
, maxAsyncRequests
and maxInitialRequests的
配置,这才从maxAsyncRequests这里找到了原因。
所以在确定需要拆分但又受到那几个属性的限制的时候,使用exforce可以一步到位。