使用环境变量

环境变量输入是你的应用程序中需要在 Turborepo 配置中考虑的重要部分。

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

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

Good to know: 

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

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

Turborepo 需要了解你的环境变量,以便考虑应用程序行为的变化。为此,请在 turbo.json 文件中使用 envglobalEnv 键。

Turborepo logo
./turbo.json
{
  "globalEnv": ["IMPORTANT_GLOBAL_VARIABLE"],
  "tasks": {
    "build": {
      "env": ["MY_API_URL", "MY_API_KEY"]
    }
  }
}
  • globalEnv:此列表中任何环境变量的值发生变化都会改变所有任务的哈希值。
  • env:包含影响任务的环境变量值的变化,允许更好的粒度控制。例如,当 API_KEY 的值发生变化时,lint 任务可能不需要缓存未命中,但 build 任务可能需要。

Good to know: 

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

框架推断

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

框架

env 通配符

AstroPUBLIC_*
BlitzNEXT_PUBLIC_*
Create React AppREACT_APP_*
GatsbyGATSBY_*
Next.jsNEXT_PUBLIC_*
NitroNITRO_*, SERVER_*, AWS_APP_ID, INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN, CLEAVR, CF_PAGES, FIREBASE_APP_HOSTING, NETLIFY, STORMKIT, NOW_BUILDER, ZEABUR, RENDER
Nuxt.jsNUXT_*, NITRO_*, SERVER_*, AWS_APP_ID, INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN, CLEAVR, CF_PAGES, FIREBASE_APP_HOSTING, NETLIFY, STORMKIT, NOW_BUILDER, ZEABUR, RENDER
RedwoodJSREDWOOD_ENV_*
Sanity StudioSANITY_STUDIO_*
SolidVITE_*
SvelteKitVITE_*, PUBLIC_*
ViteVITE_*
VueVUE_APP_*

Good to know: 

框架推断是按包进行的。

如果你想退出框架推断,可以通过以下方式实现:

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

环境模式

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

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

严格模式

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

这意味着没有考虑到所有所需环境变量的任务可能会失败。这是一件好事,因为你不希望缓存可能在不同环境中有不同行为的任务。

严格模式下的缓存安全

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

透传变量

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

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

CI 供应商兼容性

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

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

宽松模式

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

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

Terminal
turbo run build --env-mode=loose

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

例如,你的应用程序中可能有一些代码使用环境变量作为基础 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 在任务运行时可用,即使它没有计入任务哈希中。为了使这个任务更有可能失败并保护你免受这种错误配置的影响,我们鼓励你选择严格模式

平台环境变量

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

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

处理 .env 文件

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

但是,重要的是 turbo 要知道 .env 文件中值的变化,以便可以将它们用于哈希。如果你在构建之间更改了 .env 文件中的变量,build 任务应该缓存未命中。

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

Turborepo logo
./turbo.json
{
  "globalDependencies": [".env"], // 所有任务哈希
  "tasks": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", ".env"] // 仅 `build` 任务哈希
    }
  }
}

多个 .env 文件

你可以使用 * 一次捕获多个 .env 文件。

Turborepo logo
./turbo.json
{
  "globalDependencies": [".env"], // 所有任务哈希
  "tasks": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", ".env*"] // 仅 `build` 任务哈希
    }
  }
}

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

最佳实践

在包中使用 .env 文件

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

这种做法更接近应用程序的运行时行为,因为环境变量在每个应用程序的运行时中单独存在。此外,随着你的单仓库扩展,这种做法使管理每个应用程序的环境变得更容易,防止应用程序之间的环境变量泄漏。

Good to know: 

在逐步迁移到单仓库时,你可能会发现使用根 .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 的速度构建、检查和部署你的应用程序。