npm、pnpm、yarn 对比与常用命令速查
TL;DR
npm 安装时按 npm-shrinkwrap.json、package-lock.json、yarn.lock 的顺序决定依赖版本;pnpm 把依赖存入内容寻址存储,同一版本跨项目共享,只有差异文件才新增;yarn 在 yarn.lock 满足 package.json 时按锁定版本安装且不检查新版本。三者安装入口命令都是 install,但保存依赖的写法不同:npm 用 -D 等标志,yarn 用 yarn add --dev。CI 场景下 yarn 建议加 --frozen-lockfile。
核心对比表
| 项目或要点 | 值或说明 | 注意事项 |
|---|---|---|
| npm 锁文件优先级 | npm-shrinkwrap.json > package-lock.json > yarn.lock | 按此顺序决定依赖安装 |
| npm 默认保存位置 | dependencies | 加 -D 存 devDependencies,--save-peer 存 peerDependencies,-O 存 optionalDependencies |
| npm 精确版本 | -E 或 --save-exact | 默认使用 semver 范围操作符 |
| npm 生产安装 | --production 或 NODE_ENV=production | 跳过 devDependencies;--production=false 可强制全装 |
| npm 别名安装 | <alias>@npm:<name> | 仅作用于本项目,不改写传递依赖 |
| pnpm 存储方式 | 内容寻址存储,硬链接或写时复制 | 文件系统不支持时默认复制 |
| pnpm node_modules | 默认非扁平,符号链接只放直接依赖 | 工具不兼容符号链接时可设 nodeLinker=hoisted |
| pnpm 安装三阶段 | 依赖解析、目录结构计算、链接依赖 | 各包就绪即进入下一阶段,不互相等待 |
| yarn 无命令行为 | 直接运行 yarn 等同 yarn install | 透传所给标志 |
| yarn 锁定文件行为 | yarn.lock 满足 package.json 时按锁定版本安装 | 不检查更新版本 |
| yarn 冻结安装 | --frozen-lockfile | 不生成锁文件,需要更新时失败 |
| yarn 单版本约束 | --flat | 首次运行提示为多版本依赖选一个版本,写入 resolutions 字段 |
| yarn 审计 | --audit | 与 npm 不同,yarn 仅在请求时审计 |
安装与依赖管理细节
npm:锁文件优先级与保存标志
在包目录中不带参数运行 npm install,会把 package.json 中 dependencies 列出的模块装到本地 node_modules。添加依赖时默认写入 dependencies,可用 -D、--save-peer、-O、--no-save 改变保存位置,-E 保存精确版本。安装文件夹时,若文件夹在项目根内会安装其依赖并可能提升;在根外则只创建符号链接,想按注册表包方式安装内容需加 --install-links。
pnpm:磁盘与安装速度
pnpm 把依赖存入内容寻址存储:同一依赖被 100 个项目使用时,磁盘上不再有 100 份副本;若新版本只改动 100 个文件中的 1 个,pnpm update 只向存储新增 1 个文件。安装分依赖解析、目录结构计算、链接依赖三阶段,每个包就绪即推进,不必等全部包完成。默认 node_modules 非扁平,只把直接依赖符号链接到根目录。
yarn:可复现安装与常用标志
yarn 用 yarn add 和 yarn add --dev 替代 npm 的 --save 与 --save-dev。CI 中需要可复现依赖时传 --frozen-lockfile;--check-files 校验 node_modules 中已装文件未被删除;--force 重新获取所有包;--ignore-scripts 不执行 package.json 及其依赖中定义的脚本;--modules-folder <path> 指定 node_modules 的替代位置。
# npm:安装并保存为开发依赖,锁定精确版本
npm install node-tap --save-dev --save-exact
# npm:按别名安装同一包的两个版本
npm install jquery2@npm:jquery@2 jquery3@npm:jquery@3
# pnpm:安装全部依赖(默认非扁平 node_modules)
pnpm install
# pnpm:工具不兼容符号链接时改用扁平结构
pnpm install --config.nodeLinker=hoisted
# yarn:CI 中可复现安装
yarn install --frozen-lockfile
# yarn:为多版本依赖选定单一版本
yarn install --flat常见问题
npm install 会读取 yarn.lock 吗?
会,但优先级最低。npm 依次按 npm-shrinkwrap.json、package-lock.json、yarn.lock 的顺序决定依赖安装。
pnpm 为什么能节省磁盘空间?
因为依赖存放在内容寻址存储中,安装时通过硬链接或写时复制从单一位置取文件,同一版本可跨项目共享。
yarn install 在什么情况下会更新 yarn.lock?
yarn.lock 缺失,或不足以满足 package.json 中列出的依赖时,yarn 会查找满足约束的最新版本并写入 yarn.lock。
如何让 yarn 在锁文件需要更新时直接失败?
使用 yarn install --frozen-lockfile,它不生成 yarn.lock,需要更新时失败。
pnpm 的 node_modules 结构与 npm 有何不同?
npm 和 Yarn Classic 会把包提升到模块目录根部;pnpm 默认用符号链接只把直接依赖放入根目录,需要扁平结构时可设 nodeLinker 为 hoisted。
来源
- https://docs.npmjs.com/cli/v10/commands/npm-install(访问日期:2026-11-06)
- https://pnpm.io/motivation(访问日期:2026-11-06)
- https://classic.yarnpkg.com/lang/en/docs/cli/install/(访问日期:2026-11-06)