Unix系统中rm -rf node_modules后执行npm i与npm ci是否存在区别
两种操作的核心差异
首先明确:两者只有在极其理想的极端场景下才会产出相同结果,底层运行逻辑完全不同,适用场景也有明确区分。
各自的底层执行逻辑
1. rm -rf node_modules && npm i 的运行流程
- 第一步仅物理删除本地已有的依赖目录,不会对lock文件做任何校验或修改
- 第二步执行
npm i时的核心逻辑:- 优先读取
package.json中声明的依赖版本范围 - 参考现有
package-lock.json的版本记录,但会自动拉取所有符合版本范围的最新发布版本(包括补丁、小版本更新) - 如果发现
package.json和现有lock文件不一致,或者拉取到了范围内的新版本,会直接自动更新package-lock.json - 整个版本选择是弹性的,没有强制对齐的要求
- 优先读取
2. 直接执行npm ci的运行流程
这个命令是npm 5.7版本后专门为可复现安装场景设计的,执行逻辑完全是刚性的:
- 前置强制校验:项目根目录必须存在
package-lock.json或npm-shrinkwrap.json,缺失直接报错退出 - 自动删除已有的
node_modules目录,完全不需要手动提前执行rm操作 - 100%严格按照lock文件中锁定的精确版本下载安装依赖,完全忽略
package.json中与lock不一致的版本范围声明 - 一旦发现
package.json和package-lock.json的内容不匹配,直接终止安装,不会自动修改或更新任何lock文件 - 跳过了版本范围校验、lock更新等冗余步骤,安装速度通常比前一种组合快30%以上
常见认知误区
觉得两者结果一致的判断,仅在以下全部条件同时满足的极端场景下成立:
package.json和package-lock.json完全同步- 距离上次lock生成后,所有符合版本范围的依赖都没有发布任何新的补丁、小版本
- 本地没有配置任何自定义的npm registry代理、依赖镜像规则
实际开发、CI环境中几乎不会出现这种完全无版本变动的理想情况。
两种操作的适用场景优势
- 优先选
rm -rf node_modules && npm i的场景:- 本地开发时手动修改了
package.json的依赖配置,需要更新lock文件同步最新的符合要求的依赖版本 - 本地
node_modules被意外污染、文件损坏,需要重新安装依赖且允许版本在约定范围内浮动 - 项目早期还没生成稳定lock文件的开发阶段
- 本地开发时手动修改了
- 优先选
npm ci的场景:- CI/CD流水线中需要绝对可复现的构建结果,避免不同时间点构建出的依赖版本不一致
- 本地开发时需要和其他同事、测试/线上环境的依赖版本100%对齐,不需要更新lock文件
- 排查依赖版本相关的偶现bug时,排除版本浮动带来的干扰
内容的提问来源于stack exchange,提问作者Reikon
相关产品推荐
相关产品推荐

