跳转到内容

使用环境变量

Astro 让你能够访问 Vite 的内置环境变量支持,并包含一些为你的项目提供的默认环境变量,允许你访问当前项目的配置值(例如 sitebase)、判断项目是在开发环境还是生产环境中运行,等等。

Astro 还提供了一种以类型安全的方式使用和组织环境变量的方法。它可以在 Astro 上下文(例如 Astro 组件、路由和端点、UI 框架组件、中间件)中使用,并通过 Astro 配置中的模式(schema)进行管理。

Astro 使用 Vite 对环境变量的内置支持,这些变量在构建时会被静态替换,并允许你使用其任何方法来处理它们。

请注意,虽然所有环境变量都可以在服务器端代码中使用,但出于安全考虑,只有以 PUBLIC_ 为前缀的环境变量才可以在客户端代码中使用。

.env
SECRET_PASSWORD=password123
PUBLIC_ANYBODY=there

在这个例子中,PUBLIC_ANYBODY(通过 import.meta.env.PUBLIC_ANYBODY 访问)将在服务器或客户端代码中可用,而 SECRET_PASSWORD(通过 import.meta.env.SECRET_PASSWORD 访问)将只在服务器端可用。

默认情况下,Astro 在 astro/client.d.ts 中为 import.meta.env 提供了类型定义。

虽然你可以在 .env.[mode] 文件中定义更多自定义环境变量,但你可能希望为以 PUBLIC_ 为前缀的用户定义环境变量获取 TypeScript 智能提示(IntelliSense)。

要实现这一点,你可以在 src/ 目录下创建一个 env.d.ts 文件,并像这样配置 ImportMetaEnv

src/env.d.ts
interface ImportMetaEnv {
readonly DB_PASSWORD: string;
readonly PUBLIC_POKEAPI: string;
// more env variables...
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}

Astro 开箱即用地包含了一些环境变量

  • import.meta.env.MODE: 网站运行的模式。在运行 astro dev 时为 development,在运行 astro build 时为 production
  • import.meta.env.PROD: 如果你的网站在生产环境中运行,则为 true;否则为 false
  • import.meta.env.DEV: 如果你的网站在开发环境中运行,则为 true;否则为 false。始终与 import.meta.env.PROD 相反。
  • import.meta.env.BASE_URL: 你的网站所服务的基准 URL。这由 base 配置选项决定。
  • import.meta.env.SITE: 这被设置为在你的项目 astro.config 中指定的 site 选项
  • import.meta.env.ASSETS_PREFIX: 如果设置了 build.assetsPrefix 配置选项,则为 Astro 生成的资源链接的前缀。这可以用来创建 Astro 未处理的资源链接。

像使用其他任何环境变量一样使用它们。

const isProd = import.meta.env.PROD;
const isDev = import.meta.env.DEV;

环境变量可以从项目目录中的 .env 文件加载。

只需在项目目录中创建一个 .env 文件,并向其中添加一些变量。

.env
# This will only be available when run on the server!
DB_PASSWORD="foobar"
# This will be available everywhere!
PUBLIC_POKEAPI="https://pokeapi.co/api/v2"

你还可以在文件名本身添加 .production.development 或自定义模式名称(例如 .env.testing.env.staging)。这允许你在不同时间使用不同的环境变量集。

astro devastro build 命令分别默认为 "development""production" 模式。你可以使用 --mode 标志运行这些命令,为 mode 传递不同的值并加载匹配的 .env 文件。

这使你能够运行开发服务器或构建连接到不同 API 的网站

终端窗口
# Run the dev server connected to a "staging" API
npm run astro dev -- --mode staging
# Build a site that connects to a "production" API with additional debug information
npm run astro build -- --devOutput
# Build a site that connects to a "testing" API
npm run astro build -- --mode testing

关于 .env 文件的更多信息,请参阅 Vite 文档

Astro 在加载其他文件之前会先评估配置文件。这意味着你不能在 astro.config.mjs 中使用 import.meta.env 来访问在 .env 文件中设置的环境变量。

你可以在配置文件中使用 process.env 来访问其他环境变量,例如由 CLI 设置的变量

你也可以使用 Vite 的 loadEnv 辅助函数来手动加载 .env 文件。

astro.config.mjs
import { loadEnv } from "vite";
const { SECRET_PASSWORD } = loadEnv(process.env.NODE_ENV, process.cwd(), "");

你也可以在运行项目时添加环境变量

终端窗口
PUBLIC_POKEAPI=https://pokeapi.co/api/v2 npm run dev

在 Astro 中,环境变量通过 import.meta.env 访问,使用的是 ES2020 中添加的 import.meta 特性,而不是 process.env

例如,使用 import.meta.env.PUBLIC_POKEAPI 来获取 PUBLIC_POKEAPI 环境变量。

// When import.meta.env.SSR === true
const data = await db(import.meta.env.DB_PASSWORD);
// When import.meta.env.SSR === false
const data = fetch(`${import.meta.env.PUBLIC_POKEAPI}/pokemon/squirtle`);

使用 SSR 时,可以根据所使用的 SSR 适配器在运行时访问环境变量。对于大多数适配器,你可以使用 process.env 访问环境变量,但有些适配器的工作方式不同。对于 Deno 适配器,你将使用 Deno.env.get()。请参阅如何访问 Cloudflare 运行时来在使用 Cloudflare 适配器时处理环境变量。Astro 会首先检查服务器环境中的变量,如果不存在,Astro 会在 .env 文件中查找它们。

astro:env API 允许你为已设置的环境变量配置一个类型安全的模式。这允许你指定它们应该在服务器端还是客户端可用,并定义它们的数据类型和附加属性。

正在开发适配器?请参阅如何使适配器与 astro:env 兼容

要配置模式,请将 env.schema 选项添加到你的 Astro 配置中

astro.config.mjs
import { defineConfig } from "astro/config";
export default defineConfig({
env: {
schema: {
// ...
}
}
})

然后,你可以使用 envField 辅助函数将变量注册为字符串、数字、枚举或布尔值。通过为每个变量提供 context"client""server")和 access"secret""public")来定义环境变量的类型,并在一个对象中传递任何附加属性,如 optionaldefault

astro.config.mjs
import { defineConfig, envField } from "astro/config";
export default defineConfig({
env: {
schema: {
API_URL: envField.string({ context: "client", access: "public", optional: true }),
PORT: envField.number({ context: "server", access: "public", default: 4321 }),
API_SECRET: envField.string({ context: "server", access: "secret" }),
}
}
})

当你运行 astro devastro build 时,将会为你生成类型,但你也可以运行 astro sync 来仅生成类型。

从相应的 /client/server 模块中导入并使用你定义的变量

---
import { API_URL } from "astro:env/client";
import { API_SECRET_TOKEN } from "astro:env/server";
const data = await fetch(`${API_URL}/users`, {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_SECRET_TOKEN}`
},
})
---
<script>
import { API_URL } from "astro:env/client";
fetch(`${API_URL}/ping`)
</script>

环境变量共有三种类型,由你在模式中定义的 context"client""server")和 access"secret""public")设置的组合决定

  • 公共客户端变量:这些变量最终会包含在你的客户端和服务器端构建包中,可以通过 astro:env/client 模块在客户端和服务器端访问

    import { API_URL } from "astro:env/client";
  • 公共服务器变量:这些变量最终会包含在你的服务器端构建包中,可以通过 astro:env/server 模块在服务器端访问

    import { PORT } from "astro:env/server";
  • 秘密服务器变量:这些变量不属于你最终的构建包,可以通过 astro:env/server 模块在服务器端访问

    import { API_SECRET } from "astro:env/server";

    默认情况下,密钥仅在运行时进行验证。你可以通过配置 validateSecrets: true 来在启动时验证私有变量。

目前支持四种数据类型:字符串、数字、枚举和布尔值

import { envField } from "astro/config";
envField.string({
// context & access
optional: true,
default: "foo",
})
envField.number({
// context & access
optional: true,
default: 15,
})
envField.boolean({
// context & access
optional: true,
default: true,
})
envField.enum({
// context & access
values: ["foo", "bar", "baz"],
optional: true,
default: "baz",
})
有关验证字段的完整列表,请参阅 envField API 参考

尽管定义了模式,你可能仍希望检索给定密钥的原始值或检索未在模式中定义的密钥。在这种情况下,你可以使用从 astro:env/server 导出的 getSecret()

import {
FOO, // boolean
getSecret
} from "astro:env/server";
getSecret("FOO"); // string | undefined
API 参考中了解更多信息。

astro:env 是一个虚拟模块,这意味着它只能在 Astro 上下文中使用。例如,你可以在以下地方使用它

  • 中间件
  • Astro 路由和端点
  • Astro 组件
  • 框架组件
  • 模块

你不能在以下地方使用它,而必须使用 process.env

  • astro.config.mjs
  • 脚本
贡献 社区 赞助