Turborepo Monorepo 管理实战指南
James Park | 2026-09-02T01:08:11 | JavaScript, DevOps
深入讲解如何用 Turborepo 管理 JavaScript/TypeScript Monorepo,涵盖任务编排、远程缓存、增量构建和 CI 优化策略。
# Turborepo Monorepo 管理实战指南 ## 为什么选 Monorepo 当团队维护多个相关包(前端应用、共享组件库、API 客户端、工具函数)时,Monorepo 的优势明显: - 跨包修改在一个 PR 中完成 - 共享配置(ESLint、TypeScript、Prettier) - 版本一致性保证 - 原子性发布 Turborepo 是 Vercel 出品的高性能 Monorepo 构建系统。 ## 初始化 ```bash npx create-turbo@latest my-monorepo cd my-monorepo ``` 目录结构: ``` my-monorepo/ ├── apps/ │ ├── web/ # Next.js 主站 │ └── admin/ # 管理后台 ├── packages/ │ ├── ui/ # 共享组件库 │ ├── utils/ # 工具函数 │ ├── eslint-config/ │ └── typescript-config/ ├── turbo.json └── package.json ``` ## turbo.json 配置 ```json { "$schema": "https://turbo.build/schema.json", "globalDependencies": ["**/.env.*local"], "tasks": { "build": { "dependsOn": ["^build"], "inputs": ["src/**", "tsconfig.json"], "outputs": [".next/**", "dist/**"] }, "dev": { "cache": false, "persistent": true }, "lint": { "dependsOn": ["^build"] }, "test": { "dependsOn": ["build"], "inputs": ["src/**", "test/**"] }, "type-check": { "dependsOn": ["^build"] } } } ``` 关键概念: - `dependsOn: ["^build"]`:先构建所有依赖的包 - `inputs`:只有这些文件变化时才重新执行 - `outputs`:构建产物,用于缓存 - `persistent: true`:长期运行的任务(dev server) ## 任务编排 ```bash # 构建所有包 turbo build # 只构建 web 和它的依赖 turbo build --filter=web # 只构建变更的包 turbo build --filter=...[origin/main] # 并行运行 dev turbo dev # 运行特定包的特定任务 turbo lint --filter=@repo/ui ``` ## 远程缓存 Turborepo 的杀手级特性 — CI 和团队成员共享构建缓存: ```bash # 登录 Vercel(免费计划) npx turbo login # 链接到远程缓存 npx turbo link # 之后所有 turbo 命令自动使用远程缓存 turbo build # >>> FULL TURBO: 3/4 packages hit cache ``` 自托管缓存服务器: ```bash # 使用开源的 turbo cache server docker run -p 8080:8080 ducktors/turborepo-remote-cache # 配置 turbo build --api="http://localhost:8080" --token="xxx" ``` ## 包间依赖 ```json // packages/ui/package.json { "name": "@repo/ui", "version": "0.0.0", "exports": { ".": "./src/index.ts", "./button": "./src/button.tsx", "./card": "./src/card.tsx" } } // apps/web/package.json { "dependencies": { "@repo/ui": "workspace:*", "@repo/utils": "workspace:*" } } ``` 使用: ```tsx // apps/web/src/page.tsx import { Button } from "@repo/ui/button"; import { formatDate } from "@repo/utils"; ``` ## 共享配置 ```typescript // packages/eslint-config/next.js module.exports = { extends: [ "next/core-web-vitals", "plugin:@typescript-eslint/recommended", "prettier", ], rules: { "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], }, }; // apps/web/.eslintrc.js module.exports = { root: true, extends: ["@repo/eslint-config/next"], }; ``` ## CI 优化 ```yaml # .github/workflows/ci.yml name: CI on: pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 2 - uses: actions/setup-node@v4 with: node-version: 20 - uses: pnpm/action-setup@v3 with: version: 9 - run: pnpm install --frozen-lockfile # 只检查变更的包 - run: pnpm turbo build lint test type-check --filter=...[HEAD~1] env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ vars.TURBO_TEAM }} ``` ## 常见问题 1. **幽灵依赖**:用 pnpm 的严格模式避免包访问未声明的依赖 2. **类型循环依赖**:packages 之间避免双向引用 3. **dev 模式热更新**:确保包使用 `exports` 指向源码而非构建产物 ## 总结 Turborepo 用最小化的配置实现了高效的 Monorepo 管理。任务拓扑排序确保正确的构建顺序,增量构建和远程缓存大幅减少 CI 时间。对于 JavaScript/TypeScript 项目,它是当前最佳的 Monorepo 构建工具选择。