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 支持优秀有限良好
过滤命令强大有限

学习资源