DevToolBox免费
博客

Turborepo 完全指南:高性能 Monorepo 构建系统 (2026)

18 分钟阅读作者 DevToolBox Team

Turborepo 是一个面向 JavaScript 和 TypeScript monorepo 的高性能构建系统。由 Jared Palmer 创建,现由 Vercel 维护,Turborepo 通过智能缓存和任务调度大幅加速多包仓库的构建、测试和代码检查。无论你管理少量共享库还是数十个应用,Turborepo 通过理解包之间的依赖关系图来消除冗余工作,只重新构建发生变化的部分。

TL;DR

Turborepo 是一个 monorepo 构建系统,使用内容感知哈希、远程缓存(Vercel Remote Cache)和并行任务执行来将构建速度提升 65-85%。它支持 npm、pnpm 和 yarn 工作区,通过 turbo.json 进行最少配置,并集成任何 CI/CD 平台。Turborepo 理解任务依赖关系图,跳过已完成的工作,并在整个团队间共享缓存产物。

Key Takeaways
  • Turborepo 使用内容感知哈希跳过输入未改变的任务,通常可减少 65-85% 的 CI 时间。
  • 远程缓存在整个团队和 CI 间共享构建产物,一个开发者的构建结果惠及所有人。
  • turbo.json 中的任务管道系统定义任务间的依赖关系,实现最大并行执行。
  • Turborepo 支持 npm、pnpm 和 yarn 工作区,无需更换现有的包管理器。
  • turbo prune 命令生成精简的 monorepo 子集,用于高效的 Docker 镜像构建。
  • 相比 Nx 等替代方案,Turborepo 几乎零配置,使现有 monorepo 的采用变得简单。

什么是 Turborepo?为什么选择 Monorepo?

Monorepo 是一个包含多个项目、包或应用的单一仓库。Google、Meta 和 Microsoft 等公司多年来一直使用 monorepo,因为它简化了代码共享、统一了工具链,并使跨项目变更成为原子操作。然而,随着 monorepo 增长,构建时间会爆炸式增长。

Turborepo 作为一个智能任务运行器运行在包管理器工作区之上。它分析包之间的依赖图,确定哪些包受到更改影响,并以最优顺序、最大并行度执行任务。当任务以相同输入运行过时,Turborepo 在毫秒内重放缓存输出。

# Create a new Turborepo monorepo
npx create-turbo@latest my-monorepo

# Choose your package manager
? Which package manager do you want to use?
  > pnpm (recommended)
    npm
    yarn

# Resulting structure:
my-monorepo/
  apps/
    web/          # Next.js application
    docs/         # Documentation site
  packages/
    ui/           # Shared React component library
    config-ts/    # Shared TypeScript configuration
    config-eslint/ # Shared ESLint configuration
  turbo.json      # Turborepo configuration
  package.json    # Root workspace configuration
  pnpm-workspace.yaml  # pnpm workspace definition

Turborepo vs Nx vs Lerna 对比

Turborepo、Nx 和 Lerna 是 JavaScript 生态中最流行的三个 monorepo 工具,各有不同优势。

功能TurborepoNxLerna
设置复杂度极简(一个 turbo.json)中等(nx.json + project.json)极简(lerna.json)
本地缓存内置,内容感知内置,计算缓存通过 Nx 插件
远程缓存Vercel Remote Cache(免费层)Nx Cloud(免费层)通过 Nx Cloud
任务图turbo.json 管道project.json targets + nx.json基本拓扑排序
代码生成turbo gen(基础)丰富的生成器 + 插件无内置功能
Docker 裁剪turbo prune(内置)手动或社区插件手动
插件生态极简(专注工具)丰富(React、Angular、Node 等)极简
最适合追求速度和最少配置的团队需要全功能 monorepo 平台的企业团队简单 monorepo 或遗留项目

turbo.json 配置

仓库根目录的 turbo.json 文件是 Turborepo 的唯一配置文件,定义任务管道、缓存行为和全局依赖。

// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": [
    "**/.env.*local",
    ".env"
  ],
  "globalEnv": ["CI", "NODE_ENV"],
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "tsconfig.json", "package.json"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"],
      "env": ["NEXT_PUBLIC_API_URL", "DATABASE_URL"]
    },
    "test": {
      "dependsOn": ["build"],
      "inputs": ["src/**", "test/**", "vitest.config.*"],
      "outputs": ["coverage/**"],
      "env": ["TEST_DATABASE_URL"]
    },
    "lint": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", ".eslintrc.*", "eslint.config.*"]
    },
    "typecheck": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "tsconfig.json"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "clean": {
      "cache": false
    }
  }
}

管道与任务图

Turborepo 管道定义 monorepo 中任务间的关系。运行 turbo run build 时,Turborepo 读取管道配置理解任务依赖,然后以最优顺序、最大并行度执行。

关键是 dependsOn 字段。当任务列出 "^build" 作为依赖时,^ 表示依赖包依赖项的 build 任务,而非同一包中的 build 任务。这确保共享库在消费它们的应用之前构建。

# Run build for all packages (respects dependency graph)
turbo run build

# Run multiple tasks in the correct order
turbo run build test lint

# Run build only for the web app and its dependencies
turbo run build --filter=web

# Run build for packages affected by changes since main
turbo run build --filter=...[main...HEAD]

# Run tests only for packages that changed
turbo run test --filter=[HEAD^1]

# Visualize the task graph (opens in browser)
turbo run build --graph

# Dry run: show what would execute without running
turbo run build --dry=json

使用 Vercel Remote Cache 的远程缓存

远程缓存是 Turborepo 最具影响力的功能。启用后,构建产物在整个团队和 CI 基础设施间共享。开发者 A 本地构建的包,开发者 B 和 CI 管道可以直接复用。

Vercel 为 Turborepo 提供免费的远程缓存层。你也可以使用开源实现自托管远程缓存服务器。

# Step 1: Login to Vercel
turbo login

# Step 2: Link your repo to a Vercel project
turbo link

# Now all turbo commands use remote caching automatically
turbo run build
# >>> FULL TURBO (cache hit from remote)

# For CI: use a Vercel token instead of interactive login
# Set TURBO_TOKEN and TURBO_TEAM environment variables
TURBO_TOKEN=your_vercel_token \
TURBO_TEAM=your_team_slug \
turbo run build

# Disable remote caching temporarily
turbo run build --remote-only=false

# View cache status for a run
turbo run build --summarize

工作区设置:npm、pnpm 和 yarn

Turborepo 运行在包管理器工作区之上,不替代 npm、pnpm 或 yarn,而是用缓存和任务编排增强它们。

pnpm (Recommended)

# pnpm-workspace.yaml
packages:
  - "apps/*"
  - "packages/*"

# Root package.json
{
  "name": "my-monorepo",
  "private": true,
  "packageManager": "pnpm@9.15.0",
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint",
    "test": "turbo run test"
  },
  "devDependencies": {
    "turbo": "^2.4.0"
  }
}

npm Workspaces

// Root package.json for npm workspaces
{
  "name": "my-monorepo",
  "private": true,
  "workspaces": [
    "apps/*",
    "packages/*"
  ],
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev"
  },
  "devDependencies": {
    "turbo": "^2.4.0"
  }
}

共享包与内部包

内部包是组织良好的 monorepo 的基石,允许在应用间共享代码(UI 组件、工具函数、TypeScript 配置、ESLint 配置)而无需发布到 npm。

工作区协议(workspace:*)告诉包管理器从本地工作区解析依赖而非 npm 注册表,开发时共享包的更改立即反映在消费应用中。

// packages/ui/package.json
{
  "name": "@repo/ui",
  "version": "0.0.0",
  "private": true,
  "main": "./src/index.ts",
  "types": "./src/index.ts",
  "exports": {
    ".": "./src/index.ts",
    "./button": "./src/button.tsx",
    "./card": "./src/card.tsx"
  },
  "dependencies": {
    "react": "^19.0.0"
  },
  "devDependencies": {
    "@repo/config-typescript": "workspace:*",
    "typescript": "^5.7.0"
  }
}

// apps/web/package.json (consuming the shared package)
{
  "name": "web",
  "dependencies": {
    "@repo/ui": "workspace:*",
    "next": "^15.0.0",
    "react": "^19.0.0"
  }
}

// Usage in apps/web/src/app/page.tsx
import { Button } from "@repo/ui/button";
import { Card } from "@repo/ui/card";

export default function Home() {
  return (
    <Card>
      <Button onClick={() => alert("clicked")}>
        Get Started
      </Button>
    </Card>
  );
}

Monorepo 中的 TypeScript 配置

在 monorepo 中管理 TypeScript 需要分层配置策略。在内部包中创建共享基础 tsconfig,然后在每个应用和包中继承它。

// packages/config-typescript/base.json
{
  "compilerOptions": {
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  }
}

// packages/config-typescript/nextjs.json
{
  "extends": "./base.json",
  "compilerOptions": {
    "target": "ES2017",
    "lib": ["dom", "dom.iterable", "esnext"],
    "module": "esnext",
    "moduleResolution": "bundler",
    "jsx": "preserve",
    "noEmit": true,
    "incremental": true,
    "plugins": [{ "name": "next" }]
  }
}

// apps/web/tsconfig.json
{
  "extends": "@repo/config-typescript/nextjs.json",
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["next-env.d.ts", "src/**/*.ts", "src/**/*.tsx"],
  "exclude": ["node_modules"]
}

GitHub Actions CI/CD 集成

Turborepo 与 GitHub Actions 等 CI 平台无缝集成。关键优化是启用远程缓存,使 CI 运行受益于其他运行和本地开发产生的缓存产物。

# .github/workflows/ci.yml
name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  TURBO_TOKEN: \${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: \${{ vars.TURBO_TEAM }}

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 2

      - uses: pnpm/action-setup@v4
        with:
          version: 9

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: pnpm

      - run: pnpm install --frozen-lockfile

      - name: Build, lint, and test
        run: turbo run build lint test

      - name: Build only affected packages (PRs)
        if: github.event_name == 'pull_request'
        run: turbo run build --filter=...[origin/main...HEAD]

增量构建与内容哈希

Turborepo 通过计算任务输入的内容感知哈希来决定是否重新运行。输入包括包中的源文件、turbo.json 管道配置、env 中的环境变量以及依赖包的哈希值。

这种方法比基于时间戳的失效更可靠,因为它能捕获从 git 恢复或从其他机器复制文件的情况。

# View the hash inputs for a task
turbo run build --dry=json

# Output includes hash details:
# {
#   "taskId": "web#build",
#   "hash": "a1b2c3d4e5f6",
#   "inputs": {
#     "src/app/page.tsx": "sha256:...",
#     "package.json": "sha256:...",
#     "tsconfig.json": "sha256:..."
#   },
#   "hashOfExternalDependencies": "sha256:...",
#   "environmentVariables": {
#     "NEXT_PUBLIC_API_URL": "sha256:..."
#   },
#   "cache": {
#     "status": "HIT",
#     "source": "REMOTE"
#   }
# }

# Force re-execution (ignore cache)
turbo run build --force

# Generate a summary of cache performance
turbo run build --summarize

Docker 构建裁剪

为 monorepo 应用构建 Docker 镜像很棘手,因为 Docker COPY 会复制整个仓库。turbo prune 命令生成仅包含特定应用所需文件的精简子集。

# Dockerfile for a monorepo app using turbo prune
FROM node:20-alpine AS base
RUN apk add --no-cache libc6-compat
RUN corepack enable && corepack prepare pnpm@9 --activate

# Stage 1: Prune the monorepo for the target app
FROM base AS pruner
WORKDIR /app
COPY . .
RUN npx turbo prune web --docker

# Stage 2: Install dependencies
FROM base AS installer
WORKDIR /app
COPY --from=pruner /app/out/json/ .
COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN pnpm install --frozen-lockfile

# Stage 3: Build the application
COPY --from=pruner /app/out/full/ .
RUN pnpm turbo run build --filter=web

# Stage 4: Production image
FROM base AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
USER nextjs
COPY --from=installer /app/apps/web/.next/standalone ./
COPY --from=installer /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=installer /app/apps/web/public ./apps/web/public
CMD ["node", "apps/web/server.js"]

生成器:脚手架新包

Turborepo 包含代码生成功能(turbo gen),帮助你在 monorepo 中创建新包和应用。生成器底层使用 Plop 模板。

# Generate a new package interactively
turbo gen workspace

# Create a custom generator
# turbo/generators/config.ts
import type { PlopTypes } from "@turbo/gen";

export default function generator(plop: PlopTypes.NodePlopAPI) {
  plop.setGenerator("react-package", {
    description: "Create a new React package",
    prompts: [
      {
        type: "input",
        name: "name",
        message: "Package name (e.g., button):",
      },
    ],
    actions: [
      {
        type: "add",
        path: "packages/{{ name }}/package.json",
        templateFile: "templates/package.json.hbs",
      },
      {
        type: "add",
        path: "packages/{{ name }}/src/index.ts",
        template: 'export * from "./{{ name }}";',
      },
      {
        type: "add",
        path: "packages/{{ name }}/tsconfig.json",
        templateFile: "templates/tsconfig.json.hbs",
      },
    ],
  });
}

# Run the custom generator
turbo gen react-package

环境变量处理

环境变量是缓存等式的关键部分。如果构建依赖于 API_URL 等环境变量,需要在 turbo.json 中声明以便变量更改时使缓存失效。

env 键是每个任务的,只影响该任务的哈希。globalEnv 键应用于管道中的所有任务。

// turbo.json - Environment variable configuration
{
  "globalEnv": [
    "CI",
    "NODE_ENV",
    "VERCEL_URL"
  ],
  "globalDependencies": [
    ".env",
    ".env.local"
  ],
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "env": [
        "NEXT_PUBLIC_API_URL",
        "NEXT_PUBLIC_GA_ID",
        "DATABASE_URL"
      ]
    },
    "test": {
      "env": [
        "TEST_DATABASE_URL",
        "MOCK_API"
      ]
    }
  }
}

# Use environment variable passthrough for wildcards
# turbo.json supports prefix matching:
# "env": ["NEXT_PUBLIC_*"] matches all NEXT_PUBLIC_ variables

迁移指南:将 Turborepo 添加到现有 Monorepo

在现有 monorepo 中采用 Turborepo 很简单,因为它与现有的包管理器和脚本配合工作,无需重构仓库。

  1. 步骤 1:在 monorepo 根目录安装 Turborepo 作为开发依赖。
  2. 步骤 2:在仓库根目录创建 turbo.json 文件定义任务管道。
  3. 步骤 3:更新根 package.json 脚本使用 turbo run 替代包管理器工作区命令。
  4. 步骤 4:运行 turbo login 和 turbo link 启用远程缓存。
  5. 步骤 5:更新 CI 管道使用 turbo run 配合 --filter 标志。
# Step 1: Install Turborepo
pnpm add -Dw turbo

# Step 2: Create turbo.json (see configuration section above)

# Step 3: Update root package.json scripts
# Before:
#   "build": "pnpm -r run build"
#   "test": "pnpm -r run test"
# After:
#   "build": "turbo run build"
#   "test": "turbo run test"

# Step 4: Enable remote caching
turbo login
turbo link

# Step 5: Run your first cached build
turbo run build
# First run: executes everything normally
# Second run: >>> FULL TURBO (all cache hits)

最佳实践

  • 将 turbo.json 作为任务依赖的唯一真实来源,避免在 package.json 脚本中重复管道逻辑。
  • 始终在 turbo.json 的 env 或 globalEnv 中声明影响构建输出的环境变量。
  • 内部包依赖使用 workspace:* 协议确保开发时本地解析。
  • 从第一天起启用远程缓存,即使是个人开发者也能受益于 CI 缓存产物。
  • Docker 构建使用 turbo prune 最小化镜像大小并最大化层缓存。
  • 将共享代码结构化为专注的内部包(ui、utils、config-typescript、config-eslint)。
  • 开发时使用 --filter 为特定包运行任务,而非运行所有内容。
  • 使用 package.json 中的 packageManager 或 .turbo/config.json 固定团队的 Turborepo 版本。
  • 使用 turbo run dev 设置监视模式,利用持久任务和变更自动重启。
  • 使用 --summarize 分析任务执行以识别瓶颈和优化管道依赖。

常见问题

Turborepo 用来做什么?

Turborepo 是面向 JavaScript 和 TypeScript monorepo 的构建系统和任务运行器。它通过缓存任务结果和仅重新执行输入已更改的任务来加速构建、测试和代码检查。

Turborepo 缓存如何工作?

Turborepo 基于源文件、环境变量和依赖哈希为每个任务计算内容感知哈希。如果哈希匹配之前的运行,Turborepo 重放缓存的输出文件和终端日志。

Turborepo 比 Nx 好吗?

Turborepo 是专注的构建系统,配置最少,擅长缓存和任务调度。Nx 是全功能 monorepo 平台,有丰富的代码生成器和框架插件。简单选 Turborepo,全面管理选 Nx。

Turborepo 支持 pnpm 吗?

支持。Turborepo 原生支持 pnpm 工作区,pnpm 因其严格的依赖隔离和高效的磁盘存储而成为推荐的包管理器。

什么是 Turborepo 远程缓存?

远程缓存将构建产物存储在共享缓存中(默认 Vercel Remote Cache),团队成员和 CI 可以复用缓存结果而非从头构建。通常减少 65-85% 的 CI 时间。

如何从零开始创建 Turborepo monorepo?

运行 npx create-turbo@latest 创建新的 Turborepo monorepo,包括 apps 目录、packages 目录、turbo.json 配置和工作区配置。也可以在现有 monorepo 中安装 turbo 并创建 turbo.json。

Turborepo 能配合 Docker 使用吗?

可以。turbo prune 命令专为 Docker 构建设计,生成仅包含特定应用所需文件和依赖的精简子集,产生更小的镜像和更好的层缓存。

Turborepo 免费吗?

Turborepo 是 MIT 许可的开源项目,免费使用。Vercel 提供免费的远程缓存层。大型团队可选择 Vercel 付费计划或使用开源实现自托管远程缓存。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

{ }JSON FormatterTSJSON to TypeScriptY→YAML to JSON Converter

相关文章

pnpm 完全指南:快速且节省磁盘的包管理器 (2026)

完整的 pnpm 指南,涵盖内容寻址存储、工作区、严格依赖解析、补丁、覆盖、CI/CD、Docker、从 npm/yarn 迁移、Catalogs 和性能基准测试。

Next.js 高级指南:App Router、服务端组件、数据获取、中间件与性能优化

完整的 Next.js 高级指南,涵盖 App Router 架构、React 服务端组件、流式 SSR、数据获取模式、中间件、路由处理器、并行和拦截路由、缓存策略、ISR、图片优化和部署最佳实践。

CI/CD指南:GitHub Actions、GitLab CI、Docker和部署流水线

掌握CI/CD流水线。涵盖GitHub Actions工作流、GitLab CI、Docker构建、部署策略(蓝绿、金丝雀)、密钥管理、单仓库CI和流水线优化。