How to use environment variables in Next.js
Next.js 内置了对环境变量的支持,允许你执行以下操作:
警告: 默认的
create-next-app模板确保所有.env文件都被添加到你的.gitignore中。你几乎永远不应该将这些文件提交到仓库。
加载环境变量
Next.js 内置支持从 .env* 文件加载环境变量到 process.env。
DB_HOST=localhost
DB_USER=myuser
DB_PASS=mypassword这会自动将 process.env.DB_HOST、process.env.DB_USER 和 process.env.DB_PASS 加载到 Node.js 环境中,允许你在 Next.js 数据获取方法和 API 路由中使用它们。
例如,使用 getStaticProps:
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/env 加载环境变量
如果你需要在 Next.js 运行时之外加载环境变量,例如在 ORM 或测试运行器的根配置文件中,你可以使用 @next/env 包。
这个包在 Next.js 内部用于从 .env* 文件加载环境变量。
要使用它,安装该包并使用 loadEnvConfig 函数加载环境变量:
npm install @next/envimport { loadEnvConfig } from '@next/env'
const projectDir = process.cwd()
loadEnvConfig(projectDir)然后,你可以在需要的地方导入配置。例如:
import './envConfig.ts'
export default defineConfig({
dbCredentials: {
connectionString: process.env.DATABASE_URL!,
},
})引用其他变量
Next.js 会自动展开使用 $ 引用其他变量的变量,例如在你的 .env* 文件中使用 $VARIABLE。这允许你引用其他秘密。例如:
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 bundle 中,将所有对 process.env.[variable] 的引用替换为硬编码的值。要告诉它这样做,你只需要在变量前添加 NEXT_PUBLIC_ 前缀。例如:
NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk这将告诉 Next.js 在 Node.js 环境中将所有对 process.env.NEXT_PUBLIC_ANALYTICS_ID 的引用替换为你运行 next build 时环境中的值,允许你在代码中的任何地方使用它。它将被内联到发送到浏览器的任何 JavaScript 中。
注意: 构建后,你的应用将不再响应这些环境变量的更改。例如,如果你使用 Heroku pipeline 将在一个环境中构建的 slug 提升到另一个环境,或者如果你构建并部署单个 Docker 镜像到多个环境,所有
NEXT_PUBLIC_变量将被冻结为构建时评估的值,因此这些值需要在项目构建时适当设置。如果你需要访问运行时环境值,你必须设置自己的 API 将它们提供给客户端(按需或在初始化期间)。
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 bundle 中。
要读取运行时环境变量,我们建议使用 getServerSideProps 或逐步采用 App Router。
这允许你使用一个可以通过多个环境以不同值提升的单一 Docker 镜像。
值得注意的是:
- 你可以使用
register函数在服务器启动时运行代码。
测试环境变量
除了 development 和 production 环境之外,还有第三个选项可用:test。与为开发或生产环境设置默认值的方式相同,你可以使用 .env.test 文件为 testing 环境做同样的事情(尽管这个不如前两个常见)。Next.js 不会在 testing 环境中从 .env.development 或 .env.production 加载环境变量。
这在使用 jest 或 cypress 等工具运行测试时很有用,你需要仅为测试目的设置特定的环境变量。如果 NODE_ENV 设置为 test,则会加载测试默认值,尽管你通常不需要手动执行此操作,因为测试工具会为你处理。
test 环境与 development 和 production 之间有一个小差异,你需要记住:.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)
}环境变量加载顺序
环境变量按以下顺序在以下位置查找,一旦找到变量就停止。
process.env.env.$(NODE_ENV).local.env.local(当NODE_ENV为test时不检查。).env.$(NODE_ENV).env
例如,如果 NODE_ENV 为 development 并且你在 .env.development.local 和 .env 中都定义了一个变量,则会使用 .env.development.local 中的值。
值得注意的是:
NODE_ENV允许的值为production、development和test。
值得注意的是
- 如果你使用
/src目录,.env.*文件应保留在项目的根目录中。 - 如果环境变量
NODE_ENV未分配,Next.js 会在运行next dev命令时自动分配development,或者为所有其他命令分配production。
版本历史
| 版本 | 变更 |
|---|---|
v9.4.0 | 引入对 .env 和 NEXT_PUBLIC_ 的支持。 |