PNPM 使用介绍
pnpm 用硬链接共享依赖,省磁盘、装得快、依赖不幽灵。
Key Pointspnpm 全局存一份包内容,项目里用硬链接指过去,并严格隔离非法依赖。
装与用
Bash
npm install -g pnpm
pnpm -v
pnpm init
pnpm add express
pnpm add -D typescript
pnpm install
pnpm run devOutput
$ pnpm -v
9.12.3
$ pnpm add express
Packages: +54
++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 54, reused 54, downloaded 0, added 54, doneNote reused 54, downloaded 0 — the packages already exist in the global store and are hard-linked in, costing almost no time or disk.
和 npm 的差别
| Aspect | npm | pnpm |
|---|---|---|
| 磁盘 | 每个项目各存一份 | 全局一份 + 硬链接 |
| node_modules | 扁平提升 | 符号链接 + 严格隔离 |
| 幽灵依赖 | 可能装到没声明的包 | 访问不到,直接报错 |
| monorepo | 要 workspaces | 原生 workspace,体验更好 |
幽灵依赖是什么
npm hoists dependencies to the top-level node_modules, so transitive dependencies you never declared are still require-able. It works locally and breaks in CI the day that package's tree changes.
JavaScript
// 只在 dependencies 里声明了 express
// express 依赖 body-parser,但你没声明它
const bp = require('body-parser'); // npm: 能跑 pnpm: ERR_MODULE_NOT_FOUNDworkspace
YAML
# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'Bash
pnpm --filter @app/web add lodash
pnpm -r run buildTo migrate: delete
node_modules and package-lock.json; pnpm import converts the old lock into pnpm-lock.yaml so versions do not drift.装与用
Bash
npm install -g pnpm
pnpm -v
pnpm init
pnpm add express
pnpm add -D typescript
pnpm install
pnpm run devOutput
$ pnpm -v
9.12.3
$ pnpm add express
Packages: +54
++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 54, reused 54, downloaded 0, added 54, done注意 reused 54, downloaded 0 —— 这些包在全局仓库里已经有了,直接硬链接进来,几乎不花时间和磁盘。
和 npm 的差别
| 对比项 | npm | pnpm |
|---|---|---|
| 磁盘 | 每个项目各存一份 | 全局一份 + 硬链接 |
| node_modules | 扁平提升 | 符号链接 + 严格隔离 |
| 幽灵依赖 | 可能装到没声明的包 | 访问不到,直接报错 |
| monorepo | 要 workspaces | 原生 workspace,体验更好 |
幽灵依赖是什么
npm 把依赖扁平提升到顶层 node_modules,于是你没在 package.json 里声明的传递依赖也能 require 到。本地能跑,CI 一装就崩——因为哪天那个包的依赖树变了。
JavaScript
// 只在 dependencies 里声明了 express
// express 依赖 body-parser,但你没声明它
const bp = require('body-parser'); // npm: 能跑 pnpm: ERR_MODULE_NOT_FOUNDworkspace
YAML
# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'Bash
pnpm --filter @app/web add lodash
pnpm -r run build迁移项目:删掉
node_modules 和 package-lock.json,pnpm import 可以从旧 lock 生成 pnpm-lock.yaml,避免版本漂移。