Appearance
npm、yarn、pnpm 分别是什么?它们之间有什么区别?在开发中怎么选择?这篇文章来展开说说。
分别是什么
npm (Node Package Manager)
| 项目 | 说明 |
|---|---|
| 出身 | Node.js 官方自带,2009 年发布 |
| 收购 | 2010 年被 npm Inc. 收购,2020 年被 GitHub 收购 |
| 地位 | Node.js 安装时默认捆绑,生态最成熟 |
| 特点 | 开箱即用,无需额外安装 |
Yarn (Yet Another Resource Negotiator)
| 项目 | 说明 |
|---|---|
| 出身 | Facebook(Meta)2016 年开源 |
| 定位 | npm 的替代方案,强调确定性、安全性和工作区支持 |
| 贡献 | 引入 lockfile、并行下载、离线缓存等概念 |
pnpm (Performant npm)
| 项目 | 说明 |
|---|---|
| 出身 | 2017 年由 Zoltan Kochan 创建 |
| 核心理念 | 内容寻址存储 + 硬链接 |
| 特点 | 安装极快、磁盘占用极小、严格的依赖隔离 |
核心对比
| 对比项 | npm | Yarn | pnpm |
|---|---|---|---|
| 安装速度 | 较慢(串行) | 快(并行+缓存) | 最快(仅创建链接) |
| 磁盘占用 | 较大 | 大 | 极小 |
| lockfile | package-lock.json | yarn.lock | pnpm-lock.yaml |
| 依赖提升 | ✅ 有 | ✅ 有 | ❌ 无(严格隔离) |
| 幽灵依赖 | ⚠️ 有 | ⚠️ 有 | ✅ 无 |
| Monorepo | workspaces(基础) | workspaces(完善) | workspaces(最佳) |
| Node_modules | 扁平结构 | 扁平结构 | 非扁平结构 |
依赖管理原理
┌─────────────────────────────────────────────────────────┐
│ 依赖结构对比 │
├─────────────────────────────────────────────────────────┤
│ │
│ npm/Yarn(扁平结构) │
│ ┌─────────────────────────────────┐ │
│ │ node_modules/ │ │
│ │ ├─ vue/ │ │
│ │ ├─ vue-router/ │ │
│ │ ├─ vuex/ │ │
│ │ └─ ...(所有依赖平铺) │ │
│ └─────────────────────────────────┘ │
│ ⚠️ 问题:幽灵依赖(可以直接引用未声明的包) │
│ │
│ pnpm(严格隔离) │
│ ┌─────────────────────────────────┐ │
│ │ .pnpm/ │ │
│ │ ├─ node_modules/ │ │
│ │ │ ├─ vue/ │ │
│ │ │ └─ vue-router/ │ │
│ │ └─ ...(硬链接) │ │
│ │ │ │
│ │ node_modules/ │ │
│ │ └─ .bin/ │ │
│ └─────────────────────────────────┘ │
│ ✅ 优势:必须显式声明依赖,无幽灵依赖 │
│ │
└─────────────────────────────────────────────────────────┘命令对照表
| 功能 | npm | Yarn | pnpm |
|---|---|---|---|
| 初始化项目 | npm init | yarn init | pnpm init |
| 安装依赖 | npm install | yarn install | pnpm install |
| 添加依赖 | npm add <pkg> | yarn add <pkg> | pnpm add <pkg> |
| 删除依赖 | npm remove <pkg> | yarn remove <pkg> | pnpm remove <pkg> |
| 全局安装 | npm i -g <pkg> | yarn global add <pkg> | pnpm add -g <pkg> |
| 更新依赖 | npm update | yarn upgrade | pnpm update |
| 清除缓存 | npm cache clean | yarn cache clean | pnpm store prune |
| 列出依赖 | npm list | yarn list | pnpm list |
| 运行脚本 | npm run <script> | yarn <script> | pnpm <script> |
| 锁定版本 | npm shrinkwrap | yarn --frozen-lockfile | pnpm import |
选择决策树
┌─────────────────────────────────────────────────────────┐
│ 包管理器选择决策树 │
├─────────────────────────────────────────────────────────┤
│ │
│ 你需要什么? │
│ │ │
│ ├─── 简单、通用、团队无共识 ──→ npm │
│ │ (开箱即用,文档最多) │
│ │ │
│ ├─── 已有 Yarn 习惯 ──→ Yarn │
│ │ (兼容性好,命令相似) │
│ │ │
│ └─── Monorepo / 大项目 ──→ pnpm │
│ │ │
│ ├─── 严格依赖隔离? ──→ ✅ pnpm │
│ │ │
│ └─── 磁盘空间紧张? ──→ ✅ pnpm │
│ │
└─────────────────────────────────────────────────────────┘场景推荐
| 场景 | 推荐 | 理由 |
|---|---|---|
| 新手入门 | npm | 开箱即用,文档最全 |
| 老项目维护 | 保持现有 | 不要轻易换 |
| 新公司/新团队 | pnpm | 现代、快速、规范 |
| Monorepo | pnpm | workspaces 支持最佳 |
| 大型前端项目 | pnpm | 磁盘占用小、依赖隔离 |
| 小项目/个人项目 | npm / pnpm | 都行,看习惯 |
pnpm 核心优势
1. 幽灵依赖问题
javascript
// package.json
{
"dependencies": {
"vue": "^3.0.0"
}
}npm/Yarn 问题:
javascript
// 可以直接引用(幽灵依赖)
import lodash from 'lodash' // ❌ 没有声明但能用pnpm 解决方案:
javascript
// 必须先声明
// pnpm add lodash
import lodash from 'lodash' // ✅ 显式声明后才能用2. 磁盘占用对比
| 项目 | 磁盘占用 | 说明 |
|---|---|---|
| npm | 1.5GB | 每个项目独立复制 |
| Yarn | 1.2GB | 有缓存但仍需复制 |
| pnpm | 200MB | 硬链接,共享依赖 |
3. 安装速度对比
pnpm > Yarn > npm
pnpm: 2秒 ████████░░
Yarn: 5秒 ██████████████░░░░
npm: 8秒 ████████████████████████░░░░░░░配置推荐
npm 配置
json
{
"save-exact": true,
"registry": "https://registry.npmjs.org/"
}pnpm 配置(推荐)
yaml
# .npmrc
shamefully-hoist=true
strict-peer-dependencies=false
auto-install-peers=trueMonorepo 配置
yaml
# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'常见问题
Q:可以混用吗?
A: 不建议,同一个项目混用会混乱。
Q:-lock 文件可以互转吗?
A: 可以用 pnpm import 从 yarn.lock 转 pnpm-lock.yaml。
Q:pnpm 会破坏现有项目吗?
A: 一般不会,但建议先用 shamefully-hoist=true 兼容。
Q:npm 未来会追上 pnpm 吗?
A: npm 正在改进,但 pnpm 的设计理念仍然领先。
一句话总结
| 场景 | 推荐 |
|---|---|
| 新手 | npm(简单) |
| Monorepo | pnpm(规范) |
| 大项目 | pnpm(快速) |
| 老项目 | 保持现有 |
趋势:2026 年 pnpm 正在成为新项目的首选。
