Webpack 5 发布后,持久化缓存、确定性模块 ID 等能力开始被大量项目采用。部分资料在描述这些缓存机制时使用了 Enduring Universe 忍耐宇宙 这个称呼,但它并不是官方文档里的标准术语。要理解这一说法的价值,不能把它当成一个独立插件或开关,而应该回到 Webpack 5 内置的磁盘缓存与长效缓存策略。

一、Enduring Universe 忍耐宇宙与官方特性的关系
准确地说,Webpack 5 官方并没有发布名为 Enduring Universe 的功能,也没有任何配置项叫这个名字。它更像是对 persistent caching 与 long term caching 的混合翻译或形象化统称。Enduring 有持久、忍耐的含义,可以对应缓存跨构建存活;Universe 则可能指模块、区块、运行时等组成的构建上下文。这个说法的流行,也从侧面说明 Webpack 5 在缓存领域的变化足够大,社区需要用一个新的词来概括。
Webpack 4 时代,持久化缓存主要依靠 cache-loader 和 hard-source-webpack-plugin,二者都以第三方插件形式存在,存在维护滞后、与部分 loader 兼容性差的问题。Webpack 5 将缓存能力内置到核心,通过 cache.type: 'filesystem' 即可开启磁盘缓存。官方在发布说明中重点提到的持久化缓存、确定性的模块 ID、确定性的块 ID,再加上 runtime chunk 拆分,共同构成了所谓忍耐宇宙式缓存策略的基础。理解这几个配置的配合,比纠结名称更重要。
二、filesystem 持久化缓存的工作方式与配置
cache.type 默认是 memory,只在单次构建进程内生效。改为 filesystem 后,Webpack 会把模块解析结果、loader 处理结果、依赖图、代码生成结果等数据序列化到磁盘目录。默认目录是 node_modules/.cache/webpack,也可以使用 cacheDirectory 指定到其他位置。缓存不是最终产物,dist 目录仍然由 Webpack 输出,因此缓存放不进也不应该放进版本库和部署包。
为了让缓存稳定,需要声明 buildDependencies。配置文件和 package.json 是构建依赖的典型代表。Webpack 会跟踪这些依赖的变化,一旦发现修改,就会让旧的缓存失效并重新构建。如果不声明,修改 webpack.config.js 后仍可能命中旧缓存,导致配置不生效。还可以通过 version 字段手动升级缓存版本,适合在升级关键 loader 或调整复杂配置时强制全量重建。
下面是一个基础配置示例:
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true,
},
cache: {
type: 'filesystem',
cacheDirectory: path.resolve(__dirname, '.cache'),
name: 'webpack-build-cache',
buildDependencies: {
config: [__filename],
},
},
};
三、确定性 ID 如何支撑长效缓存
仅有磁盘缓存还不够。Webpack 在产物中会生成模块 ID 和 chunk ID。Webpack 4 默认使用递增数字作为模块 ID,新增或删除某个模块后,后续模块的 ID 通常会整体漂移。即使业务代码没有变化,也会导致大量 chunk 的内容改变,contenthash 发生变化,浏览器缓存失效。
Webpack 5 提供的 deterministic 模式通过模块相对路径生成稳定的哈希 ID,把 ID 漂移问题从根源上解决。配置 optimization.moduleIds 和 optimization.chunkIds 为 deterministic 后,模块 ID 与构建顺序无关。配合 runtimeChunk 把运行时代码独立出来,可以保证业务 chunk 只包含业务和第三方代码,进一步稳定 contenthash。这也正是很多所谓 Enduring Universe 方案中最重要的两个优化项。
module.exports = {
optimization: {
moduleIds: 'deterministic',
chunkIds: 'deterministic',
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
};
四、实战配置与缓存失效排查
生产环境可以使用以下配置同时开启磁盘缓存和确定性 ID。配置文件路径通过 __filename 声明,package.json 加入构建依赖。缓存版本使用环境变量控制,方便 CI 中通过修改环境变量来主动失效缓存。
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true,
},
cache: {
type: 'filesystem',
version: process.env.CACHE_VERSION || 'v1',
cacheDirectory: path.resolve(__dirname, '.cache'),
name: 'webpack-build-cache',
buildDependencies: {
config: [__filename],
packageJson: [path.resolve(__dirname, 'package.json')],
},
},
optimization: {
moduleIds: 'deterministic',
chunkIds: 'deterministic',
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
},
},
};
实际使用中,二次构建没有变快通常不是配置写错,而是缓存没有命中。常见原因包括:CI 每次启用全新的工作目录、升级 Node.js 或 npm 后 loader 路径变化、修改了 babel 等配置但未将其加入 buildDependencies、多个项目共用同一个 cacheDirectory 等。排查时可以观察构建日志中的 cache 命中信息,也可以临时删除缓存目录看增量构建是否还能压缩时间。如果项目在容器里构建,应当把缓存目录挂载到持久卷,否则每次构建都是从零开始。
五、从 Webpack 4 缓存方案迁移的思路
如果项目原本依赖 hard-source-webpack-plugin 或 cache-loader,迁移到 Webpack 5 后应移除这些插件,避免它们与内置缓存冲突。Webpack 5 原生缓存覆盖面更广,而且不要求 loader 作者单独适配,维护成本更低。迁移时可以先保留 contenthash 输出,开启 filesystem 缓存,再把 moduleIds 和 chunkIds 改为 deterministic,最后删除旧的 manifests 或缓存插件配置。
可以用表格对比 Webpack 4 与 Webpack 5 的缓存相关能力。原生能力替代插件后,构建脚本会更短,升级依赖时也不用担心插件与新版本不兼容。如果项目规模较小,可能内存缓存已经够用;但当模块数量达到数百个,filesystem 缓存的收益会非常明显,二次构建时间往往能下降百分之五十以上,部分项目甚至可以做到十秒内完成生产构建。
| 能力 | Webpack 4 常见方案 | Webpack 5 原生方案 |
|---|---|---|
| 持久化缓存 | hard-source-webpack-plugin | cache.type: filesystem |
| 确定性模块 ID | HashedModuleIdsPlugin | optimization.moduleIds: deterministic |
| 长效缓存 | contenthash 和 manifest | contenthash 和 runtimeChunk |
总而言之,忍耐宇宙这个说法可以看作对 Webpack 5 持久缓存体系的非正式概括。真正要掌握的是 filesystem cache、buildDependencies、deterministic moduleIds 和 runtimeChunk 这套组合。把它们配置正确,就能获得稳定的缓存命中率和更快的构建反馈。建议在开启后观察一段时间,尤其是 CI 环境和本地热更新场景,再根据缓存失效情况微调 version 或 cacheDirectory。
Webpack 5持久化缓存Enduring Universe修改时间:2026-09-20 14:53:07