配置任务
Turborepo 将始终按照你在turbo.json
配置和包图中描述的顺序运行任务,尽可能并行化工作以确保一切运行得尽可能快。这比一次运行一个任务要快,这也是 Turborepo 如此快速的原因之一。
例如,yarn workspaces run lint && yarn workspaces run test && yarn workspaces run build
看起来会是这样:


但是,要使用 Turborepo 更快地完成相同的工作,你可以使用 turbo run lint test build
:


入门
根 turbo.json
文件是你注册 Turborepo 将运行的任务的地方。一旦你定义了任务,你就可以使用turbo run
运行一个或多个任务。
- 如果你是从头开始,我们建议使用
create-turbo
创建一个新的仓库并编辑turbo.json
文件来尝试本指南中的代码片段。 - 如果你正在现有仓库中采用 Turborepo,请在仓库的根目录中创建一个
turbo.json
文件。你将使用它来了解本指南中的其余配置选项。
定义任务
tasks
对象中的每个键都是可以由 turbo run
执行的任务。Turborepo 将在你的包中搜索与任务同名的 package.json
中的脚本。
要定义任务,请在 turbo.json
中使用tasks
对象。例如,一个没有依赖项和输出的名为 build
的基本任务可能看起来像这样:


如果你现在运行 turbo run build
,Turborepo 将并行运行所有包中的所有 build
脚本,并且不会缓存任何文件输出。**这很快就会导致错误。**你缺少一些重要的部分来使其按你期望的方式工作。
按正确顺序运行任务
dependsOn
键用于指定在不同任务开始运行之前必须完成的任务。例如,在大多数情况下,你希望在运行应用程序的 build
脚本之前完成库的 build
脚本。为此,你可以使用以下 turbo.json
:


现在你有了你期望的构建顺序,在构建依赖项之前构建依赖者。
**但要小心。**此时,你还没有标记构建输出以进行缓存。要这样做,请跳转到指定输出部分。
使用 ^
依赖依赖项中的任务
^
微语法告诉 Turborepo 从依赖图的底部开始运行任务。如果你的应用程序依赖于名为 ui
的库,并且该库有一个 build
任务,那么 ui
中的 build
脚本将首先运行。一旦它成功完成,你的应用程序中的 build
任务就会运行。
这是一个重要的模式,因为它确保你的应用程序的 build
任务将拥有编译所需的所有必要依赖项。当你的依赖图增长到具有多个层次的任务依赖关系的更复杂结构时,这个概念也适用。
依赖同一包中的任务
有时,你可能需要确保同一包中的两个任务按特定顺序运行。例如,你可能需要在运行库中的 test
任务之前运行该库中的 build
任务。为此,将脚本指定为 dependsOn
键中的普通字符串(不带 ^
)。


依赖特定包中的特定任务
你还可以指定依赖于特定包中的单个任务。在下面的示例中,在运行任何 lint
任务之前必须运行 utils
中的 build
任务。


你也可以更具体地指定依赖任务,将其限制在某个特定的包:


使用此配置,只有在 utils
包中的 build
任务完成后,才能运行 web
包中的 lint
任务。
无依赖项
某些任务可能没有任何依赖项。例如,查找 Markdown 文件中拼写错误的任务可能不需要关心其他任务的状态。在这种情况下,你可以省略 dependsOn
键或提供一个空数组。


指定 outputs
Turborepo 缓存你的任务的输出,这样你就永远不会做两次相同的工作。我们将在 缓存指南 中深入讨论这个问题,但让我们先确保你的任务配置正确。
outputs
键告诉 Turborepo 在任务成功完成时应该缓存哪些文件和目录。如果没有定义此键,Turborepo 将不会缓存任何文件。在后续运行中命中缓存将不会恢复任何文件输出。
以下是常见工具的输出示例:


Glob 模式相对于包,所以 dist/**
将处理每个包分别输出的 dist
。有关构建 outputs
键的 glob 模式的更多信息,请参见glob 规范。
指定 inputs
inputs
键用于指定你想要包含在任务的缓存哈希中的文件。默认情况下,Turborepo 将包含包中所有由 Git 跟踪的文件。但是,你可以使用 inputs
键更具体地指定要包含在哈希中的文件。
例如,查找 Markdown 文件中拼写错误的任务可以这样定义:


现在,只有 Markdown 文件的更改才会导致 spell-check
任务缓存未命中。
此功能会退出所有 Turborepo 的默认 inputs
行为,包括跟随源代码控制跟踪的更改。这意味着你的 .gitignore
文件将不再被遵守,你需要确保不会用你的 glob 模式捕获这些文件。
要恢复默认行为,请使用 $TURBO_DEFAULT$
微语法。
使用 $TURBO_DEFAULT$
恢复默认值
默认的 inputs
行为通常是你想要的任务行为。但是,通过微调你的 inputs
来忽略已知不会影响任务输出的文件的更改,你可以提高某些任务的缓存命中率。
因此,你可以使用 $TURBO_DEFAULT$
微语法来微调默认的 inputs
行为:


在这个任务定义中,Turborepo 将对 build
任务使用默认的 inputs
行为,但会忽略对 README.md
文件的更改。如果 README.md
文件被更改,任务仍会命中缓存。
注册根任务
你也可以使用 turbo
运行工作空间根目录中的 package.json
中的脚本。例如,你可能想要运行 lint:root
任务来处理工作空间根目录中的文件,以及每个包中的 lint
任务:


现在根任务已注册,turbo run lint:root
将运行该任务。你也可以运行 turbo run lint lint:root
来运行所有的代码检查任务。
何时使用根任务
- 工作空间根目录的代码检查和格式化:你可能在工作空间根目录中有需要代码检查和格式化的代码。例如,你可能想要在根目录运行 ESLint 或 Prettier。
- 增量迁移:当你迁移到 Turborepo 时,你可能有一些还没有移动到包中的脚本。在这种情况下,你可以创建一个根任务来开始迁移,稍后再将任务分散到包中。
- 没有包作用域的脚本:你可能有一些在特定包的上下文中没有意义的脚本。这些脚本可以注册为根任务,这样你仍然可以使用
turbo
运行它们以获得缓存、并行化和工作流程的目的。
高级用例
使用包配置
包配置是直接放在包中的 turbo.json
文件。这允许包为其自己的任务定义特定的行为,而不影响仓库的其余部分。
在有多个团队的大型单体仓库中,这允许团队对自己的任务有更大的控制权。要了解更多信息,请访问包配置文档
执行副作用
某些任务应该始终运行,无论如何,比如缓存构建后的部署脚本。对于这些任务,在你的任务定义中添加 "cache": false
。


可以并行运行的依赖任务
某些任务尽管依赖于其他包,但可以并行运行。代码检查器就是这样的任务的一个例子,因为代码检查器不需要等待依赖项中的输出就能成功运行。
因此,你可能会倾向于这样定义你的 check-types
任务:


这会并行运行你的任务 - 但没有考虑依赖项中的源代码更改。这意味着你可以:
- 对你的
ui
包的接口进行破坏性更改。 - 运行
turbo check-types
,在依赖于ui
的应用程序包中命中缓存。
这是不正确的,因为应用程序包会显示成功的缓存命中,尽管它还没有更新以使用新的接口。在你的编辑器中手动检查应用程序包的 TypeScript 错误可能会显示错误。
因此,你对 check-types
任务定义做了一个小的更改:


如果你再次测试在 ui
包中进行破坏性更改,你会注意到缓存行为现在是正确的。然而,任务不再并行运行。
要同时满足这两个要求(正确性和并行性),你可以向你的任务图引入传输节点:


这些传输节点使用一个不匹配任何 package.json
中脚本的任务在你的包依赖关系之间创建关系。因此,你的任务可以并行运行并且意识到它们的内部依赖关系的更改。
在这个例子中,我们使用了名称 transit
-
但你可以将任务命名为任何在你的工作空间中还不是脚本的名称。
下一步
在配置 turbo.json
文档中还有更多选项可用,你将在接下来的指南中探索这些选项。现在,你可以开始运行一些任务来看看基础知识是如何工作的。