提取页面公共资源
1.1 使用 externals+cdn
相比于 webpack进阶用法实践2 的 ****source-map 的结果的包的大小,小太多了;
1.2 使用 SplitChunksPlugin
SplitChunksPlugin | webpack 中文文档
1.2.1
1.2.2
1.2.3
1.2.4
默认情况只会影响按需加载模块,所以所有内容全部被打包到一起了。
1.2.5 有模块动态导入
这里 lodash 使用动态导入,打包结果中可以看到 lodash 被单独打包了,因为默认情况下异步模块会被单独打包。
1.2.6 react 按需加载
打包结果分析:生成了三个 JS 文件,index.js Hello.js 和lodash。
Hello.js 是异步引入的,单独打包,因为默认情况下 webpack 会对异步模块进行打包优化。
lodash 符合提到默认的 4 个条件,所以 lodash 也被单独打包了。
1.2.7 lodash 按需加载
我们调整下 lodash 的引入,只引入 sum 模块。
可以看到此时就两个文件,因为 lodash/sum 的文件大小小于 20kb,不会被单独打包。
import {sum} from 'lodash-es'; 同理也是打印俩文件;
1.2.8 共享模块打包
除了 node_modules 满足条件会被单独打包,共享模块也会,我们看下面例子:
为啥共享模块和第三方库是分开打包的,是和 webpack 的默认配置有关,后面我们就可以看到默认配置。
1.2.9 初始和异步模块的公共库
相比于1.2.8,加了两行,可以看到lodash打包到初始块文件里了,异步模块和初始块都有的第三方库,会被打包在初始模块中。原因也很简单,Hello.js和World.js 加载前肯定会加载 index 模块,index 模块中有了 lodash,Hello.js和World.js 就直接可以使用 index 模块中的 lodash 了。讲完了 webpack 默认情况下对打包块的优化,接下来看 splitChunks 配置项。
1.2.10 配置项
默认配置
webpack 5 splitChunks 默认配置如下,上面提到的默认情况下打包的条件(按需加载 + 满足 4 个默认打包条件)在下方配置中就可以体现。
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,
},
},
},
},
};
-
chunks: 表示哪些代码需要优化,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为 async
-
minSize: 表示在压缩前的最小模块大小,默认为 20000Bytes.
-
minChunks: 表示被引用次数,默认为 1
-
maxAsyncRequests: 按需加载时候最大的并行请求数,默认为 30
-
maxInitialRequests: 一个入口最大的并行请求数,默认为 30
-
enforceSizeThreshold:强制执行拆分的体积阈值
-
cacheGroups: 缓存组。缓存组的属性除上面所有属性外,还有 test, priority, reuseExistingChunk
- test: 用于控制哪些模块被这个缓存组匹配到
- priority: 缓存组打包的先后优先级
- reuseExistingChunk: 如果当前代码块包含的模块已经有了,就不在产生一个新的代码块
- 自定义打包块的默认优先级是 0,所有优先处理自定义打包。
1.2.11 提取第三方库
最后看下之前 CommonsChunkPlugin 常用的分离部分第三方库功能。
上面已经提到了设置 chunks: initial || all 都可以提取出第三方库。但是它是把所有第三库提取出来,所以我们在只提取 react 和 react-dom 的情况下,需要自定义一个 cacheGroup。
splitChunks: {
chunks: 'all',
cacheGroups: {
react: {
name: 'react',
test: /[\/]node_modules[\/](react|react-dom)[\/]/,
}
}
}
可以看到我们新增了一个缓存组,只匹配 react 和 react-dom,所以达到了之前 CommonsChunkPlugin 的功能。
1.2.12 optimization.runtimeChunk
最后提一下 runtimeChunk,通过optimization.runtimeChunk: true选项,webpack 会添加一个只包含运行时 (runtime) 额外代码块到每一个入口。(译注:这个需要看场景使用,会导致每个入口都加载多一份运行时代码)
1.3 总结
webpack5 默认情况下只对异步模块做打包优化,额外的打包必须满足 4 个条件(webpack 的默认配置,可修改)。根据需求可调整为只对初始模块做打包优化,或者初始和异步模块一起优化。同时可配置自己的打包规则。
简而言之:chunks 控制打包作用范围,其他控制打包规则。
webpack5 的 splitChunks 功能是比较强大的,不过推荐还是使用默认模式,或者提取一下第三方库。