Skip to content

安装

bash
pnpm add turbo

配置

新建turbo.json,在里面配置task任务后,你就可以在package.json中使用turbo <task>进行任务了,可根据场景配置构建缓存、依赖分析等。

建议结合pnpm-workspace使用

如果要统一相同的依赖可以结合pncat进行,不过得pnpm9以上才行

Turborepo 任务配置笔记

一、核心认知

  1. 作用:通过 turbo.json 和包图定义任务执行规则,支持并行处理,比传统串行命令(如 yarn workspaces run lint && test && build)更高效
  2. 核心命令:turbo run [任务名](执行已配置任务)

二、基础准备

1. 关键文件

  • 配置入口:根目录 turbo.json(注册任务的核心文件)
  • 关联文件:package.json(存储脚本,任务名需与脚本名一致)、apps(应用目录)、packages(内部包目录)

2. 初始化方式

场景操作方式
全新仓库使用 create-turbo 创建,直接编辑 turbo.json
现有仓库手动在根目录创建 turbo.json

三、核心配置:任务定义

1. 基础结构

plain
{
  "tasks": {
    "任务名": {
      "dependsOn": [],  // 任务依赖(控制执行顺序)
      "outputs": [],    // 缓存输出文件/目录
      "inputs": [],     // 影响缓存哈希的输入文件
      "cache": true     // 是否缓存(默认true)
    }
  }
}

⚠️ 注意:仅定义空任务(如 "build": {})会导致并行执行无缓存,易出错,需补充关键配置

2. 任务顺序控制(dependsOn)

(1)依赖「依赖项」的任务(^ 微语法)

  • 作用:从依赖图底部执行,确保依赖包先完成任务(如库先 build,应用再 build)
  • 示例:
plain
{
  "tasks": {
    "build": { "dependsOn": ["^build"] }  // ui库build → 应用build
  }
}

(2)依赖「同一包」的任务

  • 作用:同一包内任务按顺序执行(如先 build 再 test)
  • 示例:
plain
{
  "tasks": {
    "test": { "dependsOn": ["build"] }  // 同一包:build → test
  }
}

(3)依赖「特定包的特定任务」

  • 格式:"包名#任务名",支持限定特定包的依赖
  • 示例:
    • 所有 lint 依赖 utils 的 build:"lint":
    • web 包 lint 依赖 utils 的 build:"web#lint":

(4)无依赖任务

  • 场景:无需其他任务前置(如 Markdown 拼写检查)
  • 配置:省略 dependsOn 或设为空数组
  • 示例:"spell-check":

3. 缓存输出配置(outputs)

  • 作用:指定任务成功后需缓存的文件 / 目录,未配置则不缓存
  • 规则:Glob 模式(相对包路径),支持排除(! 前缀)
  • 示例(Next.js 项目):
plain
{
  "tasks": {
    "build": { "outputs": [".next/**", "!.next/cache/**"] }
  }
}

4. 缓存输入配置(inputs)

  • 作用:定义影响缓存哈希的文件,默认包含包内 Git 跟踪文件
  • 两种配置方式:
配置类型操作方式示例
完全自定义直接指定文件 / Glob,覆盖默认"spell-check":
微调默认用 $TURBO_DEFAULT$ 保留默认,补充排除"build":

5. 根任务注册

  • 作用:运行工作区根目录 package.json 中的脚本
  • 格式:"//#根任务名": {}
  • 示例:
plain
{
  "tasks": {
    "lint": { "dependsOn": ["^lint"] },
    "//#lint:root": {}  // 注册根目录 lint:root 脚本
  }
}
  • 执行命令:turbo run lint:root(单独运行)、turbo run lint lint:root(同时运行所有 lint)
  • 适用场景:根目录代码 lint / 格式化、Turbo 迁移过渡、无包范围的脚本

四、高级用例

1. 包级配置

  • 操作:在包内创建 turbo.json,自定义该包任务行为
  • 优势:大型 monorepo 中,各团队独立控制自己包的任务,不影响全局

2. 长时任务(with 关键字)

  • 场景:长时任务需其他任务同时运行(如 web 开发时需 api 服务)
  • 配置:需加 persistent: true(任务持续运行)、cache: false(不缓存)
  • 示例:
plain
// apps/web/turbo.json
{
  "tasks": {
    "dev": {
      "with": ["api#dev"],  // 运行 web#dev 时,同时运行 api#dev
      "persistent": true,
      "cache": false
    }
  }
}

3. 副作用任务(强制运行)

  • 场景:需始终执行的任务(如构建后部署)
  • 配置:"cache": false(跳过缓存,每次强制运行)
  • 示例:
plain
{
  "tasks": {
    "deploy": {
      "dependsOn": ["^build"],  // 依赖所有包的 build
      "cache": false
    }
  }
}

4. 并行依赖任务(Transit Nodes)

  • 问题:如 check-types 任务,需兼顾「并行运行」和「感知依赖项更改」
  • 解决方案:引入「中转任务」(无实际脚本,仅建立依赖关系)
  • 示例:
plain
{
  "tasks": {
    "transit": { "dependsOn": ["^transit"] },  // 中转任务,建立依赖链
    "check-types": { "dependsOn": ["transit"] }  // 依赖中转任务,实现并行+正确性
  }
}

筛选器 filter

过滤器可筛选任务,仅运行任务图的子集,常见用法如下:

按包筛选turbo build --filter=@acme/web
turbo run web#build
turbo run web#build docs#lint
仅为指定包运行任务,也可直接在 CLI 命令中为不同包指定不同任务,无需使用--filter
按目录筛选turbo lint --filter="./packages/utilities/*"通过 glob 模式,聚焦目录下相关包的任务
包含依赖项筛选turbo build --filter=...ui为指定包及其依赖项运行任务,适用于验证包更改是否影响依赖项
包含依赖筛选turbo dev --filter=web...将范围限定为指定包及其所依赖的所有包
按源代码控制更改筛选turbo build --filter=[HEAD^1]
(与上一提交比较);turbo build --filter=[main...my-feature]
(与主分支比较);turbo build --filter=[a1b2c3d...e4f5g6h]
(按 SHA 比较特定提交);turbo build --filter=[your-feature...my-feature]
(按分支名比较特定提交)
仅为受源代码控制更改影响的包运行任务,过滤器需用[]括起
组合过滤器turbo build --filter=...ui --filter={./packages/*} --filter=[HEAD^1]多个过滤器组合为并集,任务图包含与任一过滤器匹配的任务

根据一些.gitignore的信息,以及turbo.json的输入配置,计算作为输入文件的实际内容hash,判断是否缓存。

为什么不用时间戳?如果touch了,内容没变化但是缓存就失效了