我正在参加「掘金·启航计划」
在 webpack 中如何缩短构建时间,我相信大部分人选择的都是缓存编译结果,毕竟这个效果最明显,而在编译缓存的路上使用最多的应该是以下这 3 个工具/配置,下面我们来看看这三者有什么不同以及该如何使用?
cache-loader
作用
cache-loader 可以在磁盘中缓存 loaders 的结果。需要注意的是,由于保存和读取这些缓存文件会有一些时间开销,所以请只对性能开销较大的 loader 使用此 loader,并且请在其他 loader 前使用。
使用
module.exports = {
module: {
rules: [
{
test: /.tsx?$/,
exclude: [/node_modules/],
use: [
'cache-loader',
'ts-loader',
],
},
]
}
}
hard-source-webpack-plugin
作用
HardSourceWebpackPlugin 为模块提供了中间缓存步骤。需要注意的是需要在二次构建时才能看到这个插件的效果,首次构建耗时不会有明显的差异,但二次构建就会十分快速了。
使用
module.exports = {
module: {
rules: [
{
plugins: [
new HardSourceWebpackPlugin(),
],
},
]
}
}
cache
作用
缓存生成的 webpack 模块和 chunk,来改善构建速度。和 HardSourceWebpackPlugin 作用类似。需要注意仅在 webpack 5 中可以使用。
使用
module.exports = {
module: {
cache: {
type: 'filesystem',
allowCollectingMemory: true,
cacheDirectory: path.resolve(__dirname, '../.temp_cache'),
},
}
}
怎么选择
webpack 4
cache-loader + hard-source-webpack-plugin
效果(分别为首次构建和二次构建):
webpack 5
cache
持久化缓存是 webpack 5 其中一个非常重要的特性。通过这个配置会将构建结果持久化的缓存在本地磁盘中,二次构建时将直接使用磁盘缓存的结果,跳过了构建过程中解析和构建等耗时过程,因此大大的提升了编译和构建效率。
通过新缓存系统的设计,整个构建过程变得更加高效和安全。在此之前,官方和社区中也有许多解决编译耗时长和提升编译效率的解决方案。例如,官方提供的 cache-loader 可以把前一个 loader 处理的结果缓存在磁盘中。在下次构建过程中,根据某些规则跳过紧接着的 loader 处理,而是使用缓存的内容。但是 cache-loader 只能复盘经过 loader 处理的文件内容,缓存的内容范围还是十分有限的,此外,cache-loader 在构建过程中缓存数据的过程是有额外开销的,这会影响到整个编译和构建的速度,因此推荐只在一些编译耗时长的 loader 中一起使用。并且,cache-loader 是通过比较文件的时间戳来进行缓存的,这种缓存失效策略并不安全。
其他
需要注意的是不管使用哪个工具,编译耗时的减少都是需要在二次编译时才能体现出来的,毕竟需要第一次运行来缓存相应的内容
关于减少本地编译耗时,我推荐个工具给大家,通过这个工具 speed-measure-webpack-plugin 可以看到当前项目使用到的 loader / plugin 耗时情况,知道问题出在哪里以后,就可以针对这个“始作俑者”进行优化或者替换;像我们组内的项目,通过这个插件分析下来发现 CaseSensitivePathsPlugin 耗时非常长,去掉这个插件后,编译耗时上有了明显的效果👍