1. npm 是什么
npm(Node Package Manager)是 Node.js 的官方包管理器,用于安装、管理和发布 JavaScript 模块。它的核心是一个 包注册表(registry),默认是 https://registry.npmjs.org。
2. npm install 的作用
当你在项目中执行:
npm install
npm 会根据 package.json 或你指定的包名,下载并安装对应的依赖。
3. 安装原理拆解
3.1 读取配置
- npm 会读取当前项目的
package.json(如果是第一次安装则没有)。 - 还会读取全局配置文件(
~/.npmrc)、项目配置文件(./.npmrc)等。
3.2 解析依赖 ( DFS )
- 解析
package.json中的dependencies、devDependencies、peerDependencies等字段。 - 生成一个 依赖树(dependency tree),包括所有间接依赖。
- npm 在解析依赖关系、生成依赖树时,使用的是 深度优先搜索 算法。
为什么是 DFS
- 依赖嵌套的自然结构:JavaScript 项目的依赖关系通常是嵌套的。例如,
A依赖B,B又依赖C。DFS 会先沿着一条路径(A → B → C)一直往下探索,直到没有更多依赖,然后再回溯处理其他分支。
3.3 去重 & 扁平化
- npm 会尽量让相同版本的包只安装一次,减少重复文件。
- 这一过程称为 dependency hoisting(依赖提升)。
3.4 查找包信息
-
npm 会去 registry(默认是 npmjs.org)查询包的元数据,包括:
- 最新版本
- 版本号(semver)
- tarball 下载地址
3.5 下载 & 解压
- 从 registry 下载包的 tarball(压缩包)。
- 解压到本地的
node_modules目录。
3.6 执行脚本
- 某些包在安装时会运行
preinstall、install、postinstall等脚本。 - 这些脚本通常用于编译二进制文件(比如 node-gyp)或生成配置文件。
3.7 更新锁文件
- npm 会生成或更新
package-lock.json(npm 5+),确保后续安装使用相同版本的依赖。
4. 依赖解析流程示意图
package.json
↓
解析 dependencies/devDependencies
↓
生成依赖树
↓
去重 & 扁平化
↓
查询 registry 元数据
↓
下载 tarball
↓
解压到 node_modules
↓
执行安装脚本
↓
更新 package-lock.json
5. 与其他工具的区别
- npm:官方包管理器,速度相对较慢,但兼容性好。
- yarn:Facebook 开发,速度快,有缓存机制。
- pnpm:速度最快,使用硬链接节省磁盘空间。
✅ 总结:npm install 的原理就是读取配置 → 解析依赖 → 查询包信息 → 下载解压 → 执行脚本 → 更新锁文件的过程。它保证项目的依赖版本一致,并且能在不同环境中复现安装结果。