在CI流水线中应缓存node_modules目录和.npm元数据,使用npm ci配合lock文件哈希作为缓存key,可将依赖安装从数分钟降至秒级,确保一致性与离线可靠性。

在 CI 流水线中缓存 npm 依赖,核心目标是避免每次构建都重复下载、解压和安装 node_modules,把耗时从几分钟降到秒级。关键不在于“要不要缓存”,而在于“缓存什么、怎么命中、何时失效”。
缓存 node_modules 目录(最直接有效)
多数场景下,直接缓存 node_modules 是最快见效的方式,尤其适合前端项目或依赖变动不频繁的仓库。
- GitLab CI 示例:
cache:key: ${CI_COMMIT_REF_SLUG}paths:- node_modules/
配合npm ci --prefer-offline使用,缓存命中后依赖安装可从 4+ 分钟降至 0.8 分钟左右 - GitHub Actions 示例:
- name: Cache node modulesuses: actions/cache@v3with:path: node_moduleskey: ${{ runner.os }}-node-modules-${{ hashFiles('**/package-lock.json') }}
使用package-lock.json哈希作为 key,确保依赖变更时自动失效,避免脏缓存
同时缓存 npm 元数据(提升离线可靠性)
仅缓存 node_modules 在某些情况下不够稳定——比如 Runner 换机器、Node 版本升级,或 node_modules 被意外清理。此时缓存 npm 自身的元数据(.npm 目录)能提供双重保障。
- GitLab CI 中可叠加缓存:
paths:- node_modules/- .npm/
并在脚本中显式指定缓存路径:npm ci --cache .npm --prefer-offline - 该方式让 npm 优先从本地
.npm查找包文件(.tgz),跳过网络请求,即使 registry 不可用也能完成安装
用 npm ci 替代 npm install(强制一致性)
CI 环境不是开发环境,不需要生成或更新 package-lock.json。用 npm ci 是更安全、更高效的选择。
立即学习“Java免费学习笔记(深入)”;
-
npm ci会严格按package-lock.json安装,不读package.json的 ^ 或 ~ 版本范围,杜绝隐式升级 - 它自动删除旧
node_modules,避免残留模块引发冲突 - 跳过
preinstall/postinstall钩子(除非显式启用),减少非必要执行时间 - 配合缓存使用时,真正“只装变动部分”,而不是全量重装
注意缓存失效边界(避免误用)
缓存不是万能的,错误的 key 策略会让它形同虚设。
- 不要用固定字符串做 key(如
node-modules-cache),否则永远命中,无法响应依赖更新 - 推荐 key 组合:分支名 + lock 文件哈希(
${CI_COMMIT_REF_SLUG}-${HASH}),兼顾隔离性与准确性 - 当
package-lock.json变更时,新 key 自动生成,旧缓存自然淘汰;无需手动清理 - 私有 registry 或内网镜像源可进一步缩短首次下载时间,但缓存仍是第一道加速屏障


















