Webpack 5 对缓存系统做了彻底重构,引入了基于文件的持久化缓存(Persistent Caching),这是版本升级中最受关注的特性之一。在 Webpack 4 时代,开发者需要依赖 cache-loader 或 hard-source-webpack-plugin 这类第三方方案来加速二次构建,而这些方案存在缓存失效判断不精准、升级后容易出问题等缺陷。Webpack 5 将缓存能力内置到核心中,通过文件快照与内容哈希实现精准的增量构建,官方数据显示二次构建速度平均可以提升 60% 到 80%,大型项目效果更加明显。本文将系统讲解这套缓存策略的原理、配置方法与实战技巧。
一、缓存类型与基本配置
Webpack 5 的缓存行为由顶层配置项 cache 控制,它支持三种取值。设置为 false 时完全禁用缓存,行为与旧版本一致;设置为 true 时启用内存缓存并使用默认配置;设置为对象形式时可以进行细粒度定制,其中 type 字段是最核心的选项,可选值为 memory 和 filesystem。
内存缓存只在当前进程生命周期内有效,进程退出后缓存即销毁,适合一次性构建任务。而文件系统缓存会把模块、chunk、resolve 结果等序列化后写入磁盘,下次启动时直接读取,这就是所谓的持久化缓存。对于日常开发和持续集成场景,filesystem 是毫无疑问的首选。
最基础的配置只需两行:
module.exports = {
cache: {
type: 'filesystem'
}
};配置完成后,第一次构建会正常执行并写入缓存,第二次构建时你会明显感受到速度飞跃。缓存文件默认存放在 node_modules/.cache/webpack 目录下,如果你想自定义位置,可以通过 cacheDirectory 选项指定一个绝对路径,例如把缓存放到独立的磁盘分区以获得更好的 IO 性能。
二、核心配置参数详解
仅仅开启文件缓存还不够,要保证缓存命中可靠,必须理解几个关键参数,否则可能出现代码改了但构建结果没更新的诡异问题。
第一个是 buildDependencies。它用来声明额外的缓存依赖,当这些文件变化时缓存会整体失效。最重要的用法是把 webpack 配置文件本身加入进来:
const path = require('path');
module.exports = {
cache: {
type: 'filesystem',
buildDependencies: {
// 配置文件变化时自动让缓存失效
config: [__filename]
}
}
};如果你的项目使用了自定义的 babel 配置、postcss 配置,或者封装了共享的构建函数,也应该把相关文件路径加入 config 数组,确保任何影响构建逻辑的文件变动都能触发缓存重建。
第二个是 version。它是一个字符串标识,webpack 会把它纳入缓存键的计算。当你手动修改了这个值,缓存就会失效。常见的用法是将环境变量注入其中,让不同环境使用独立的缓存空间:
cache: {
type: 'filesystem',
version: `${process.env.NODE_ENV}-v2`
}第三个是 snapshot 相关配置。webpack 通过文件快照来判断模块是否需要重新构建,其中 managedPaths 默认指向 node_modules,这些路径下的包采用时间戳加哈希的混合判断策略,而项目自身代码默认只用时间戳判断,性能开销更低。如果你的依赖目录做了软链接或者 monorepo 结构比较特殊,可能需要调整 immutablePaths 来声明完全不可变的路径。
三、性能优化与实战技巧
在冷启动场景下,webpack 需要从磁盘读取并反序列化缓存数据,这个过程是异步的。可以通过 idleTimeout 控制编译器空闲多久后开始把内存中的缓存写入磁盘,默认是 60 秒。开发时如果经常快速保存文件触发增量编译,适当调大这个值可以减少频繁的序列化操作:
cache: {
type: 'filesystem',
cacheDirectory: path.resolve(__dirname, '.webpack_cache'),
idleTimeout: 120000,
compression: 'gzip'
}上面配置中的 compression 选项值得关注。磁盘空间紧张的项目可以设置为 gzip 压缩缓存文件,能减少约一半的存储占用,代价是读写时多消耗一点 CPU。空间充裕时保持默认的 false 即可获得最快的读取速度。
在持续集成环境中使用持久化缓存也有讲究。由于 CI 机器往往是全新容器,可以配置 cache.load 为 false 只写入不读取,或者把缓存目录挂载为可持久化的卷,配合 CI 平台的缓存机制在多次流水线之间复用。多分支并行开发时,建议把分支名纳入 version 字段,避免不同分支的缓存互相污染导致构建产物异常。
排查缓存问题时,可以在启动命令加上 node node_modules/webpack/bin/webpack.js --json 查看输出统计中的缓存命中信息。如果发现缓存始终不生效,优先检查三点:webpack 版本是否变化、buildDependencies 中的文件是否被改动、node_modules 里的依赖是否发生了升级。确认命中后,大型项目的二次构建通常能从几十秒降到几秒,这对开发体验和 CI 效率的提升是实打实的。