Monorepo 实践:Turborepo 从零到一

Monorepo 实践:Turborepo 从零到一

多个相关项目放在一个仓库里管理,共享代码、统一构建、依赖一处安装。这就是 Monorepo。

为什么用 Monorepo

  • 共享代码 — 公共组件、工具函数不用发 npm 包
  • 原子提交 — 一个改动同时改多个包,一起提交
  • 统一依赖 — 不会出现版本不一致
  • 增量构建 — 只构建改动的包

Turborepo 初始化

1
2
3
pnpm dlx create-turbo@latest my-monorepo
cd my-monorepo
pnpm install

项目结构

1
2
3
4
5
6
7
8
9
10
11
monorepo/
├── apps/
│ ├── web/ # 主应用
│ └── admin/ # 后台管理
├── packages/
│ ├── ui/ # 公共组件库
│ ├── utils/ # 工具函数
│ └── tsconfig/ # 共享 TS 配置
├── turbo.json
├── package.json
└── pnpm-workspace.yaml

pnpm-workspace.yaml

1
2
3
packages:
- 'apps/*'
- 'packages/*'

共享组件包

1
2
3
4
5
6
7
8
9
// packages/ui/package.json
{
"name": "@my/ui",
"main": "./src/index.ts",
"types": "./src/index.ts",
"dependencies": {
"vue": "^3.5.0"
}
}
1
2
3
// packages/ui/src/index.ts
export { default as Button } from './Button.vue'
export { default as Modal } from './Modal.vue'
1
2
3
4
<!-- apps/web 中使用 -->
<script setup lang="ts">
import { Button, Modal } from '@my/ui'
</script>

Turborepo 任务配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"dev": {
"dependsOn": ["^build"],
"cache": false
},
"lint": {},
"type-check": {
"dependsOn": ["^build"]
}
}
}

常用命令

1
2
3
4
5
6
7
8
9
10
11
# 构建所有包
pnpm turbo build

# 只构建 web 应用(及其依赖)
pnpm turbo build --filter=web

# 并行开发
pnpm turbo dev

# 清理缓存
pnpm turbo clean

缓存优化

Turborepo 默认开启本地缓存和远程缓存:

1
2
3
4
5
6
# 本地缓存位置
.turbo/cache/

# 远程缓存(团队共享)
pnpm turbo login
pnpm turbo link

构建过一次的包,下次直接用缓存,CI 构建时间从 10 分钟降到 2 分钟。

踩坑记录

  1. 包之间不要循环依赖 — A 依赖 B,B 就不能再依赖 A
  2. 版本号统一管理 — 用 changesets 做版本发布
  3. TypeScript 路径别名 — 每个包配自己的 tsconfig.json
  4. 不要把所有东西都放 packages — 业务逻辑留在 apps 里

Monorepo 实践:Turborepo 从零到一
https://000902.icu/2026/06/25/monorepo-turborepo/
作者
Xiazhou
发布于
2026年6月26日
许可协议