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 命令对比
| npm | pnpm |
|---|---|
npm install | pnpm 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 list | pnpm list |
npm outdated | pnpm outdated |
npm update | pnpm update |
npm ci | pnpm 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
了解更多
- pnpm 官网:https://pnpm.io
- pnpm GitHub:https://github.com/pnpm/pnpm
- pnpm 文档:https://pnpm.io/motivation