Optimization Configuration
2023.06.21 17:06:47 +0800 粗看了一遍optimization 配置的文档 (opens in a new tab),简要摘录一些比较关键的配置
2023.11.20 19:27:54 +0800 开始看中文版的文档 (opens in a new tab),翻译的还不错,推荐
optimization.chunkIds
控制 webpack 打包 chunk 产物的命名算法
- 在 production 模式下默认是
deterministic
,能够保证每次构建是幂等的结果(deterministic by content),方便长期的缓存(文件名) named
更可读的 id(其他模式)natural
数值,使用顺序
moduleIds 配置也一样
optimization.concatenateModules
concatenateModules 是 webpack 安全的将一些模块提升组合到一个单独模块(why?)production 模式下开启
optimization.emitOnErrors
在产物编译发生异常的时候依旧输出产物
optimization.mergeDuplicateChunks
顾名思义的一个重复 chunk 的优化,默认开启
optimization.realContentHash
产物输出后名称增加内容 hash,默认开启
optimization.removeAvailableModules
告诉 webpack 移除已经被导入使用过的模块,production 下默认开启
会降低 webpack 的性能
optimization.sideEffects
识别依赖 npm 包 package.json
中的 sideEffects
字段,默认开启
optimization.splitChunks
大背景是 webpack4 从
CommonsChunkPlugin
切到了SplitChunksPlugin
(这篇官方文章 (opens in a new tab)),并且引入了ChunkGroup
这个新对象,简单来说有几个原因:
从老的 chunk 图模型(chunk graph)的缺点
- parent-child 关系(一个 chunk 所属一个 chunk)
- 如果一个 chunk 有 parents,则可以认为这个 chunk load 完,至少一个 parent 是加载了的,这样在优化阶段就可以利用这个假设信息,做到(比如):如果 chunk 中的某个模块在所有的 parents 都可用,那就可以将这个模块直接在 chunk 中移除
- 从一个 entrypoint 开始加载的一系列 chunk 会并行的加载
- CommonsChunkPlugin 在处理将模块提升到 chunk 之后,会错误的将其作为 parent chunk(会影响后续的优化)(其实这里还并不是很理解说的是什么情况,总之意思就是很难去表达一个 chunk 到底是如何 split 的)
新的对象
ChunkGroup
包含很多 chunk,相当于是用一个集合去包含 chunk,不存在父子层级关系,当然加载的时候从一个 entrypoint 开始指向一个 chunkgroup,其中 chunks 也是并行加载
- 所以现在 chunk 的拆分就很好去表达了:一个 chunk 拆分出来之后,所有所需的 chunkgroup 只要去把他的引用加入到自己的 group 即可!
- 推出了
SplitChunksPlugin
内置在 webpack 中做优化举几个例子:
Vendors:
`chunk-a`: react, react-dom, some components `chunk-b`: react, react-dom, some other components `chunk-c`: angular, some components `chunk-d`: angular, some other components webpack would automatically create two vendors chunks, with the following result: `vendors~chunk-a~chunk-b`: react, react-dom `vendors~chunk-c~chunk-d`: angular `chunk-a` to `chunk-d`: Only the components
还有 vendors overlap/share 等情况见文章。。
将代码拆分成块,按需使用。
对于动态引入的模块,可以采用 split chunk 的策略,在用到的时候才 import 模块代码。
Since webpack v4, the CommonsChunkPlugin
was removed in favor of optimization.splitChunks
.
SplitChunksPlugin
默认的配置已经足够用了(out of box),会按照下面的条件自动拆分 chunk
- New chunk can be shared OR modules are from the
node_modules
folder - New chunk would be bigger than 20kb (before min+gz)(文章中写的是 30kb 可能后面改过)
- Maximum number of parallel requests when loading chunks on demand would be lower or equal to 30
- Maximum number of parallel requests at initial page load would be lower or equal to 30
整体配置:
module.exports = {
//...
optimization: {
splitChunks: {
chunks: "async",
minSize: 20000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
接下来看下具体的字段是如何影响最终 chunk 生产的
splitChunks.automaticNameDelimiter
默认值是 ~
,控制 chunk 名称比如 vendor~main.js
splitChunks.chunks
indicates which chunks will be selected for optimization.
Providing all
can be particularly powerful, because it means that chunks can be shared even between async and non-async chunks.
value: all
, async
, and initial
splitChunks.cacheGroups
reuseExistingChunk