Monorepo 实践:Turborepo 从零到一
多个相关项目放在一个仓库里管理,共享代码、统一构建、依赖一处安装。这就是 Monorepo。
为什么用 Monorepo
- 共享代码 — 公共组件、工具函数不用发 npm 包
- 原子提交 — 一个改动同时改多个包,一起提交
- 统一依赖 — 不会出现版本不一致
- 增量构建 — 只构建改动的包
Turborepo 初始化
bash
pnpm dlx create-turbo@latest my-monorepo
cd my-monorepo
pnpm install项目结构
monorepo/
├── apps/
│ ├── web/ # 主应用
│ └── admin/ # 后台管理
├── packages/
│ ├── ui/ # 公共组件库
│ ├── utils/ # 工具函数
│ └── tsconfig/ # 共享 TS 配置
├── turbo.json
├── package.json
└── pnpm-workspace.yamlpnpm-workspace.yaml
yaml
packages:
- 'apps/*'
- 'packages/*'共享组件包
ts
// packages/ui/package.json
{
"name": "@my/ui",
"main": "./src/index.ts",
"types": "./src/index.ts",
"dependencies": {
"vue": "^3.5.0"
}
}ts
// packages/ui/src/index.ts
export { default as Button } from './Button.vue'
export { default as Modal } from './Modal.vue'vue
<!-- apps/web 中使用 -->
<script setup lang="ts">
import { Button, Modal } from '@my/ui'
</script>Turborepo 任务配置
json
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"dev": {
"dependsOn": ["^build"],
"cache": false
},
"lint": {},
"type-check": {
"dependsOn": ["^build"]
}
}
}常用命令
bash
# 构建所有包
pnpm turbo build
# 只构建 web 应用(及其依赖)
pnpm turbo build --filter=web
# 并行开发
pnpm turbo dev
# 清理缓存
pnpm turbo clean缓存优化
Turborepo 默认开启本地缓存和远程缓存:
bash
# 本地缓存位置
.turbo/cache/
# 远程缓存(团队共享)
pnpm turbo login
pnpm turbo link构建过一次的包,下次直接用缓存,CI 构建时间从 10 分钟降到 2 分钟。
踩坑记录
- 包之间不要循环依赖 — A 依赖 B,B 就不能再依赖 A
- 版本号统一管理 — 用
changesets做版本发布 - TypeScript 路径别名 — 每个包配自己的
tsconfig.json - 不要把所有东西都放 packages — 业务逻辑留在 apps 里