Turborepo

使用环境变量

环境变量输入是应用程序的重要组成部分,您需要在 Turborepo 配置中考虑这些输入。

在 Turborepo 中使用环境变量时,有三个重要问题

如果未在配置中考虑环境变量,可能会导致您的应用程序在错误的配置下发布。这可能会导致严重问题,例如将您的预览部署发布到生产环境。

须知

Turborepo 还使用系统环境变量来配置其自身的行为。您可以在下面找到有关任务运行时环境变量以及它们如何影响任务哈希的信息。

将环境变量添加到任务哈希

Turborepo 需要知道您的环境变量,以考虑应用程序行为的更改。为此,请在您的 turbo.json 文件中使用 envglobalEnv 键。

./turbo.json
{
  "globalEnv": ["IMPORTANT_GLOBAL_VARIABLE"],
  "tasks": {
    "build": {
      "env": ["MY_API_URL", "MY_API_KEY"]
    }
  }
}
  • globalEnv:此列表中任何环境变量值的更改都将更改所有任务的哈希值。
  • env:包括影响任务的环境变量值的更改,从而实现更好的粒度。例如,当 API_KEY 的值更改时,lint 任务可能不需要错过缓存,但 build 任务可能应该错过缓存。

须知

Turborepo 支持环境变量的通配符,因此您可以轻松地考虑具有给定前缀的所有环境变量。请访问env 的 API 参考了解更多信息。

框架推断

Turborepo 会自动将前缀通配符添加到您的 env 键中,以用于常见的框架。如果您在包中使用以下框架之一,则无需指定具有这些前缀的环境变量

框架

env 通配符

AstroPUBLIC_*
BlitzNEXT_PUBLIC_*
Create React AppREACT_APP_*
GatsbyGATSBY_*
Next.jsNEXT_PUBLIC_*
NitroNITRO_*
Nuxt.jsNUXT_*, NITRO_*
RedwoodJSREDWOOD_ENV_*
Sanity StudioSANITY_STUDIO_*
SolidVITE_*
SvelteKitVITE_*, PUBLIC_*
ViteVITE_*
VueVUE_APP_*

须知

框架推断是按包进行的。

如果您想选择退出框架推断,您可以通过以下方式实现

  • 使用 --framework-inference=false 运行您的任务
  • env 键添加一个负通配符(例如,"env": ["!NEXT_PUBLIC_*"]

环境模式

Turborepo 的环境模式允许您控制在运行时可用于任务的环境变量

  • 严格模式(默认):将环境变量过滤为 turbo.json 中的 envglobalEnv 键中指定的变量。
  • 宽松模式:允许该进程的所有环境变量都可用。

严格模式

严格模式将可用于任务运行时的环境变量过滤为 turbo.json 中的 globalEnvenv 键中指定的变量。

这意味着未考虑所需的所有环境变量的任务很可能会失败。这是一件好事,因为您不想缓存可能在不同环境中具有不同行为的任务。

严格模式下的缓存安全性

虽然严格模式使您在未考虑所有环境变量时更有可能导致任务失败,但它并不能保证任务失败。如果您的应用程序能够优雅地处理丢失的环境变量,您仍然可以成功完成任务并获得意外的缓存命中。

传递变量

在高级用例中,您可能希望使某些环境变量可用于任务,而无需将其包含在哈希中。对这些变量的更改不会影响任务输出,但仍然需要可用以使任务成功运行。

对于这些情况,请将这些环境变量添加到 globalPassThroughEnvpassThroughEnv

CI 供应商兼容性

严格模式将过滤掉来自 CI 供应商的环境变量,直到您使用 envglobalEnvpassThroughEnvglobalPassThroughEnv 考虑这些变量。

如果这些变量中的任何一个对您的任务很重要,并且未被框架推断包含,请确保它们在您的 turbo.json 配置中。

宽松模式

宽松模式不会根据您的 globalEnvenv 键过滤您的环境变量。这使得更容易开始逐步迁移到严格模式。

使用 --env-mode 标志 在您看到脚本找不到环境变量的任何调用中启用宽松模式

终端
turbo run build --env-mode=loose

只要在运行 turbo 时环境变量可用,您的脚本就可以使用它。但是,这也使您更容易意外忘记在配置中考虑环境变量,从而允许任务在不应该命中的情况下命中缓存。

例如,您的应用程序中可能有一些代码使用环境变量获取来自 API 的数据,作为基本 URL

./apps/web/data-fetcher.ts
const data = fetch(`${process.env.MY_API_URL}/resource/1`);

然后,您使用以您的预览环境为目标的 MY_API_URL 值构建您的应用程序。当您准备发布您的应用程序时,您为生产环境构建并看到缓存命中 - 即使 MY_API_URL 变量的值已更改!MY_API_URL 更改了 - 但是 Turborepo 从缓存中还原了应用程序的版本,该版本使用预览环境的 MY_API_URL 而不是生产环境的 MY_API_URL

当您使用宽松模式时,MY_API_URL 在任务运行时可用,即使它没有在任务哈希中被考虑。为了使此任务更有可能失败并保护您免受此错误配置的影响,我们鼓励您选择严格模式

平台环境变量

当将您的应用程序部署到 Vercel 时,您可能已经在您的项目上配置了环境变量。Turborepo 将自动检查这些变量是否与您的 turbo.json 配置匹配,以确保您已考虑了它们,并且会警告您任何丢失的变量。

可以通过设置 TURBO_PLATFORM_ENV_DISABLED=false 来禁用此功能

处理 .env 文件

.env 文件非常适合在本地处理应用程序。Turborepo 不会将 .env 文件加载到您任务的运行时中,而是让它们由您的框架或 dotenv 等工具处理。

但是,重要的是 turbo 知道您的 .env 文件中值的更改,以便将其用于哈希。如果您在构建之间更改了 .env 文件中的变量,则 build 任务应错过缓存。

为此,请将文件添加到 inputs 键中

./turbo.json
{
  "globalDependencies": [".env"], // All task hashes
  "tasks": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", ".env", ".env.local"] // Only the `build` task hash
    }
  }
}

即使环境变量未添加到 env.env 文件也可以将变量加载到任务运行时中。确保将构建的环境变量添加到 env 键中以用于 CI 和生产环境构建。

最佳实践

在包中使用 .env 文件

不建议在存储库的根目录使用 .env 文件。相反,我们建议将您的 .env 文件放入它们使用的包中。

此做法更紧密地模拟了应用程序的运行时行为,因为环境变量分别存在于每个应用程序的运行时中。此外,随着您的 monorepo 的扩展,此做法使得管理每个应用程序的环境更容易,从而防止环境变量跨应用程序泄漏。

须知

在逐步迁移到 monorepo 时,您可能会发现使用根 .env 文件更容易。诸如 dotenv 之类的工具可以从不同的位置加载 .env 文件。

使用 eslint-config-turbo

eslint-config-turbo 可以帮助您查找代码中使用的但未在您的 turbo.json 中列出的环境变量。这有助于确保您的所有环境变量都在您的配置中被考虑。

避免在运行时创建或修改环境变量

Turborepo 在任务开始时会哈希该任务的环境变量。如果在任务期间创建或修改环境变量,Turborepo 将不会知道这些更改,也不会在任务哈希中考虑这些更改。

例如,Turborepo 将无法检测到下面示例中的内联变量

./apps/web/package.json
{
  "scripts": {
    "dev": "export MY_VARIABLE=123 && next dev"
  }
}

MY_VARIABLE 是在 dev 任务启动添加到环境中的,因此 turbo 将无法将其用于哈希。

示例

以下是一些流行的框架的正确环境变量配置示例

故障排除

使用 --summarize

可以将--summarize 标志添加到你的 turbo run 命令中,以生成一个 JSON 文件,其中汇总了有关任务的数据。检查 globalEnvenv 键的差异可以帮助你识别配置中可能缺少的任何环境变量。

下一步

一旦你考虑了你的环境变量,你就可以开始构建 CI 管道,以 turbo 的速度构建、检查和部署你的应用程序。

小时

节省的总计算量
开始使用
远程缓存 →

本页内容