一、准备阶段:配置与环境检查
读取配置优先级
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.x
4。
三、安装阶段:缓存与下载
缓存查询
每个包根据
name@version
生成唯一 Key,在缓存目录(npm config get cache
,通常为_cacache
)中查找14。若缓存命中且校验通过(通过
integrity
字段验证完整性)→ 直接解压到项目node_modules
。
远程下载
若缓存未命中 → 从 npm 仓库(或配置的镜像如淘宝源)下载包。
下载后:
校验完整性(SHA 摘要)。
存入缓存。
解压至
node_modules
14。
📦 四、收尾阶段:写入与清理
生成/更新
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
流程图