Chapter 10

把 Turbo 用在真仓库里

前九章把单点能力讲透,本章把它们串起来——一个真实大仓的 turbo.json、生产 checklist、v1→v2 迁移路径、boundaries 等 2026 新特性,和 Turborepo 在 pnpm/Bun 生态里的未来位置。

生产级 turbo.json 范本

{
  "$schema": "https://turbo.build/schema.json",
  "ui": "tui",
  "globalDependencies": [
    ".env*",
    "tsconfig.base.json",
    "tailwind.config.*",
    "postcss.config.*"
  ],
  "globalEnv": ["NODE_ENV", "VERCEL_ENV", "CI"],
  "globalPassThroughEnv": [
    "TURBO_*",
    "GITHUB_TOKEN",
    "NPM_TOKEN",
    "AWS_*",
    "SENTRY_AUTH_TOKEN"
  ],
  "remoteCache": { "signature": true },
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": [
        "$TURBO_DEFAULT$",
        "!**/*.md",
        "!**/*.test.*",
        "!**/__snapshots__/**"
      ],
      "outputs": [
        "dist/**",
        ".next/**",
        "!.next/cache/**",
        "storybook-static/**"
      ],
      "env": ["NEXT_PUBLIC_*", "SENTRY_DSN", "DATABASE_URL"]
    },
    "test": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "test/**", "vitest.config.*"],
      "outputs": ["coverage/**"]
    },
    "typecheck": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "tsconfig.json"]
    },
    "lint": {
      "inputs": ["src/**", ".eslintrc*", "eslint.config.*"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "//#generate-schema": {
      "inputs": ["openapi.yaml"],
      "outputs": ["packages/api-types/src/**"]
    }
  }
}

这份配置包含了几乎所有生产要素:全局依赖、签名校验、通配 env、精细 inputs/outputs、任务拓扑。

从 Turbo 1.x 迁移到 2.x

pnpm dlx @turbo/codemod migrate

常见变化:

pipeline → tasks
顶层键名改了,codemod 自动处理。
env 不再隐式
v1 下 env 自动被读取;v2 必须显式声明,否则 strict 模式读不到。codemod 扫代码里的 process.env 访问帮你列全。
dotenv 字段移除
v1 的 dotenv: [".env"] 字段废弃,改用 globalDependencies: [".env"] + 你自己的构建工具加载。
--filter 语法收紧
部分旧语法(如 --filter=...{path})换成更清晰的。官方文档有完整 mapping。
Rust 引擎
v1 是 Go 写的,v2 Rust;二进制更小,启动 50ms 以内,大仓任务调度更快。

boundaries:package 边界检查

pnpm turbo boundaries

Turbo 2.x 新功能,检查:

// turbo.json 启用
{
  "boundaries": {
    "tags": {
      "@myorg/ui": ["ui", "shared"],
      "@myorg/web": ["app"]
    },
    "rules": {
      "app": { "dependencies": { "allow": ["ui", "shared"] } },
      "ui": { "dependencies": { "deny": ["app"] } }
    }
  }
}

类似 Nx 的 enforce-module-boundaries——大仓的"包依赖纪律"工具。

常见生产问题

"缓存明明该命中,却一直 miss"
"远程缓存上传失败但没报错"
"生产构建和 CI 构建不一致"

Turbo + Bun

bun install
bun run turbo run build

Bun 1.2 官方支持 Turbo。workspaces 兼容 pnpm 布局,包管理器换成 Bun 也能无痛接 Turbo。只是:

Turbo + Nx 对比的演进

功能Turbo 2.xNx 19.x
远程缓存Vercel / 自建Nx Cloud / 自建
代码生成强大
边界检查boundaries(2.x)enforce-module-boundaries
任务分发有限(本地并发)Nx Agents 多机分发
集成度
上手半小时1-2 天

差距在缩小——Turbo 每次大版本补齐一个 Nx 特性(v2 补了 boundaries、watch、TUI)。对多数团队,"轻 + 够用"还是 Turbo 的核心价值。

性能调优实战

1. 量化当前水平
记录三个数:冷 CI、热 CI、命中率。--summarize 可导出。
2. 攻最大的任务
--profile=profile.json 看瓶颈,Next.js build / Storybook build 往往是最大头。
3. 收窄 inputs
默认 $TURBO_DEFAULT$ 太宽。列具体目录后,命中率通常能从 60% 提到 90%+。
4. 远程缓存必开
CI 和本地都受益,投入产出比极高。
5. 拆 job 并行
build/test/lint 各自 job——比单 job 串行快。
6. Vercel ignoreCommand
多 app 仓库,无关部署跳过——省部署额度、省等待时间。

大仓案例:100+ 包

一个真实的金融科技 monorepo(2026):
  - 12 个 apps(Next.js web + admin + mobile-rn + 2 个 API + worker + …)
  - 88 个 packages(ui / utils / api-types / db / auth / …)
  - pnpm + Turbo + Changesets + Vercel
  - 每天 80+ PR,一个 PR 平均 build 时间 45 秒(命中率 ~92%)
  - CI 月费比换 Turbo 前降了 70%
关键经验

什么时候"不用 Turbo"

Turborepo 2026 路线

写在最后

Turborepo 的价值不在"运行得快",在"让团队协作中的重复计算自动消失":

这是一个工程文化层面的变化——从"每次都全量"变成"只跑该跑的"。花两小时配对 turbo.json,能省团队几千个小时。

学习路径
  1. 先在已有 pnpm workspace 里 pnpm add -Dw turbo 起手
  2. 写最小 turbo.json(build + test + dev 三个)
  3. 第二次 build 看到 FULL TURBO
  4. 接 Vercel Remote Cache,CI 时间立刻降
  5. --summarize 定期看命中率
  6. 收窄 inputs / outputs / env,把命中率推到 90%+
  7. 多 app 仓库上 turbo prune + turbo-ignore
  8. Changesets + 远程缓存 + Vercel 集成,全自动发版

本章小结