Skip to content

Turborepo

Turborepo 是面向 Monorepo 的构建任务编排与缓存工具。

它本身不负责安装依赖或管理包版本,而是建立在 pnpmnpmYarn 等包管理器提供的 Workspace 能力之上,统一调度多个 package 中的 buildlinttesttypecheckdev 等任务。

为什么需要 Turborepo

在一个包含多个应用和共享包的仓库中,例如:

bash
apps/
  web
  admin
  api
packages/
  ui
  utils
  config

每个应用或包通常都有各自的 package.json 和脚本。Turborepo 可以根据这些包之间的依赖关系,自动决定任务执行顺序,并尽量只执行真正受改动影响的任务。

pnpm Workspace 的职责

pnpm Workspace 主要负责包与依赖管理:

  • 统一安装和管理仓库内的依赖。
  • 将多个子项目识别为同一个 Workspace。
  • 支持通过 workspace:* 引用仓库内的本地包。
  • 自动建立本地 package 之间的软链接。
  • 统一执行 workspace 范围内的脚本。

例如,apps/web 依赖 packages/ui

json
{
  "dependencies": {
    "@repo/ui": "workspace:*"
  }
}

pnpm 会将 @repo/ui 链接到本地的 packages/ui,应用可以像使用普通 npm 包一样使用仓库内部的共享组件或工具库。

Turborepo 的职责

Turborepo 主要解决“任务如何执行”的问题:

  • 根据 package 依赖关系安排任务顺序。
  • 自动并行执行互不依赖的任务。
  • 仅执行受当前改动影响的任务。
  • 缓存任务结果,避免重复构建。
  • 支持团队共享远程缓存。
  • 为 CI 提供更快、更稳定的构建流程。

例如,apps/web 依赖 packages/ui。执行:

bash
pnpm turbo run build

Turborepo 会先构建 packages/ui,再构建 apps/web

如果 packages/ui 没有变化,并且此前的构建结果仍然有效,Turborepo 可以直接命中缓存,跳过重新构建。

安装与初始化

在已有 pnpm Workspace 中安装 Turborepo:

bash
pnpm -w add -D turbo

在根目录 package.json 中添加仓库级脚本:

json
{
  "scripts": {
    "dev": "turbo dev",
    "build": "turbo build",
    "lint": "turbo lint",
    "test": "turbo test",
    "typecheck": "turbo typecheck"
  }
}

子包需要各自声明对应脚本。Turborepo 只负责任务编排,不会自动生成 buildlinttest 等脚本。

json
{
  "name": "@repo/web",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "typecheck": "vue-tsc --noEmit"
  }
}

然后在根目录创建 turbo.json,声明任务依赖、缓存产物和开发任务行为。

turbo.json

Turborepo 通常通过根目录的 turbo.json 描述任务规则:

json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "test": {
      "dependsOn": ["^build"],
      "outputs": ["coverage/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

字段说明:

  • dependsOn: ["^build"]:当前 package 执行 build 前,需要先完成依赖包的 build
  • outputs:声明任务生成的产物目录,Turborepo 会将这些产物纳入缓存。
  • cache: false:不缓存该任务,通常用于本地开发服务。
  • persistent: true:任务会持续运行,例如 Vite、Next.js 或 Node 开发服务器。

缓存机制

Turborepo 会根据任务相关信息生成缓存键,通常包括:

  • 当前 package 的源码文件。
  • package.json 与锁文件。
  • 环境变量。
  • 任务命令。
  • turbo.json 配置。
  • 依赖 package 的构建结果。

只要这些输入没有变化,Turborepo 就可以复用之前的任务结果。

第一次执行:

bash
pnpm turbo run build

会正常构建所有需要构建的 package。

第二次在代码未变化的情况下执行相同命令时,Turborepo 可以直接从本地缓存恢复构建产物,通常明显快于重新构建。

本地缓存与远程缓存

默认情况下,Turborepo 使用本地缓存,缓存通常保存在仓库中的 .turbo 目录。

多人协作或 CI 场景可以启用远程缓存。某位开发者或 CI 已经完成过的构建结果,其他开发者或后续 CI 任务可以直接复用,无需再次执行相同构建。

远程缓存适合以下场景:

  • 多人维护同一个 Monorepo。
  • GitHub Actions、GitLab CI 等持续集成环境。
  • 应用较多、构建时间较长。
  • 频繁执行 buildlinttesttypecheck

与 pnpm Workspace 的关系

工具主要职责
pnpm Workspace管理 package、依赖安装、本地包链接、Workspace 范围脚本执行
Turborepo编排任务依赖、并行执行、增量执行、本地缓存、远程缓存

可以理解为:

  • pnpm Workspace 解决“仓库中有哪些包,以及这些包如何互相依赖”。
  • Turborepo 解决“这些包的构建、检查、测试任务应该以什么顺序、什么范围、高效地执行”。

因此,常见组合是:

bash
pnpm Workspace + Turborepo

pnpm 负责包管理,Turborepo 负责任务调度与构建加速。两者并不冲突,而是互补关系。

基于 MIT 许可发布