关于 webpack 编译缓存

594 阅读3分钟

我正在参加「掘金·启航计划」

在 webpack 中如何缩短构建时间,我相信大部分人选择的都是缓存编译结果,毕竟这个效果最明显,而在编译缓存的路上使用最多的应该是以下这 3 个工具/配置,下面我们来看看这三者有什么不同以及该如何使用?

cache-loader

www.webpackjs.com/loaders/cac…

作用

cache-loader 可以在磁盘中缓存 loaders 的结果。需要注意的是,由于保存和读取这些缓存文件会有一些时间开销,所以请只对性能开销较大的 loader 使用此 loader,并且请在其他 loader 前使用。

使用

module.exports = {
    module: {
        rules: [
            {
                test: /.tsx?$/,
                exclude: [/node_modules/],
                use: [
                    'cache-loader',
                    'ts-loader',
                ],
            },
        ]
    }
}

hard-source-webpack-plugin

github.com/mzgoddard/h…

作用

HardSourceWebpackPlugin 为模块提供了中间缓存步骤。需要注意的是需要在二次构建时才能看到这个插件的效果,首次构建耗时不会有明显的差异,但二次构建就会十分快速了。

使用

module.exports = {
    module: {
        rules: [
            {
                plugins: [
                    new HardSourceWebpackPlugin(),
                ],
            },
        ]
    }
}

cache

webpack.docschina.org/configurati…

作用

缓存生成的 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 耗时非常长,去掉这个插件后,编译耗时上有了明显的效果👍

相关文档

segmentfault.com/a/119000004…

zhuanlan.zhihu.com/p/110995118

github.com/webpack-con…