什么是 Monorepo?pnpm workspace 如何使用?
Monorepo
将多个项目/包放在同一个 Git 仓库中管理。
my-monorepo/
├── packages/
│ ├── ui/ # UI 组件库
│ ├── utils/ # 工具库
│ ├── types/ # 类型定义
│ └── config/ # 共享配置
├── apps/
│ ├── web/ # Web 应用
│ └── admin/ # 管理后台
├── pnpm-workspace.yaml
└── package.jsonMonorepo vs Polyrepo
| 特性 | Monorepo | Polyrepo |
|---|---|---|
| 仓库 | 单一仓库 | 多个仓库 |
| 代码共享 | 容易 | 需发布 npm 包 |
| 版本管理 | 统一 | 各自独立 |
| CI/CD | 统一管理 | 各自配置 |
| 权限 | 全部可见 | 按仓库控制 |
| 适合 | 关联度高的项目 | 独立项目 |
pnpm workspace
# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'常用命令
# 安装所有依赖(自动链接内部包)
pnpm install
# 在特定包中运行命令
pnpm --filter @my/ui build
pnpm --filter web dev
# 在所有包中运行命令
pnpm -r build
# 添加内部依赖
pnpm --filter web add @my/ui # web 包依赖 @my/ui
# 添加外部依赖到所有包
pnpm -r add lodash包间引用
// packages/ui/package.json
{
"name": "@my/ui",
"version": "1.0.0",
"main": "./src/index.ts"
}
// apps/web/package.json
{
"name": "@my/web",
"dependencies": {
"@my/ui": "workspace:*" // 引用 workspace 内的包
}
}workspace:* 表示使用 workspace 内的版本,发布时自动替换为实际版本号。
Turborepo(构建加速)
// turbo.json
{
"tasks": {
"build": {
"dependsOn": ["^build"], // 先构建依赖的包
"outputs": ["dist/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}# 只构建变更影响的包
pnpm turbo build
# 并行运行 dev
pnpm turbo devTurborepo 优势
- 增量构建:只构建变更的包
- 缓存:相同输入不重复构建
- 并行执行:无依赖关系的任务并行
- 远程缓存:CI 和本地共享缓存
变更管理
# 检测哪些包有变更
pnpm turbo run build --filter=...[origin/main]
# Changesets(版本管理)
npx changeset # 记录变更
npx changeset version # 更新版本
npx changeset publish # 发布到 npmMonorepo 最佳实践
- 按职责分包:ui / utils / types / config
- 明确依赖方向:apps → packages,packages 之间尽量不互相依赖
- 统一工具链:ESLint / Prettier / TS 配置共享
- 使用 pnpm:比 npm/yarn 更节省磁盘空间(硬链接)
- CI 优化:只测试/构建变更的包
适合 Monorepo 的场景
- 设计系统(组件库 + 文档 + 示例)
- 多端应用(Web + Mobile + Admin)
- 公司内部多个关联项目
- 开源工具集
不适合的场景
- 完全独立的项目
- 不同团队、不同技术栈
- 需要严格权限控制