Skip to main content

Next.js 环境变量完全指南

本文档详细说明 Next.js 中如何使用环境变量,包括文件类型、加载顺序、优先级规则和最佳实践。

📋 目录


环境变量文件类型

Next.js 支持以下环境变量文件:

基础文件

文件名说明使用场景
.env默认环境变量,所有环境都会加载公共配置
.env.local本地环境变量,不应提交到 Git本地开发覆盖
.env.development开发环境专用 (next dev)开发环境配置
.env.production生产环境专用 (next build + next start)生产环境配置
.env.test测试环境专用 (jestvitest)测试环境配置

组合文件

文件名说明
.env.development.local开发环境的本地覆盖
.env.production.local生产环境的本地覆盖
.env.test.local测试环境的本地覆盖

加载顺序和优先级

🎯 优先级规则(数字越小,优先级越高)

开发环境 (next dev)

1. .env.development.local   ← 最高优先级
2. .env.local ← ⚠️ 注意:.env.test.local 不会加载
3. .env.development
4. .env ← 最低优先级

生产环境 (next build + next start)

1. .env.production.local     ← 最高优先级
2. .env.local ← ⚠️ 注意:.env.test.local 不会加载
3. .env.production
4. .env ← 最低优先级

测试环境 (jest / vitest)

1. .env.test.local           ← 最高优先级
2. .env.test
3. .env ← 最低优先级
注意:.env.local 不会在测试环境加载(确保测试一致性)

📊 优先级可视化

┌─────────────────────────────────────────────┐
│ 优先级从上到下递减 │
├─────────────────────────────────────────────┤
│ .env.[environment].local (最高) │
│ ↓ 会覆盖下面的配置 │
│ .env.local │
│ ↓ 会覆盖下面的配置 │
│ .env.[environment] │
│ ↓ 会覆盖下面的配置 │
│ .env (最低) │
└─────────────────────────────────────────────┘

🔍 实际加载示例

假设有以下文件和配置:

# .env
NEXT_PUBLIC_API_URL=http://default-api.com
DATABASE_URL=default-db

# .env.development
NEXT_PUBLIC_API_URL=http://dev-api.com

# .env.local
NEXT_PUBLIC_API_URL=http://local-api.com

运行 next dev 时的结果:

process.env.NEXT_PUBLIC_API_URL = "http://local-api.com"  // 来自 .env.local
process.env.DATABASE_URL = "default-db" // 来自 .env

解释

  1. .env.localNEXT_PUBLIC_API_URL 覆盖了其他文件
  2. DATABASE_URL 只在 .env 中定义,所以使用该值

NODE_ENV 的特殊性

⚠️ 重要特性

  1. 不能在 .env 文件中设置 NODE_ENV
  2. Next.js 会自动设置 NODE_ENV
    • next devNODE_ENV=development
    • next buildNODE_ENV=production
    • next startNODE_ENV=production

实验:尝试覆盖 NODE_ENV

# .env.local
NODE_ENV=production # ❌ 这不会生效!
# 命令行
$ cross-env NODE_ENV=production next dev

# Next.js 警告:
⚠ You are using a non-standard "NODE_ENV" value in your environment.
This creates inconsistencies in the project and is strongly advised against.

结果process.env.NODE_ENV 仍然是 "development"

✅ 正确的做法

如果需要自定义环境标识,使用自定义变量:

# .env.staging
NEXT_PUBLIC_ENV=staging
NEXT_PUBLIC_API_URL=http://staging-api.com
// 代码中使用
const env = process.env.NEXT_PUBLIC_ENV || 'development';

环境变量类型

1. 服务端环境变量(默认)

# .env
DATABASE_URL=postgresql://localhost:5432/mydb
API_SECRET=my-secret-key

特点

  • ✅ 只在服务端可用
  • ✅ 不会暴露到浏览器
  • ✅ 可以存储敏感信息

使用

// app/api/route.ts (服务端)
export async function GET() {
const dbUrl = process.env.DATABASE_URL; // ✅ 可以访问
return Response.json({ success: true });
}
// app/page.tsx (客户端组件)
'use client';

export default function Page() {
console.log(process.env.DATABASE_URL); // ❌ undefined(安全)
}

2. 浏览器端环境变量

使用 NEXT_PUBLIC_ 前缀:

# .env
NEXT_PUBLIC_API_URL=http://api.example.com
NEXT_PUBLIC_ANALYTICS_ID=GA-123456

特点

  • ✅ 客户端和服务端都可用
  • ⚠️ 会暴露到浏览器(内联到 JavaScript bundle)
  • ❌ 不要存储敏感信息

使用

// app/page.tsx (客户端组件)
'use client';

export default function Page() {
const apiUrl = process.env.NEXT_PUBLIC_API_URL; // ✅ 可以访问
return <div>API: {apiUrl}</div>;
}

⚠️ 安全警告

# ❌ 错误示例 - 敏感信息不要用 NEXT_PUBLIC_
NEXT_PUBLIC_DATABASE_PASSWORD=secret123 # 会暴露到浏览器!

# ✅ 正确示例 - 敏感信息不加前缀
DATABASE_PASSWORD=secret123 # 只在服务端可用

实战示例

场景 1:多环境配置

文件结构

项目根目录/
├── .env # 公共配置
├── .env.development # 开发环境
├── .env.production # 生产环境
├── .env.local # 本地覆盖(不提交)
└── .gitignore

.env(默认配置)

# 公共配置 - 所有环境共享
APP_NAME=PayUnify
APP_VERSION=1.0.0

.env.development(开发环境)

# 开发环境配置
NEXT_PUBLIC_API_URL=http://localhost:8097
NEXT_PUBLIC_ENV=development

# 开发环境数据库
DATABASE_URL=postgresql://localhost:5432/payunify_dev

.env.production(生产环境)

# 生产环境配置
NEXT_PUBLIC_API_URL=https://api.payunify.com
NEXT_PUBLIC_ENV=production

# 生产环境数据库(敏感信息,通常由服务器设置)
DATABASE_URL=postgresql://prod-db.example.com:5432/payunify

.env.local(本地开发覆盖)

# 本地开发时的个性化配置
# 此文件不提交到 Git,每个开发者可以有自己的配置

# 如果你在本地测试生产 API
NEXT_PUBLIC_API_URL=http://124.222.202.16:8089

# 本地数据库
DATABASE_URL=postgresql://localhost:5432/payunify_local

.gitignore

# 环境变量
.env*.local
.env.local

场景 2:条件配置加载

// lib/config.ts
export const config = {
apiUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8097',
env: process.env.NEXT_PUBLIC_ENV || 'development',
isDev: process.env.NODE_ENV === 'development',
isProd: process.env.NODE_ENV === 'production',

// 服务端专用配置
database: {
url: process.env.DATABASE_URL,
},

// 第三方服务
analytics: {
googleId: process.env.NEXT_PUBLIC_GA_ID,
},
};

场景 3:API 客户端配置

// services/apiClient.ts
class ApiClient {
private baseURL: string;

constructor() {
// 根据协议决定使用代理还是直连
const isHttps = typeof window !== 'undefined' &&
window.location.protocol === 'https:';

if (isHttps) {
// HTTPS 环境使用代理避免混合内容
this.baseURL = '/api/proxy';
} else {
// HTTP 环境直连
this.baseURL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8097';
}

console.log('Environment:', process.env.NODE_ENV);
console.log('API Base URL:', this.baseURL);
}
}

最佳实践

1. 文件组织策略

✅ 推荐结构

.env                  # 提交到 Git - 默认配置
.env.example # 提交到 Git - 配置模板
.env.development # 提交到 Git - 开发环境
.env.production # 提交到 Git - 生产环境
.env.local # 不提交 - 本地覆盖

.env.example(配置模板)

# API 配置
NEXT_PUBLIC_API_URL=http://localhost:8097

# 数据库配置(示例值)
DATABASE_URL=postgresql://user:password@localhost:5432/dbname

# 第三方服务(示例值)
NEXT_PUBLIC_GA_ID=your-ga-id
STRIPE_SECRET_KEY=your-stripe-key

2. 安全实践

✅ 正确做法

# 服务端专用(敏感信息)
DATABASE_PASSWORD=secret123
API_SECRET_KEY=very-secret
STRIPE_SECRET_KEY=sk_live_xxx

# 客户端可见(非敏感信息)
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_GA_ID=GA-123456

❌ 错误做法

# ❌ 敏感信息加了 NEXT_PUBLIC_ 前缀
NEXT_PUBLIC_DATABASE_PASSWORD=secret123 # 会暴露到浏览器!
NEXT_PUBLIC_API_SECRET=xxx # 会暴露到浏览器!

3. Git 版本控制

.gitignore

# 环境变量 - 忽略本地配置
.env*.local
.env.local

# 不要忽略这些
# .env
# .env.example
# .env.development
# .env.production

4. 团队协作

新成员入职流程

# 1. 克隆项目
git clone <repo>
cd project

# 2. 复制环境配置
cp .env.example .env.local

# 3. 修改个人配置
nano .env.local

5. 部署配置

Vercel 部署

# 在 Vercel 项目设置中配置环境变量
Environment Variables:
NEXT_PUBLIC_API_URL=https://api.production.com
DATABASE_URL=postgresql://...(敏感信息)
STRIPE_SECRET_KEY=sk_live_xxx

Docker 部署

# docker-compose.yml
services:
frontend:
environment:
- NODE_ENV=production
- NEXT_PUBLIC_API_URL=http://api:8080
- DATABASE_URL=${DATABASE_URL} # 从宿主机加载

常见问题

Q1: 为什么我的环境变量没有生效?

可能原因

  1. 没有重启开发服务器

    # ❌ 运行中修改 .env 文件不会自动生效
    # ✅ 需要重启
    npm run dev
  2. 优先级问题

    # .env.local 会覆盖 .env.development
    # 检查是否有优先级更高的文件
  3. 客户端组件访问服务端变量

    // ❌ 客户端无法访问
    'use client';
    console.log(process.env.DATABASE_URL); // undefined

    // ✅ 需要 NEXT_PUBLIC_ 前缀
    console.log(process.env.NEXT_PUBLIC_API_URL); // 正常
  4. 构建时内联

    # NEXT_PUBLIC_ 变量在构建时内联到代码中
    # 修改后需要重新构建
    npm run build

Q2: 如何在不同环境切换 API 地址?

方案 1:使用 .env.local(推荐)

# .env.local
NEXT_PUBLIC_API_URL=http://staging-api.com

# 切换环境时修改这个文件
# 重启: npm run dev

方案 2:使用环境特定文件

# .env.development
NEXT_PUBLIC_API_URL=http://dev-api.com

# .env.production
NEXT_PUBLIC_API_URL=http://prod-api.com

# 使用不同命令
npm run dev # 使用 .env.development
npm run build # 使用 .env.production
npm start

方案 3:使用自定义环境变量

# .env.staging
NEXT_PUBLIC_ENV=staging
NEXT_PUBLIC_API_URL=http://staging-api.com
// 代码中条件判断
const apiUrl = process.env.NEXT_PUBLIC_ENV === 'staging'
? 'http://staging-api.com'
: process.env.NEXT_PUBLIC_API_URL;

Q3: NODE_ENV 可以自定义吗?

答案:不推荐

# ❌ 不推荐 - Next.js 会警告
cross-env NODE_ENV=staging next dev

# ✅ 推荐 - 使用自定义变量
cross-env NEXT_PUBLIC_ENV=staging next dev

原因

  • Next.js 依赖 NODE_ENV 进行优化
  • 非标准值会导致构建行为不一致
  • 使用自定义变量更灵活安全

Q4: 如何调试环境变量?

方法 1:在代码中打印

// app/page.tsx
console.log('NODE_ENV:', process.env.NODE_ENV);
console.log('API URL:', process.env.NEXT_PUBLIC_API_URL);
console.log('All NEXT_PUBLIC vars:',
Object.keys(process.env)
.filter(key => key.startsWith('NEXT_PUBLIC_'))
.reduce((obj, key) => ({ ...obj, [key]: process.env[key] }), {})
);

方法 2:创建调试页面

// app/env-test/page.tsx
export default function EnvTest() {
const envVars = Object.keys(process.env)
.filter(key => key.startsWith('NEXT_PUBLIC_'))
.reduce((obj, key) => ({ ...obj, [key]: process.env[key] }), {});

return (
<div>
<h1>环境变量调试</h1>
<p>NODE_ENV: {process.env.NODE_ENV}</p>
<pre>{JSON.stringify(envVars, null, 2)}</pre>
</div>
);
}

方法 3:检查启动日志

npm run dev

# 查看输出中的环境变量加载信息
# ▲ Next.js 15.5.5 (Turbopack)
# - Environments: .env.local, .env.development, .env

Q5: 生产环境如何管理敏感信息?

最佳实践

  1. 不要在代码中硬编码

    // ❌ 错误
    const apiKey = 'sk_live_xxxxx';

    // ✅ 正确
    const apiKey = process.env.STRIPE_SECRET_KEY;
  2. 使用平台环境变量

    • Vercel: 项目设置 → Environment Variables
    • Docker: docker-compose.yml 或启动参数
    • 服务器: 系统环境变量
  3. 使用密钥管理服务

    • AWS Secrets Manager
    • HashiCorp Vault
    • Google Secret Manager
  4. 分层管理

    # .env.production(提交到 Git)
    NEXT_PUBLIC_API_URL=https://api.production.com

    # 服务器环境变量(不提交)
    DATABASE_URL=postgresql://...
    STRIPE_SECRET_KEY=sk_live_...

Q6: 如何处理多个子环境?

场景:开发、测试、预发布、生产

# 创建自定义环境文件
.env.dev
.env.test
.env.staging
.env.production

方案 1:使用 dotenv-cli

npm install -D dotenv-cli

# package.json
{
"scripts": {
"dev": "next dev",
"dev:test": "dotenv -e .env.test -- next dev",
"dev:staging": "dotenv -e .env.staging -- next dev"
}
}

方案 2:使用自定义脚本

// scripts/load-env.js
const fs = require('fs');
const path = require('path');

const env = process.argv[2] || 'development';
const envFile = path.resolve(process.cwd(), `.env.${env}`);

if (fs.existsSync(envFile)) {
require('dotenv').config({ path: envFile });
}
# package.json
{
"scripts": {
"dev:staging": "node scripts/load-env.js staging && next dev"
}
}

快速参考

环境变量优先级(开发环境)

.env.development.local  (最高)

.env.local

.env.development

.env (最低)

变量类型对比

前缀客户端服务端用途
NEXT_PUBLIC_公开配置
无前缀敏感配置

常用命令

# 开发模式
npm run dev # 使用 .env.development

# 生产构建
npm run build # 使用 .env.production
npm start # 运行生产构建

# 自定义环境
cross-env NEXT_PUBLIC_ENV=staging npm run dev

调试检查清单

  • 重启开发服务器
  • 检查文件优先级(.env.local > .env.development)
  • 客户端变量必须有 NEXT_PUBLIC_ 前缀
  • 检查拼写和大小写
  • 查看启动日志中的环境变量加载信息

总结

✅ 最佳实践总结

  1. 文件管理

    • 提交 .env.example 作为模板
    • .env.local 用于本地覆盖,不提交
    • 使用 .env.development.env.production 区分环境
  2. 安全原则

    • 敏感信息不用 NEXT_PUBLIC_ 前缀
    • 生产敏感配置在服务器设置,不提交代码
  3. 命名规范

    • 使用 NEXT_PUBLIC_ 前缀表示公开变量
    • 使用大写字母和下划线:DATABASE_URL
  4. 调试技巧

    • 修改后重启服务器
    • 检查启动日志
    • 使用 console.log 验证
  5. 团队协作

    • 维护 .env.example 文档
    • 在 README 中说明环境变量配置
    • 不提交 .env.local 到版本控制

相关资源


最后更新: 2025年11月24日