在前端团队优化 CI/CD 流水线时,很多人会尝试「缓存 node_modules」来加快依赖安装。但实际用下来,大家经常发现——加新依赖或者依赖有变动时,安装依然很慢,且维护和管理成本极高。这是因为 node_modules 缓存存在一些技术陷阱和效率瓶颈。
node_modules 缓存:看似高效,实则暗藏风险
1. node_modules 不是增量结构
- Yarn/NPM/PNPM 的
node_modules跟package.json/ lockfile 紧密相关,并不是可增量合并的目录。 - 一旦依赖树有变化,之前缓存下来的 node_modules 结构就会和当前项目声明(package.json/yarn.lock)不一致。
- 包管理器因此会做校验、删除残留老依赖,安装新包、修复依赖树。实际效果往往接近“全量 reinstall”,老 cache 利用不高。
2. 慢的根源不仅仅在 network I/O
- 你加包或升级依赖后,安装流程往往还需:
- 校验旧 cache 和 lockfile 差异
- 下载新包,删除无用包,解压并重写依赖
- 重新执行所有 postinstall、build 脚本(如 node-gyp、canvas、sharp 等会重新编译 C++ 插件)
- /** 对于大型 monorepo,解包、I/O、脚本构建非常耗时,哪怕 CI 服务器配有 SSD 也不总比本地快多少 */
科学的依赖缓存方案
1. 推荐缓存“store”,而非 node_modules
- Yarn v1:
~/.cache/yarn - pnpm:
.pnpm-store或~/.pnpm-store - npm:
~/.npm - 只要 store 命中,包管理器能极快增量恢复依赖,把 node_modules 重建成本降到最低,还能利用 cache 最大化加速。
2. 更优体验与维护
- store 缓存具备良好的增量性,依赖变动时只需下载新增部分。
- 配合 lockfile 做 cache key,保障构建环境一致性,最大化利用 cache。
- node_modules 每次 clean install,消除残留幽灵依赖的风险。
总结
node_modules cache 并非最佳实践,依赖一变就失效、维护负担大、提速有限。推荐用包管理器自带的 store 缓存方案,实现安全、高效、一致的 CI/CD 依赖管理。
让缓存提速真正简单可控,让构建和调试更加安心。如果你还在纠结 node_modules cache,不如现在就切换到 store 缓存吧!