跳到主要内容

pnpm

pnpm 是一个高效、快速的 JavaScript 包管理器,由 npm 的早期开发者 Zoltan Kochan 创建。它使用硬链接和符号链接来共享依赖,显著节省磁盘空间。

主要特点

  • 节省磁盘空间:通过内容寻址存储,相同的依赖只存储一份
  • 快速安装:比 npm 和 yarn 更快,依赖链接而非复制
  • 严格的依赖管理:防止"幽灵依赖",只能访问 package.json 中声明的依赖
  • 确定性:生成锁文件确保跨环境一致性
  • 支持单体仓库:内置 workspace 支持

安装

# 使用 npm 安装
npm install -g pnpm

# 使用 Corepack(Node.js 16.13+)
corepack enable
corepack prepare pnpm@latest --activate

# 使用安装脚本(Windows PowerShell)
iwr https://get.pnpm.io/install.ps1 -useb | iex

# 使用 Homebrew(macOS)
brew install pnpm

基本使用

初始化项目

# 创建 package.json
pnpm init

# 使用默认值
pnpm init --ignore-scripts

安装依赖

# 安装所有依赖
pnpm install

# 安装生产依赖
pnpm add lodash

# 安装指定版本
pnpm add [email protected]

# 安装开发依赖
pnpm add -D jest
pnpm add --save-dev jest

# 安装可选依赖
pnpm add -O eslint

# 全局安装
pnpm add -g typescript

# 安装精确版本
pnpm add --save-exact lodash

# 安装到特定 workspace
pnpm add lodash --filter @myproject/core

删除依赖

# 删除依赖
pnpm remove lodash

# 删除开发依赖
pnpm remove -D jest

# 删除全局依赖
pnpm remove -g typescript

# 从所有 workspace 删除
pnpm remove lodash --recursive

更新依赖

# 检查可更新的依赖
pnpm outdated

# 更新依赖
pnpm update

# 更新到最新版本(忽略版本范围)
pnpm update --latest

# 更新特定包
pnpm update lodash

# 交互式更新
pnpm update --interactive

node_modules 结构

pnpm 使用独特的 node_modules 结构:

node_modules/
├── .pnpm/ # 所有包的硬链接存储
│ ├── [email protected]/
│ │ └── node_modules/
│ │ └── lodash/ # 实际包内容
│ └── ...
├── lodash -> .pnpm/[email protected]/node_modules/lodash # 符号链接
└── .modules.yaml

优点

  • 防止访问未声明的依赖
  • 节省磁盘空间
  • 安装速度快

兼容性设置

如果需要兼容 npm 的扁平化结构:

# .npmrc
shamefully-hoist=true
node-linker=hoisted

pnpm-lock.yaml

pnpm 使用 pnpm-lock.yaml 锁定依赖版本。

lockfileVersion: '6.0'

importers:
.:
dependencies:
lodash:
specifier: ^4.17.21
version: 4.17.21

packages:
/[email protected]:
resolution: {integrity: sha512-v3k...}
dev: false

配置管理

.npmrc 文件

# 设置镜像源
registry=https://registry.npmmirror.com

# 兼容性设置
shamefully-hoist=true
strict-peer-dependencies=false

# 存储位置
store-dir=~/.pnpm-store

# 缓存设置
cache-dir=~/.pnpm-cache

常用配置命令

# 查看所有配置
pnpm config list

# 查看特定配置
pnpm config get registry

# 设置配置
pnpm config set registry https://registry.npmmirror.com

# 设置全局配置
pnpm config set registry https://registry.npmmirror.com --global

# 删除配置
pnpm config delete registry

工作区 (Workspaces)

pnpm 原生支持单体仓库管理。

配置

# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'
- '!**/test/**'

workspace 命令

# 在所有包中执行命令
pnpm -r run build

# 在特定包中执行命令
pnpm --filter @myproject/core run build

# 在包及其依赖中执行
pnpm --filter @myproject/core... run build

# 在包及其依赖者中执行
pnpm --filter ...@myproject/core run build

# 并行执行
pnpm -r --parallel run test

# 按拓扑顺序执行
pnpm -r --workspace-concurrency=4 run build

workspace 协议

{
"dependencies": {
"@myproject/core": "workspace:*",
"@myproject/utils": "workspace:^"
}
}
协议说明
workspace:*使用精确版本
workspace:^使用兼容版本
workspace:~使用近似版本
workspace:^1.0.0指定版本范围

脚本命令

定义脚本

{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest",
"build": "webpack --mode production"
}
}

运行脚本

# 运行脚本
pnpm run start
pnpm start # start 可省略 run

# 传递参数
pnpm run test -- --coverage

# 并行运行
pnpm -r run test

# 按拓扑顺序运行
pnpm -r run build

发布包

# 登录
pnpm login

# 发布前检查
pnpm pack --dry-run

# 发布
pnpm publish

# 发布到指定镜像源
pnpm publish --registry https://registry.npmjs.org

# 发布 scoped 包
pnpm publish --access public

# 发布 beta 版本
pnpm publish --tag beta

常用命令速查

命令说明
pnpm init初始化项目
pnpm install安装所有依赖
pnpm add <pkg>安装依赖
pnpm add -D <pkg>安装开发依赖
pnpm remove <pkg>删除依赖
pnpm update更新依赖
pnpm outdated检查过期依赖
pnpm run <script>运行脚本
pnpm list查看已安装依赖
pnpm list -g --depth=0查看全局依赖
pnpm why <pkg>查看依赖原因
pnpm store prune清理未使用的包
pnpm store path查看存储位置
pnpm doctor检查环境
pnpm rebuild重新构建依赖
pnpm fetch仅下载依赖到存储

与 npm 命令对比

npmpnpm
npm installpnpm install
npm install <pkg>pnpm add <pkg>
npm install -D <pkg>pnpm add -D <pkg>
npm uninstall <pkg>pnpm remove <pkg>
npm run <script>pnpm run <script>
npm listpnpm list
npm outdatedpnpm outdated
npm updatepnpm update
npm cipnpm install --frozen-lockfile
npm dedupe不需要(pnpm 自动优化)
npx <cmd>pnpm dlx <cmd>

pnpm dlx

类似于 npx,用于执行包命令:

# 创建项目
pnpm dlx create-react-app my-app
pnpm dlx create-vite my-app

# 使用特定版本
pnpm dlx [email protected] my-app

# 从 GitHub 执行
pnpm dlx github:user/repo

最佳实践

1. 使用 .npmrc 配置

# 自动安装 peer dependencies
auto-install-peers=true

# 严格的 peer dependencies 检查
strict-peer-dependencies=true

# 提升依赖(兼容旧项目)
shamefully-hoist=true

2. 使用 catalog 管理版本

# pnpm-workspace.yaml
packages:
- 'packages/*'

catalog:
react: ^18.2.0
typescript: ^5.0.0
jest: ^29.5.0
// packages/core/package.json
{
"dependencies": {
"react": "catalog:"
}
}

3. 使用 onlyBuiltDependencies

{
"pnpm": {
"onlyBuiltDependencies": ["esbuild"]
}
}

4. 安全审计

# 检查安全漏洞
pnpm audit

# 自动修复
pnpm audit --fix

5. 清理存储

# 清理未使用的包
pnpm store prune

# 检查存储状态
pnpm store status

了解更多