第一集:什么是Turborepo & 核心功能
Turborepo 是什么
Turborepo is an intelligent build system optimized for JavaScript and TypeScript codebases.
Turborepo 是一个针对 JavaScript 和 TypeScript 代码库优化的智能构建系统。
核心功能
缓存任务
每个 JavaScript 或 TypeScript 代码库都需要运行 package.json 脚本,例如构建、测试和 lint。 在 Turborepo 中,将这些称为任务。
Turborepo 可以缓存任务的结果和日志 - 从而为缓慢的任务带来巨大的加速。
如何配置缓存
「TO CACHE」 或者「NOT TO CACHE」
通过 Turbo.json 内的 pipeline.<task>.cache 控制是否进行对该 task 进行缓存
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"lint": {}
// 或者 turborepo 默认cache = true, 所以直接按上面一行配置即可
"lint": {
cache: true
}
// 配置不缓存,即永远执行
"lint": {
cache: false
}
}
}
在上述示例中,我们配置了缓存 lint 任务。 但是,由于只指定了缓存键,没有配置到底需要缓存什么,因此turborepo 默认唯一被缓存的是终端输出。
以下是一些不建议使用缓存的任务:
- 执行速度极快的任务。(假设该任务可以在小于网络往返时间(例如 100 毫秒)的时间内执行,如果使用远程缓存,有悖我们快速执行的预期。)
- 产出资产巨大的任务。 (如果运行任务的结果是生成 Docker 容器,则创建缓存工件、上传它和下载它所花费的时间可能会超过重新生成它的时间。)
- 非转换性文件系统操作。 如果任务是“将一大堆图像从一个目录移动到另一个目录”,则该任务可能需要一段时间,但在本地执行此操作的过程始终比缓存和恢复移动的资源更快。
- 有自己缓存的任务。 有些任务有自己的内部缓存行为,例如 Docker 的 Layer Cache。 在大多数情况下,这些二级缓存与 Turborepo 协同工作,但在某些情况下,配置变得极其复杂。
配置缓存文件
Turborepo 默认缓存所有的 console output,对于 build 结果、test 结果需要我们自己配置到底需要哪些缓存哪些文件。 我们以配置 build 结果目录的缓存为例:
将 build 后产生的 dist 文件进行缓存
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"outputs": ["dist/**"]
}
}
}
缓存多个项目不同build目录,例项目A build结果目录为dist,项目B build结果目录为lib
方法一
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"outputs": ["dist/**", "lib/**"]
}
}
}
以上配置可以将 build 后产生的 dist 或者 lib 文件进行缓存。 需要注意的是官网有提到文件夹必须是空的这种模式才可以正常工作。
方法二
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"A#build": {
"outputs": ["dist/**"]
},
"B#build": {
"outputs": ["lib/**"]
}
}
}
必须使用 /** 运算符指定目录内的所有文件。 简单地指定目录名称(例如 lib)将仅包含目录本身,而不包含其内容。
排除某些文件
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"app#build": {
"outputs": [".next/**", "!.next/cache/**"],
}
}
}
使用「!」, 排除任何匹配的内容。
依赖文件输入(File Input)
默认情况下,当工作区中的任何文件发生更改时,该工作区被视为已更新。 但是,并非整个存储库内的每个文件更改都应导致重新运行任务。 Turborepo 为您提供了工具,确保您可以定义每个重要的文件。
全局文件(Global Files)
这里指的是可能影响每个工作区(workspace)的文件,例如 tsconfig.json 、eslintrc.json等等,我们可以将该文件配置在 globalDependencies 中
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["tsconfig.json"],
"pipeline": {
"type-check": {}
}
}
对于globalDependencies中配置的文件的改变,都将导致在turborepo 中的每个任务都将重新运行。turborepo 默认将turbo.json 和 package.json 配置为 globalDependencies。
工作区文件(Workspace Files)
除了出现在任何工作区之外的全局文件之外,还可以指定要在每个工作区中包含哪些文件。只等这些文件的作用是配置每个工作区进行hash的标准。
每个工作区的 package.json 和turbo.json(如果存在)的内容会自动考虑用于是否当作哈希用于缓存, 该行为是不可配置进行改变的。
对于其他文件 Turborepo 的默认行为是检查存储库并识别哪些文件应包含在哈希计算中。 Turborepo 通常使用 Git 来识别要考虑的文件:
自定义包含文件
例如,在许多 build 任务中,唯一依赖的文件可能出现在 src 目录中。 或者,测试任务可能仅依赖于 src 和 test 目录中的文件。 可以指定传递给 pipeline.<task>.inputs 的 glob 模式来进行配置:
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"inputs": ["src/**"]
},
"test": {
"inputs": ["src/**", "test/**"]
}
}
}
定义任务依赖关系
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"inputs": ["src/**"]
},
"test": {
// This task dependsOn build...
"dependsOn": ["build"],
// ...which means that it does not need to specify "src/**" here:
"inputs": ["test/**"]
}
}
}
使用此模式可以使您不必为每个任务重复枚举文件全局列表。
其中有一行配置 "build": { "dependsOn": ["^build"], "inputs": ["src/**"] }, 该行配置作用是:工作区的build任务仅应在其依赖的所有工作区的build任务完成后运行。
其中工作空间依赖项是指的是package.json 中的dependency 和devDependency ^ 符号显式声明该任务取决于它所依赖的工作区中的任务。 详解请见如下链接👇
环境变量(Environment Variable Inputs)
由于环境变量不会在源代码中捕获,因此它们不容易在计算机之间共享。 为确保开发人员和 CI 在不同机器上设置一致的环境是一项艰巨的任务。 Turborepo 提供了应用程序所依赖的环境变量的工具。
配置(Configuration)
Turborepo 能够在全局级别和“管道”级别直接枚举应考虑将哪些环境变量用作哈希键。
{
"$schema": "https://turbo.build/schema.json",
"globalEnv": ["API_BASE_URL","NEXT_PUBLIC_*", "!NEXT_PUBLIC_GIT_*"],
"pipeline": {
"test": {
"env": ["MOCHA_REPORTER"] },
//...
}
}
在此示例中,我们可以想象一个应用程序在测试环境、临时环境和生产环境中具有不同的 API_BASE_URL。 此配置将确保 API_BASE_URL 的值被考虑用于哈希,如果不同,则不会从缓存中恢复任务。
另外,还支持通配符进行配置例如"NEXT_PUBLIC_", "!NEXT_PUBLIC_GIT_"
严格模式和非严格模式( Loose & Strict Environment Modes)
turbo默认的是非严格模式,不过滤任何环境变量。 因此,机器中的所有环境变量都可供每个任务使用。 这确保了最大的兼容性,同时接受任务隐式访问未指定的环境变量的一些风险。 用户可能会使用不同的环境变量值运行任务,但会错误地看到 FULL TURBO,因为在 Turbo.json 中未配置环境变量。
在严格模式中,只有重要的系统环境变量和在turbo.json中配置的环境变量才可供任务使用。严格模式可以通过turbo --env-mode=strict 启用,过滤掉环境变量。
Turborepo 通过推断您是否希望从配置中获得严格行为,从而逐步采用严格模式。 “globalPassThroughEnv”:[]。 每个任务都启用严格模式。 没有环境变量被列入允许名单。“passThroughEnv”:[]。 为特定任务启用严格模式。 没有环境变量被列入允许名单。
「缓存」依据
这里官网解释的比较简单,主要根据「代码全局状态」、「工作区相关其他因素」。
其中「代码全局状态」包括:
- 满足 globalDependency 中的 glob 模式的任何文件内容的哈希值,(globalDependency 可以在turbo的配置文件 turbo.json 中找到)
- globalEnv 中列出的环境变量的值
- Turbo.json、package.json 和任何锁定文件中的信息
- ...
「工作区相关其他因素」包括:
-
工作区文件夹中所有版本控制文件的内容的哈希值(或与输入配置的 glob 匹配的文件)
-
pipeline 中指定的配置输出(例如build的output配置)
-
所有已安装依赖项、devDependency 和 optionalDependency 的已解析版本集
-
工作区任务名称(workspace 的 package.json name)
-
pipeline.<task>.env 列表中指定的环境变量键值对的排序列表
-
...
未完待续...