一、准备阶段:配置与环境检查
-
读取配置优先级
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
流程图
