pnpm
1. 定义
pnpm 是 Node.js 生态下的一款包管理器,定位是 npm / yarn 的替代品。 两大卖点:快、省磁盘。通过内容寻址存储 (content-addressable store) + 硬链接实现全局包复用。
名字含义:performant npm。读音直接拼字母 P-N-P-M,或读 “perf-npm”。
2. pnpm 解决了什么问题
传统 npm/yarn 的问题:
| 问题 | npm/yarn | pnpm |
|---|---|---|
| 磁盘占用 | 每个项目都拷一份 node_modules,10 个项目用 lodash 就存 10 份 | 全局 store 只存一份,项目里用硬链接 + 软链指过去 |
| 幽灵依赖 (phantom deps) | 扁平化 node_modules,导致没在 package.json 里声明的包也能被 import | 严格结构,只能 import 声明过的包 |
| Peer 依赖警告满天飞 | 自动装 peer deps,版本冲突时报错 | 默认不自动装,用 --shamefully-hoist 或配置控制 |
| 安装速度 | 慢,要拷大量文件 | 快,硬链接几乎不增加磁盘 IO |
3. 核心机制:Content-Addressable Store + Symlinked node_modules
全局 store (~/.pnpm-store/)
└── lodash@4.17.21/ ← 真正的文件只存一份
项目 node_modules/
├── .pnpm/ ← 中间层,硬链接到全局 store
│ └── lodash@4.17.21/
│ └── node_modules/lodash/
└── lodash -> .pnpm/lodash@4.17.21/node_modules/lodash ← 软链给你的代码用
关键点:
- 全局 store:所有包按
包名@版本/hash存一份,跨项目复用 - 硬链接:项目里的包文件硬链到 store,不占额外磁盘
- 软链接结构:
node_modules里只暴露 package.json 声明的包,杜绝幽灵依赖
这就是为什么 pnpm 装一个新项目几乎不增加磁盘占用——大部分包 store 里早有了。
4. 常用命令
基础(和 npm 几乎一样)
pnpm install # 安装 package.json 所有依赖(alias: pnpm i)
pnpm add express # 添加生产依赖
pnpm add -D vitest # 添加开发依赖
pnpm add -g pm2 # 全局安装
pnpm remove express # 卸载
pnpm update # 升级所有依赖
pnpm update express # 只升级 express运行脚本
pnpm run build # 跑 package.json 里的 scripts.build
pnpm build # run 可省略
pnpm test # 等于 pnpm run test
pnpm start # 等于 pnpm run start查询
pnpm list # 列出依赖树(alias: pnpm ls)
pnpm list --depth 1 # 只看一层
pnpm why lodash # 看 lodash 是被谁依赖进来的
pnpm outdated # 看哪些包过期了Workspace(monorepo 多包管理)
pnpm init # 初始化 package.json
pnpm init --shamefully-hoist # 兼容老项目:扁平化 node_modules(像 npm 那样)
pnpm -r add lodash # 给 workspace 里所有包都装 lodash
pnpm --filter webapp add axios # 只给名为 webapp 的子包装 axios
pnpm -r run build # 在所有包里跑 build 脚本workspace 配置(根 pnpm-workspace.yaml):
packages:
- 'packages/*'
- 'apps/*'其他实用
pnpm exec tsc # 在项目环境里运行本地装的二进制
pnpm dlx create-vite # 临时运行一个包,不安装到项目(类似 npx)
pnpm store prune # 清理 store 里没被任何项目引用的包
pnpm pack # 打包成 .tgz5. pnpm vs npm vs yarn 速查
| 维度 | npm | yarn (classic) | pnpm |
|---|---|---|---|
| 安装速度 | 慢 | 中 | 快 |
| 磁盘占用 | 高(每项目一份) | 高 | 低(全局复用) |
node_modules 结构 | 扁平 | 扁平 | 严格分层(软链) |
| 幽灵依赖 | 有 | 有 | 无 |
| Lockfile | package-lock.json | yarn.lock | pnpm-lock.yaml |
| Workspaces | 支持 | 支持 | 支持(更灵活) |
| Plug’n’Play | 不支持 | yarn 2+ PnP | 不支持(用软链方案) |
| 缓存机制 | 本地 cache | 本地 cache | 全局 store + 硬链接 |
6. 典型工作流
新项目
pnpm create vite my-app --template react-ts
cd my-app
pnpm install
pnpm dev接手已有项目
git clone <repo>
cd <repo>
pnpm install # 自动识别 lockfile,按锁定的版本装Monorepo(多包仓库)
mkdir monorepo && cd monorepo
pnpm init
echo "packages:\n - 'packages/*'" > pnpm-workspace.yaml
mkdir -p packages/webapp packages/utils
pnpm --filter webapp add express
pnpm -r run build7. 常见坑
- 某些工具找不到包:依赖了扁平化
node_modules的老工具会失败。解决:pnpm install --shamefully-hoist,或针对性配置node-linker=hoisted pnpm dlxvsnpx:用法一样,但 pnpm 的 dlx 也会走全局 store,重复运行更快- Peer 依赖冲突:pnpm 默认不自动装 peer deps,会报警告。需要的话手动
pnpm add那个 peer 包,或在.npmrc配置auto-install-peers=true node_modules/.pnpm不要手动改:这是 pnpm 的内部结构,改了会出诡异问题- 硬链接跨磁盘失效:如果 store 和项目不在同一磁盘分区,硬链接会降级为拷贝,磁盘优势就没。Apple Silicon 默认 store 在
~/.pnpm-store,跨盘用户需配置store-dir
8. 延伸阅读 / 关联概念
- Corepack — Node 自带的包管理器版本管理工具,
corepack enable pnpm即可用,不用全局装 pnpm - 幽灵依赖 (Phantom Dependencies) — 扁平 node_modules 导致能 import 未声明包的问题,pnpm 用软链结构解决
- Monorepo 工具对比 — pnpm workspaces / Nx / Turborepo,pnpm 自带 workspace 就够大多数场景用
- 官方文档:https://pnpm.io/