前端工程Technical Deep Dive
Monorepo 实战 —— Turborepo、PNPM Workspace 与 Nx
发布时间2026/03/29
分类前端工程
预计阅读2 分钟
作者吴长龙
*
什么是 Monorepo?
01.内容
什么是 Monorepo?
Monorepo(单体仓库)是将多个项目放在一个仓库中管理的方式。
对比:
- •Multi-repo:每个项目独立仓库
- •Monorepo:所有项目统一仓库
为什么需要 Monorepo?
#### Multi-repo 的痛点
text snippettext
项目A (repo-a)
└── utils-a
项目B (repo-b)
└── utils-b (和 utils-a 类似)
项目C (repo-c)
└── 需要同时依赖 repo-a 和 repo-b问题:
- •代码复用困难
- •版本管理混乱
- •跨项目修改麻烦
- •统一构建/部署复杂
#### Monorepo 的优势
text snippettext
monorepo/
├── packages/
│ ├── utils/ # 共享工具
│ ├── ui/ # 组件库
│ ├── api/ # API 封装
│ └── app-a/ # 应用 A
│ └── app-b/ # 应用 B
├── apps/
│ └── web/
│ └── mobile/
└── packages/
└── shared/ # 共享逻辑优势:
- •代码共享简单
- •统一依赖管理
- •原子提交(atomic commit)
- •一致的开发体验
PNPM Workspace
PNPM 的内置 Monorepo 支持:
yaml snippetyaml
# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'json snippetjson
// package.json (根目录)
{
"name": "my-monorepo",
"private": true,
"scripts": {
"dev": "pnpm --filter web dev",
"build": "pnpm -r build",
"test": "pnpm -r test"
},
"devDependencies": {
"typescript": "^5.0.0"
}
}json snippetjson
// packages/shared/package.json
{
"name": "@myorg/shared",
"version": "1.0.0",
"main": "./src/index.ts",
"exports": {
".": "./src/index.ts"
}
}
// packages/ui/package.json
{
"name": "@myorg/ui",
"version": "1.0.0",
"dependencies": {
"@myorg/shared": "workspace:*"
}
}使用:
bash snippetbash
# 安装依赖(根目录一次安装)
pnpm install
# 在特定包运行
pnpm --filter @myorg/ui build
# 构建所有
pnpm -r buildTurborepo:构建优化
Turborepo 是 Vercel 出的构建编排工具:
json snippetjson
// package.json
{
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"lint": "turbo run lint"
},
"devDependencies": {
"turbo": "^1.10.0"
}
}json snippetjson
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"outputs": []
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
}
}
}#### 核心特性:智能缓存
bash snippetbash
# 首次构建
$ turbo run build
• build Completed in 2m30s
# 修改一个包后再次构建
$ turbo run build
• build Completed in 45s (缓存命中)#### 远程缓存
bash snippetbash
# 登录 Vercel
npx turbo login
# 链接远程缓存
npx turbo link
# 团队共享缓存
# CI/CD 中自动使用远程缓存#### 并行执行
Turborepo 自动分析依赖图,并行执行独立任务:
code snippetcode
app-a ──┐
├───> build (可并行)
app-b ──┘
shared ──> build --> app-a/build (依赖等待)Nx:企业级方案
Nx 是更完整的 Monorepo 解决方案:
json snippetjson
// nx.json
{
"targetDefaults": {
"build": {
"dependsOn": ["^build"]
}
}
}bash snippetbash
# 安装
npm install -D nx
# 创建应用
npx nx g @nx/react:app web
npx nx g @nx/react:lib ui
# 构建
npx nx build web
# affected 模式:只构建变更的部分
npx nx affected:build#### Nx 插件生态
bash snippetbash
# React
npm i -D @nx/react
# Next.js
npm i -D @nx/next
# Node.js
npm i -D @nx/node
# Storybook
npm i -D @nx/storybook#### 计算缓存
bash snippetbash
# 本地缓存
npx nx reset # 清除缓存
# 分布式缓存(Nx Cloud)
npx nx connect-to-nx-cloud实际项目结构
code snippetcode
my-monorepo/
├── pnpm-workspace.yaml
├── turbo.json
├── package.json
│
├── apps/
│ ├── web/ # Next.js 主站
│ │ ├── src/
│ │ ├── project.json
│ │ └── package.json
│ ├── admin/ # 管理后台
│ └── mobile/ # React Native
│
├── packages/
│ ├── ui/ # 组件库
│ │ ├── src/
│ │ ├── stories/
│ │ ├── project.json
│ │ └── package.json
│ │
│ ├── shared/ # 共享工具
│ │ ├── src/
│ │ ├── project.json
│ │ └── package.json
│ │
│ ├── config/ # 配置
│ │ ├── eslint/
│ │ ├── tsconfig/
│ │ └── vite/
│ │
│ └── utils/ # 工具函数
│ ├── src/
│ ├── project.json
│ └── package.json
│
└── tools/
└── scripts/ # 构建脚本迁移建议
#### 从 Multi-repo 迁移
bash snippetbash
# 1. 创建 Monorepo 仓库
mkdir my-monorepo && cd $_
git init
# 2. 创建 workspace 配置
echo "packages: ['packages/*', 'apps/*']" > pnpm-workspace.yaml
# 3. 迁移现有项目
mv ../project-a apps/
mv ../project-b packages/
# 4. 调整依赖
# 将 package.json 中的依赖改为 workspace 协议#### 注意事项
- •权限控制:使用 GitHub Actions 限制应用访问
- •发布流程:CI/CD 需要处理独立发布
- •代码所有权: CODEOWNERS 管理包权限
选型对比
| 特性 | PNPM Workspace | Turborepo | Nx |
|---|---|---|---|
| 依赖管理 | 内置 | 依赖其他 | 内置 |
| 构建缓存 | 无 | 有 | 有 |
| 远程缓存 | 无 | Vercel | Nx Cloud |
| 学习曲线 | 低 | 中 | 高 |
| 企业功能 | 少 | 中 | 多 |
| 适用 | 小团队 | 中团队 | 大企业 |
最佳实践
- •统一代码风格:ESLint + Prettier + Husky
- •类型共享:typescript 依赖提升到根目录
- •版本管理:changesets 自动版本控制
- •CI/CD:affected 模式只构建变更
bash snippetbash
# changesets 用法
pnpm add -Dw @changesets/cli
pnpm changeset init
# 发布
pnpm changeset version
pnpm publish -r总结
Monorepo 是现代前端工程的趋势:
- •小团队:PNPM Workspace 足够
- •中团队:PNPM + Turborepo
- •大企业:Nx 全家桶
核心收益是开发体验和维护效率,但也要考虑迁移成本。