一、准备阶段:配置与环境检查
-
读取配置优先级
npm install首先加载多层级的配置(优先级从高到低)4:-
项目级
.npmrc -
用户级
.npmrc(如~/.npmrc) -
全局
npmrc -
npm 内置默认配置
可通过
npm config ls -l查看所有配置。
-
-
检查锁定文件
-
若存在
package-lock.json:对比其与
package.json的依赖版本是否一致:-
✅ 一致 → 直接使用锁定文件中的依赖树。
-
❌ 不一致 → 按 npm 版本策略处理(如 npm 5.x+ 会以
package.json为准更新锁定文件)4。
-
-
若无锁定文件 → 根据
package.json递归构建依赖树4。
-
二、依赖解析阶段:构建依赖树与扁平化
-
依赖树生成
npm 解析
package.json中的dependencies和devDependencies,递归收集所有子依赖,形成树状结构4。 -
扁平化处理(Deduplication)
-
将依赖按相同版本提升到
node_modules根目录 (如react只安装一份)。 -
若版本冲突(如 A 依赖
lodash@^4.0,B 依赖lodash@^3.0)→ 在 B 的node_modules下单独安装lodash@3.x4。
-
三、安装阶段:缓存与下载
-
缓存查询
-
每个包根据
name@version生成唯一 Key,在缓存目录(npm config get cache,通常为_cacache)中查找14。 -
若缓存命中且校验通过(通过
integrity字段验证完整性)→ 直接解压到项目node_modules。
-
-
远程下载
-
若缓存未命中 → 从 npm 仓库(或配置的镜像如淘宝源)下载包。
-
下载后:
-
校验完整性(SHA 摘要)。
-
存入缓存。
-
解压至
node_modules14。
-
-
📦 四、收尾阶段:写入与清理
-
生成/更新
package-lock.json记录所有依赖的精确版本、下载地址、依赖树结构,确保后续安装一致4。
-
运行生命周期脚本
按顺序执行包中定义的脚本(如
preinstall、postinstall),某些包可能在此阶段编译原生模块。
⚠️ 五、常见问题与解决
| 问题场景 | 原因与解决方案 |
|---|---|
| 安装后报错"模块找不到" | 缓存损坏或网络中断导致包不完整 → 清除缓存重试: npm cache clean --force + 删除 node_modules 重装14。 |
node_modules 无法删除 |
文件被进程占用 → 关闭 IDE(如 VSCode)或使用命令行强制删除12。 |
| 安全漏洞警告 | 运行 npm audit 查看漏洞详情 → 使用 npm audit fix 自动修复,或手动升级受影响包7。 |
| Linux 系统权限灾难 | ⚠️ 历史教训:npm v5.7.0 在 sudo 下运行时递归修改系统目录所有权(如 /etc),导致系统崩溃 → 永远避免用 sudo 执行 npm!356。 |
💎 关键机制总结
-
缓存优化:显著加速重复安装,但需注意缓存污染问题4。
-
锁定文件作用 :确保跨环境安装一致性,务必提交到版本控制。
-
安全审计 :
npm audit主动检测依赖链漏洞(如react-native-validator-form案例中的 Karma 漏洞)7
流程图
