Appearance
PNPM
简介
PNPM (Performance NPM) 是一个快速、节省磁盘空间的包管理器,通过使用内容寻址存储和硬链接来共享依赖,显著减少了磁盘空间占用和安装时间。PNPM 在保持 NPM 兼容性的同时,解决了 NPM 和 Yarn 的一些核心问题。
核心特性
内容寻址存储
PNPM 最大的创新是使用内容寻址存储来管理依赖,所有包都存储在一个全局存储中,项目只通过硬链接引用它们:
.pnpm-store/
└── v3/
└── files/
└── 00/
└── 01abcdef... # 包的内容哈希
这意味着无论有多少项目使用同一个依赖,磁盘上只存储一份。
非扁平化 node_modules
PNPM 创建了一个非扁平化的 node_modules
结构,解决了 NPM 和 Yarn 的"幻影依赖"问题:
node_modules/
├── .pnpm/
│ ├── express@4.17.1/
│ ├── lodash@4.17.21/
│ └── ... (所有依赖)
├── express -> .pnpm/express@4.17.1/node_modules/express
└── lodash -> .pnpm/lodash@4.17.21/node_modules/lodash
这确保了项目只能访问 package.json
中声明的依赖。
速度优势
bash
# 安装依赖
pnpm install
# 添加依赖
pnpm add lodash
# 添加开发依赖
pnpm add -D jest
# 全局安装
pnpm add -g typescript
工作空间支持
PNPM 提供了强大的工作空间 (Workspace) 支持,非常适合 Monorepo 项目:
yaml
# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'
- '!**/test/**'
bash
# 在所有工作空间中运行命令
pnpm -r test
# 在特定工作空间运行命令
pnpm --filter @myorg/package-name build
# 在依赖图中按顺序运行命令
pnpm -r --workspace-concurrency=1 build
配置文件
package.json
与 NPM 和 Yarn 使用相同的 package.json 格式。
pnpm-lock.yaml
锁文件,确保依赖的确定性安装。
.npmrc
PNPM 使用与 NPM 相同的 .npmrc 配置文件,但增加了一些特有的选项:
node-linker=hoisted # 使用扁平化结构 (默认为 isolated)
store-dir=./.pnpm-store # 自定义存储位置
shared-workspace-lockfile=false # 每个工作空间使用独立的锁文件
常用命令
bash
# 初始化项目
pnpm init
# 安装依赖
pnpm install
pnpm i # 简写
# 添加依赖
pnpm add package-name
pnpm add package-name@version
pnpm add package-name --save-exact # 精确版本
# 更新依赖
pnpm update
pnpm update package-name
# 移除依赖
pnpm remove package-name
pnpm rm package-name # 简写
# 运行脚本
pnpm run script-name
pnpm script-name # 简写
# 查看依赖图
pnpm list
pnpm list --depth=1
# 清理缓存
pnpm store prune
高级功能
过滤命令
PNPM 提供了强大的过滤功能,可以在特定包上执行命令:
bash
# 在所有包含 test 脚本的包中运行测试
pnpm -r exec -- pnpm test
# 在所有依赖了 react 的包中运行构建
pnpm -r --filter "[react]" build
# 在所有被 my-app 依赖的包中运行构建
pnpm -r --filter "...my-app" build
依赖管理策略
PNPM 提供了多种依赖管理策略:
bash
# 使用对等依赖 (peer dependencies)
pnpm add package-name --save-peer
# 安装可选依赖
pnpm add package-name --save-optional
# 安装确切版本
pnpm add package-name --save-exact
最佳实践
存储优化
- 使用
pnpm store prune
定期清理未使用的包 - 配置 CI 环境使用共享存储:
pnpm config set store-dir ~/.pnpm-store
Monorepo 管理
- 使用
publishConfig
配置发布设置 - 利用
pnpm publish -r
发布工作空间中的所有包 - 使用
--filter
和--workspace-concurrency
优化构建流程
常见问题与解决方案
兼容性问题
bash
# 使用扁平化结构解决兼容性问题
pnpm install --shamefully-hoist
迁移到 PNPM
bash
# 从 NPM/Yarn 迁移到 PNPM
rm -rf node_modules
rm package-lock.json yarn.lock
pnpm import # 从现有锁文件导入
pnpm install
CI 环境配置
bash
# 在 CI 中使用 PNPM
pnpm config set store-dir ~/.pnpm-store
pnpm install --frozen-lockfile
与其他包管理器对比
特性 | PNPM | NPM | Yarn |
---|---|---|---|
安装速度 | 最快 | 慢 | 快 |
磁盘空间使用 | 极低 | 高 | 高 |
依赖结构 | 严格 | 扁平 | 扁平 |
幻影依赖问题 | 无 | 有 | 有 |
Monorepo 支持 | 优秀 | 有限 | 良好 |
过滤命令 | 强大 | 无 | 有限 |