Skip to content

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

与其他包管理器对比 ​

特性PNPMNPMYarn
安装速度最快慢快
磁盘空间使用极低高高
依赖结构严格扁平扁平
幻影依赖问题无有有
Monorepo 支持优秀有限良好
过滤命令强大无有限

学习资源 ​