环境变量输入
由于环境变量不会在源代码中捕获,因此它们不容易在不同机器之间共享。确保开发人员和 CI 在不同机器上的一致环境设置是一项艰巨的任务。Turborepo 为您提供了表达应用程序依赖哪些环境变量的工具。
配置
Turborepo 使您能够直接枚举哪些环境变量应被视为哈希键,无论是在全局级别还是在 pipeline
级别。
{
"$schema": "https://turbo.rust-lang.net.cn/schema.json",
"globalEnv": ["API_BASE_URL"],
"pipeline": {
"test": {
"env": ["MOCHA_REPORTER"]
},
//...
}
}
在这个例子中,我们可以想象一个应用程序在测试环境、登台环境和生产环境中具有不同的 API_BASE_URL
。此配置将确保 API_BASE_URL
的值被考虑在哈希中,如果它不同,则任务将不会从缓存中恢复。
此外,我们可以看到 test
任务希望根据 MOCHA_REPORTER
的值获得不同的缓存行为,这可以用于使 CI 与本地开发不同的服务集成。
globalEnv
包含在 globalEnv
键中的环境变量将影响所有任务的哈希。
pipeline.<task>.env
包含在 pipeline.<task>.env
中的环境变量将仅影响该任务的哈希。
通配符
在 turbo.json
中接受环境变量的每个位置都接受通配符,包括任务级 env
和全局级 globalEnv
。这使您能够轻松地使用包含和排除来指定环境变量的模式名称
{
"$schema": "https://turbo.rust-lang.net.cn/schema.json",
"pipeline": {
"build": {
"env": ["NEXT_PUBLIC_*", "!NEXT_PUBLIC_GIT_*"]
}
}
}
排除模式仅适用于通过包含匹配的变量集。
小心通配符和 CI 环境的组合。一些 CI 环境设置了额外的环境变量,例如 NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA
,这将阻止您获得缓存命中。在配置通配符后,请务必仔细查看来自所有环境的 运行摘要,以确保它只包含您关心的变量。
语法
由于这些值是在 JSON 中指定的,而 JSON也使用 \
作为转义符,您需要确保您传入的值解析为转义字符串。
- 在模式中的任何位置的
*
将匹配零个或多个字符。 - 一个领先的
!
表示整个模式将被否定。 - 一个
!
在第一个位置以外的任何位置都是一个字面上的!
。 - 具有特殊含义的字符(领先的
!
和*
)可以通过在它们前面放置一个\
来转义,以获得字面值。
示例
"*"
: 匹配每个环境变量。"!*"
: 排除每个环境变量。"FOO*"
: 匹配FOO
,FOOD
,FOO_FIGHTERS
等。"FOO\*"
: 因为这是在 JSON 中指定的,所以它解析为"FOO*"
并匹配FOO
,FOOD
和FOO_FIGHTERS
。"FOO\\*"
: 匹配一个名为FOO*
的单个环境变量。"!FOO*"
: 排除所有以FOO
开头的环境变量。"\!FOO"
: 因为这是在 JSON 中指定的,所以它解析为"!FOO"
,并从匹配集中排除一个名为!FOO
的单个环境变量。"\\!FOO"
: 匹配一个名为!FOO
的单个环境变量。"FOO!"
: 匹配一个名为FOO!
的单个环境变量。
宽松和严格的环境模式
Turborepo 提供两种不同的模式来处理任务中的环境变量:loose
模式和 strict
模式。该模式控制在执行时哪些环境变量可用于每个任务。
宽松模式
宽松模式是默认行为,它不会过滤任何环境变量。因此,机器上的所有环境变量都可用于每个任务。这确保了最大的兼容性,同时接受了任务将隐式访问未指定环境变量的风险。用户可以使用环境变量的不同值运行任务,但错误地看到 FULL TURBO,因为环境变量未在 turbo.json
中配置。
严格模式
严格模式可以使用 turbo --env-mode=strict
启用,它会过滤掉环境变量。
只有 重要的系统环境变量 和在 turbo.json
中配置的环境变量将可用于任务。
如果你希望环境变量成为缓存键的一部分,请使用 哈希环境变量。
如果你 **不希望** 环境变量成为缓存键的一部分,请使用 未哈希环境变量。
系统环境变量
Turborepo 将以下环境变量传递给所有任务,即使在严格模式下也是如此
PATH
SHELL
SYSTEMROOT
哈希环境变量
在 globalEnv
和 env
中定义的哈希环境变量将可用于任务,并包含在哈希缓存键中。
诸如 NODE_ENV
之类的环境变量,其值可以改变任务输出,应包含在 globalEnv
或 env
中。
未哈希环境变量
在 globalPassThroughEnv
和 passThroughEnv
中定义的未哈希环境变量将可用于任务,但 *不* 包含在哈希缓存键中。
诸如 NPM_TOKEN
之类的访问令牌,它们会因用户而异,但会导致相同的任务输出,应在 globalPassThroughEnv
和 passThroughEnv
中定义。
推断模式
Turborepo 通过推断你是否希望从你的配置中获得 strict
行为,来实现严格模式的增量采用。
"globalPassThroughEnv": []
. 严格模式对每个任务都启用。不允许列出任何环境变量。"passThroughEnv": []
. 严格模式对特定任务启用。不允许列出任何环境变量。
.env
文件
Turborepo 不会将 .env
文件加载到环境中!你的任务必须自己处理 .env
文件的加载。
框架通常使用 dotenv
(opens in a new tab) 自动为任务加载环境变量。这可能会使 Turborepo 难以默认理解你的任务的环境
.env
文件将环境变量存储在文件中,而不是环境中。- 来自此文件环境变量在 Turborepo 开始执行任务之后加载。
- 该文件通常在
.gitignore
中指定,因此 Turborepo 默认情况下不会将其包含在任务哈希中。
鉴于仅使用文件输入正确配置的复杂性,Turborepo 明确支持 .env
文件模式,使用 globalDotEnv
和 dotEnv
字段在 turbo.json
中。为了让 Turborepo 考虑适当的 .env
文件集,请在 turbo.json
中指定它们。以下是 Next.js 应用程序的正确 dotEnv
配置
在大多数情况下,此配置应与您的框架行为相匹配,而不是您当前用于应用程序的特定配置。
{
"$schema": "https://turbo.rust-lang.net.cn/schema.json",
"globalDotEnv": [".env"],
"pipeline": {
"build": {
"dotEnv": [".env.production.local", ".env.local", ".env.production", ".env"]
},
"dev": {
"dotEnv": [".env.development.local", ".env.local", ".env.development", ".env"]
},
"test": {
"dotEnv": [".env.test.local", ".env.test", ".env"]
}
}
}
这些字段是有序的 Unix 格式 (/
分隔) 路径列表,相对于 globalDotEnv
的根目录,以及相对于 dotEnv
的工作区。它们不支持通配符或绝对路径。
框架推断
此功能可以通过将 --framework-inference=false
传递到您的 turbo
命令来禁用。
默认情况下,Turborepo 会尝试检测您 turborepo 中工作区的框架,并使用它来帮助确保所有默认环境变量都被正确考虑用于任务哈希。
如果 Turborepo 成功检测到您的框架,您无需在 turbo.json
的管道配置中手动指定某些特定于框架的环境变量。Turborepo 支持的框架以及将包含到任务的 env
键中的环境变量通配符是
框架 | env 通配符 |
---|---|
Astro | PUBLIC_* |
Blitz | NEXT_PUBLIC_* |
Create React App | REACT_APP_* |
Gatsby | GATSBY_* |
Next.js | NEXT_PUBLIC_* |
Nuxt.js | NUXT_ENV_* |
RedwoodJS | REDWOOD_ENV_* |
Sanity Studio | SANITY_STUDIO_* |
Solid | VITE_* |
SvelteKit | VITE_* |
Vite | VITE_* |
Vue | VUE_APP_* |
您可以通过以下方式确定 Turborepo 是否已成功检测到工作区的框架
- 检查运行摘要(通过
--summarize
)。 - 检查来自干运行的输出(通过
--dry
)。
框架推断排除
Turborepo 从框架推断中自动包含的通配符也可能与 CI 平台插入环境中的环境变量匹配。这些变量可以包括运行 ID 或 Git SHA 等内容,如果包含在内,将永远无法获得缓存命中。
因此,Turborepo 提供两种方法来排除哈希中的变量
-
使用排除前缀设置
TURBO_CI_VENDOR_ENV_KEY
。如果您的 CI 环境检测到您正在使用 Turborepo,这将理想地为您处理。例如,对于在 Vercel 上构建的 Next.js 应用程序,Vercel 会设置TURBO_CI_VENDOR_ENV_KEY=NEXT_PUBLIC_VERCEL_
以确保它不包含会导致缓存问题的变量。此变量仅针对推断的框架变量进行处理。 -
使用
"env": ["!NEXT_PUBLIC_UNNEEDED_*"]
在适当的task
定义的env
中手动指定排除项。这使您可以对从哈希考虑中排除环境变量进行极其精细的控制。
框架推断是按工作区进行的
环境变量将仅包含在使用该框架的工作区的任务的缓存键中。换句话说,为 Next.js 应用程序推断的环境变量将仅包含在检测为 Next.js 应用程序的工作区的缓存键中。monorepo 中其他工作区的任务将不包含它们。
例如,此 turbo.json
指定了两个独立工作区 (next-app
和 utils
) 的构建行为,将仅为 next-app
包含 NEXT_PUBLIC_*
{
"$schema": "https://turbo.rust-lang.net.cn/schema.json",
"pipeline": {
"next-app#build": {
"outputs": [".next/**", "!.next/cache/**"]
},
"utils#build": {
"outputs": ["dist/**"],
},
}
}
eslint-config-turbo
为了进一步帮助检测潜入构建的未见环境变量依赖项,并帮助确保您的 Turborepo 缓存跨环境正确共享,请使用 eslint-config-turbo
(opens in a new tab) 包。此 ESLint 配置将为 Turborepo 检测到在 turbo.json
中未指定的环境变量的使用提供编写时反馈。
要开始使用,请在您的 eslintrc
(opens in a new tab) 文件中从 eslint-config-turbo
扩展
{
// Automatically flag env vars missing from turbo.json
"extends": ["turbo"]
}
为了更好地控制规则,您可以通过首先将其添加到插件,然后配置所需的规则来直接安装和配置 eslint-plugin-turbo
(opens in a new tab) 插件
{
"plugins": ["turbo"],
"rules": {
// Automatically flag env vars missing from turbo.json
"turbo/no-undeclared-env-vars": "error"
}
}
如果在您的代码中使用未在 turbo.json
中声明的非框架相关环境变量,该插件将向您发出警告。
不可见的环境变量
由于 Turborepo 在您的任务之前运行,因此您的任务可能在 turbo
已计算出特定任务的哈希值后创建或更改环境变量。例如,考虑此 package.json
{
"scripts": {
"build": "source .env && next build"
}
}
export NEXT_PUBLIC_GA_ID=UA-00000000-0
turbo
在执行 build
脚本之前计算了任务哈希,因此无法发现 NEXT_PUBLIC_GA_ID
环境变量的值,因此无法根据其值对缓存进行分区。请确保在调用 turbo
之前将所有环境变量加载到环境中!
{
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"build": {
"env": ["NEXT_PUBLIC_GA_ID"],
"outputs": [".next/**", "!.next/cache/**"],
},
}
}