Files
2026-07-13 21:35:53 +08:00

208 lines
3.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: pnpm-workspaces
description: 通过工作空间实现 monorepo 支持,用于管理多个包
---
# pnpm Workspaces
pnpm 通过工作空间(workspaces)内置支持 monorepo(多包仓库)。
## 设置工作空间
在仓库根目录创建 `pnpm-workspace.yaml`
```yaml
packages:
# 包含 packages/ 目录下的所有包
- 'packages/*'
# 包含所有应用
- 'apps/*'
# 包含嵌套的包
- 'tools/*/packages/*'
# 排除测试目录
- '!**/test/**'
```
## 工作空间协议
使用 `workspace:` 协议引用本地包:
```json
{
"dependencies": {
"@myorg/utils": "workspace:*",
"@myorg/core": "workspace:^",
"@myorg/types": "workspace:~"
}
}
```
### 协议变体
| 协议 | 行为 | 发布时转换 |
|----------|----------|--------------|
| `workspace:*` | 任意版本 | 实际版本(如 `1.2.3` |
| `workspace:^` | 兼容版本 | `^1.2.3` |
| `workspace:~` | 补丁版本 | `~1.2.3` |
| `workspace:^1.0.0` | Semver 范围 | `^1.0.0` |
## 过滤包
使用 `--filter` 在特定包上运行命令:
```bash
# 按包名
pnpm --filter @myorg/app build
pnpm -F @myorg/app build
# 按目录路径
pnpm --filter "./packages/core" test
# Glob 模式
pnpm --filter "@myorg/*" lint
pnpm --filter "!@myorg/internal-*" publish
# 所有包
pnpm -r build
pnpm --recursive build
```
### 基于依赖关系的过滤
```bash
# 包及其所有依赖
pnpm --filter "...@myorg/app" build
# 包及其所有依赖者
pnpm --filter "@myorg/core..." test
# 双向
pnpm --filter "...@myorg/shared..." build
# 自 git 引用以来的变更
pnpm --filter "...[origin/main]" test
pnpm --filter "[HEAD~5]" lint
```
## 工作空间命令
### 安装依赖
```bash
# 安装所有工作空间包
pnpm install
# 向特定包添加依赖
pnpm --filter @myorg/app add lodash
# 添加工作空间依赖
pnpm --filter @myorg/app add @myorg/utils
```
### 运行脚本
```bash
# 在所有包含该脚本的包中运行
pnpm -r run build
# 按拓扑顺序运行(依赖优先)
pnpm -r --workspace-concurrency=1 run build
# 并行运行
pnpm -r --parallel run test
# 流式输出
pnpm -r --stream run dev
```
### 执行命令
```bash
# 在所有包中运行命令
pnpm -r exec pwd
# 在特定包中运行
pnpm --filter "./packages/**" exec rm -rf dist
```
## 工作空间设置
`.npmrc``pnpm-workspace.yaml` 中配置:
```ini
# 自动链接工作空间包
link-workspace-packages=true
# 优先使用工作空间包而非注册表
prefer-workspace-packages=true
# 单一锁文件(推荐)
shared-workspace-lockfile=true
# 工作空间协议处理方式
save-workspace-protocol=rolling
# 并发工作空间脚本数
workspace-concurrency=4
```
## 发布工作空间
发布时,`workspace:` 协议会被转换:
```json
// 发布前
{
"dependencies": {
"@myorg/utils": "workspace:^"
}
}
// 发布后
{
"dependencies": {
"@myorg/utils": "^1.2.3"
}
}
```
从 CI 发布时使用 `--no-git-checks`
```bash
pnpm publish -r --no-git-checks
```
## 最佳实践
1. **对内部依赖使用 workspace 协议**
2. **启用 `link-workspace-packages`** 以实现自动链接
3. **使用共享锁文件** 以保证一致性
4. **构建时按依赖过滤** 以确保正确的顺序
5. **使用目录(catalogs** 管理共享的外部依赖版本
## 项目结构示例
```
my-monorepo/
├── pnpm-workspace.yaml
├── package.json
├── pnpm-lock.yaml
├── packages/
│ ├── core/
│ │ └── package.json
│ ├── utils/
│ │ └── package.json
│ └── types/
│ └── package.json
└── apps/
├── web/
│ └── package.json
└── api/
└── package.json
```
<!--
参考来源:
- https://pnpm.io/workspaces
- https://pnpm.io/filtering
- https://pnpm.io/npmrc#workspace-settings
-->