Webpack 5 带来了一项被称为 Fact 事实缓存的能力,它把编译器在构建过程中产生的大量中间事实(如文件依赖图、模块解析结果、哈希值)直接固化到本地存储中。与以往每次启动都从零开始扫描目录不同,Fact 缓存让二次构建只需比对关键事实是否变化,从而跳过昂贵的计算步骤。这项机制建立在内容寻址与弱一致性校验之上,是 Webpack 持久化缓存的核心组成。

Fact 缓存的基本原理与存储结构
Fact 事实缓存的本质是一层介于文件系统与编译主流程之间的元数据层。当 Webpack 首次构建时,它会记录每个模块的解析路径、loader 执行结果、ast 抽象语法树摘要以及文件内容的 hash。这些信息被序列化为二进制或 json 结构,写入由 cache.cacheDirectory 指定的目录中。下一次启动,编译器优先读取这些事实,仅当源文件或配置发生实质变更才重新生成。
底层存储采用了分片设计,以避免单文件过大。默认情况下,内存缓存使用 Map 结构,而磁盘缓存则按内容的 hash 前缀散列到不同子目录。这样的设计让数万模块的项目也能保持较低的索引开销。同时,Webpack 5 使用 inode 与 mtime 的联合校验,防止仅修改时间被误判为内容变化,也比单纯靠时间戳的旧方案更可靠。
值得注意的是,Fact 缓存并不等同于把打包产物缓存起来。它缓存的是“事实”而不是“文件”。例如某个模块是否被 tree-shaking 掉、它依赖了哪些全局变量,这些推导结果都会被记录。因此即便最终输出的 bundle 因入口变化而不同,大量底层事实仍可跨构建复用,这是其提速明显的原因。
如何在项目中开启并配置 Fact 缓存
要在 Webpack 5 中启用 Fact 缓存,只需在配置对象中设置 cache 属性并声明类型为 filesystem。下面是一个最小可用配置,展示了关键字段的含义。其中 buildDependencies 用于声明配置文件的依赖,当这些文件变动时缓存会自动失效。
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
cache: {
type: 'filesystem',
cacheDirectory: path.resolve(__dirname, 'node_modules/.cache/webpack'),
buildDependencies: {
config: [__filename]
},
name: 'fact-demo-cache',
version: '1.0'
},
module: {
rules: [
{
test: /.js$/,
use: 'babel-loader'
}
]
}
};
上述配置中,version 字段非常关键。当团队升级了 babel 插件或调整了压缩参数,应当修改该值,否则旧事实可能误导编译器。此外,cacheDirectory 建议放在已被 gitignore 的路径中,避免缓存文件被提交到仓库。对于 monorepo,可为每个子包设定独立的 name 以防冲突。
在 CI 环境中,Fact 缓存同样有效。可以将 cacheDirectory 挂载到持久卷,使流水线第二次运行直接命中本地事实。不过要注意,不同操作系统的换行符差异可能导致 hash 不一致,此时应统一在 Linux 环境下生成缓存,或借助 resolve.fullySpecified 等选项降低环境敏感度。
Fact 缓存与传统缓存方案的对比及避坑
在 Webpack 4 时代,开发者常使用 cache-loader 或 hard-source-webpack-plugin 来加速。前者把 loader 结果缓存在内存或磁盘,后者劫持了编译器内部状态。Fact 缓存则是官方一等公民,不再需要第三方插件,且与 splitChunks、module-federation 等新特性天然兼容。下表列出了三者的主要区别。
| 方案 | 缓存层级 | 配置复杂度 | 多进程安全 |
|---|---|---|---|
| cache-loader | loader 结果 | 中 | 否 |
| hard-source | 模块级快照 | 高 | 有限 |
| Fact 缓存 | 编译事实 | 低 | 是 |
实践中一个常见误区是认为开启 Fact 缓存就不需要关心 watch 模式下的内存占用。实际上,文件系统缓存只负责跨进程复用,单次运行仍会在内存维护事实表。若项目极其庞大,可配合 cache.maxMemorySize 限制常驻对象,防止 Node 进程溢出。另一个坑是符号链接:若源码通过软链引入,需设置 resolve.symlinks 为 false,否则事实中的真实路径与逻辑路径错配,缓存会频繁失效。
从架构角度看,Fact 缓存将“计算”与“IO 校验”解耦,使构建系统更接近增量编译器的形态。团队在迁移 Webpack 5 时,应把缓存目录纳入构建基线的考量,而不是视作临时产物。当配合 parallel-webpack 做分片构建时,各分片写入同一 cacheDirectory 也不会相互覆盖,因为其写入键基于内容 hash 而非执行顺序,这也是官方方案优于民间插件的地方。
Webpack_5Fact_cache构建性能修改时间:2026-08-14 07:45:14