跳到主要内容

如何在 Next.js 中使用环境变量

Next.js 内置了对环境变量的支持,允许你执行以下操作:

警告: 默认的 create-next-app 模板确保所有 .env 文件都添加到你的 .gitignore 中。你几乎从不希望将这些文件提交到你的仓库。

加载环境变量

Next.js 内置支持从 .env* 文件加载环境变量到 process.env

.env
DB_HOST=localhost
DB_USER=myuser
DB_PASS=mypassword

这会将 process.env.DB_HOSTprocess.env.DB_USERprocess.env.DB_PASS 自动加载到 Node.js 环境中,允许你在 Next.js 数据获取方法API 路由 中使用它们。

例如,使用 getStaticProps

pages/index.js
export async function getStaticProps() {
const db = await myDB.connect({
host: process.env.DB_HOST,
username: process.env.DB_USER,
password: process.env.DB_PASS,
})
// ...
}

注意: Next.js 还支持在你的 .env* 文件中的多行变量:

# .env

# 你可以用换行符编写
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
Kh9NV...
...
-----END DSA PRIVATE KEY-----"

# 或者在双引号内使用 `\n`
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END DSA PRIVATE KEY-----\n"

注意: 如果你使用 /src 文件夹,请注意 Next.js 将从父文件夹加载 .env 文件,而不是/src 文件夹加载。 这会将 process.env.DB_HOSTprocess.env.DB_USERprocess.env.DB_PASS 自动加载到 Node.js 环境中,允许你在路由处理器中使用它们。

例如:

app/api/route.js
export async function GET() {
const db = await myDB.connect({
host: process.env.DB_HOST,
username: process.env.DB_USER,
password: process.env.DB_PASS,
})
// ...
}

使用 @next/env 加载环境变量

如果你需要在 Next.js 运行时之外加载环境变量,例如在 ORM 或测试运行器的根配置文件中,你可以使用 @next/env 包。

这个包被 Next.js 内部用来从 .env* 文件加载环境变量。

要使用它,安装包并使用 loadEnvConfig 函数来加载环境变量:

npm install @next/env
envConfig.ts
import { loadEnvConfig } from '@next/env'

const projectDir = process.cwd()
loadEnvConfig(projectDir)

然后,你可以在需要的地方导入配置。例如:

orm.config.ts
import './envConfig.ts'

export default defineConfig({
dbCredentials: {
connectionString: process.env.DATABASE_URL!,
},
})

引用其他变量

Next.js 会自动展开使用 $ 引用其他变量的变量,例如在你的 .env* 文件中的 $VARIABLE。这允许你引用其他秘密。例如:

.env
TWITTER_USER=nextjs
TWITTER_URL=https://x.com/$TWITTER_USER

在上面的例子中,process.env.TWITTER_URL 将被设置为 https://x.com/nextjs

温馨提示: 如果你需要在实际值中使用带有 $ 的变量,需要转义它,例如 \$

为浏览器打包环境变量

NEXT_PUBLIC_ 环境变量仅在 Node.js 环境中可用,这意味着浏览器无法访问它们(客户端在不同的_环境_中运行)。

为了使环境变量的值在浏览器中可访问,Next.js 可以在构建时将值"内联"到发送给客户端的 js 包中,用硬编码值替换对 process.env.[variable] 的所有引用。要告诉它这样做,你只需要用 NEXT_PUBLIC_ 前缀变量。例如:

Terminal
NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk

这将告诉 Next.js 用运行 next build 的环境中的值替换 Node.js 环境中对 process.env.NEXT_PUBLIC_ANALYTICS_ID 的所有引用,允许你在代码中的任何地方使用它。它将被内联到发送给浏览器的任何 JavaScript 中。

注意: 构建后,你的应用程序将不再响应这些环境变量的更改。例如,如果你使用 Heroku 管道将在一个环境中构建的 slug 提升到另一个环境,或者如果你构建并部署单个 Docker 镜像到多个环境,所有 NEXT_PUBLIC_ 变量都将冻结为构建时评估的值,因此这些值需要在项目构建时适当设置。如果你需要访问运行时环境值,你将必须设置自己的 API 来向客户端提供它们(按需或在初始化期间)。

pages/index.js
import setupAnalyticsService from '../lib/my-analytics-service'

// 'NEXT_PUBLIC_ANALYTICS_ID' 可以在这里使用,因为它以 'NEXT_PUBLIC_' 为前缀。
// 它将在构建时转换为 `setupAnalyticsService('abcdefghijk')`。
setupAnalyticsService(process.env.NEXT_PUBLIC_ANALYTICS_ID)

function HomePage() {
return <h1>Hello World</h1>
}

export default HomePage

注意,动态查找将不会被内联,例如:

// 这不会被内联,因为它使用了一个变量
const varName = 'NEXT_PUBLIC_ANALYTICS_ID'
setupAnalyticsService(process.env[varName])

// 这不会被内联,因为它使用了一个变量
const env = process.env
setupAnalyticsService(env.NEXT_PUBLIC_ANALYTICS_ID)

运行时环境变量

Next.js 可以支持构建时和运行时环境变量。

默认情况下,环境变量仅在服务器上可用。要向浏览器暴露环境变量,必须用 NEXT_PUBLIC_ 前缀。但是,这些公共环境变量将在 next build 期间内联到 JavaScript 包中。

要读取运行时环境变量,我们建议使用 getServerSideProps逐步采用 App Router

你可以在动态渲染期间安全地在服务器上读取环境变量:

app/page.ts
import { connection } from 'next/server'

export default async function Component() {
await connection()
// cookies、headers 和其他动态 API
// 也会选择动态渲染,这意味着
// 这个环境变量在运行时评估
const value = process.env.MY_VALUE
// ...
}

这允许你使用一个单一的 Docker 镜像,可以通过具有不同值的多个环境进行提升。

温馨提示:

  • 你可以使用 register 函数 在服务器启动时运行代码。
  • 我们不建议使用 runtimeConfig 选项,因为这不适用于独立输出模式。相反,如果你需要此功能,我们建议逐步采用 App Router。

测试环境变量

除了 developmentproduction 环境外,还有第三个选项可用:test。就像你可以为开发或生产环境设置默认值一样,你可以为 testing 环境使用 .env.test 文件做同样的事情(虽然这个不如前两个常见)。Next.js 在 testing 环境中不会从 .env.development.env.production 加载环境变量。

这在运行 jestcypress 等工具的测试时很有用,你需要仅为测试目的设置特定的环境变量。如果 NODE_ENV 设置为 test,将加载测试默认值,虽然你通常不需要手动执行此操作,因为测试工具会为你处理。

test 环境与 developmentproduction 之间有一个小差异,你需要记住:.env.local 不会被加载,因为你期望测试为每个人产生相同的结果。这样,每次测试执行都会通过忽略你的 .env.local(旨在覆盖默认设置)在不同执行中使用相同的环境默认值。

温馨提示: 与默认环境变量类似,.env.test 文件应该包含在你的仓库中,但 .env.test.local 不应该,因为 .env*.local 旨在通过 .gitignore 被忽略。

在运行单元测试时,你可以通过利用 @next/env 包中的 loadEnvConfig 函数来确保以与 Next.js 相同的方式加载环境变量。

// 以下可以在 Jest 全局设置文件或类似的测试设置中使用
import { loadEnvConfig } from '@next/env'

export default async () => {
const projectDir = process.cwd()
loadEnvConfig(projectDir)
}

环境变量加载顺序

环境变量按以下顺序查找,一旦找到变量就停止。

  1. process.env
  2. .env.$(NODE_ENV).local
  3. .env.local(当 NODE_ENVtest 时不检查。)
  4. .env.$(NODE_ENV)
  5. .env

例如,如果 NODE_ENVdevelopment 并且你在 .env.development.local.env 中都定义了一个变量,将使用 .env.development.local 中的值。

温馨提示: NODE_ENV 的允许值是 productiondevelopmenttest

温馨提示

  • 如果你使用 /src 目录.env.* 文件应该保留在项目的根目录中。
  • 如果环境变量 NODE_ENV 未分配,Next.js 在运行 next dev 命令时自动分配 development,或为所有其他命令分配 production

版本历史

版本更改
v9.4.0支持 .envNEXT_PUBLIC_ 引入。