nextjs-env-variables

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Next.js Environment Variable Structure

Next.js环境变量结构

Complete guide to Next.js environment variable management.
Next.js环境变量管理完整指南。

File Structure

文件结构

my-nextjs-app/
├── .env                      # Shared defaults (committed)
├── .env.local               # Local secrets (gitignored)
├── .env.development         # Development defaults (committed)
├── .env.development.local   # Local dev overrides (gitignored)
├── .env.production          # Production defaults (committed)
├── .env.production.local    # Production secrets (gitignored)
├── .env.test                # Test environment (committed)
└── .env.example             # Documentation (committed)
my-nextjs-app/
├── .env                      # 共享默认配置(需提交至版本库)
├── .env.local               # 本地密钥(需加入.gitignore忽略)
├── .env.development         # 开发环境默认配置(需提交至版本库)
├── .env.development.local   # 本地开发环境覆盖配置(需加入.gitignore忽略)
├── .env.production          # 生产环境默认配置(需提交至版本库)
├── .env.production.local    # 生产环境密钥(需加入.gitignore忽略)
├── .env.test                # 测试环境配置(需提交至版本库)
└── .env.example             # 配置文档(需提交至版本库)

File Precedence

文件优先级

Next.js loads files in this order (higher = higher precedence):
  1. .env.$(NODE_ENV).local
    (e.g.,
    .env.production.local
    )
  2. .env.local
    (not loaded in test environment)
  3. .env.$(NODE_ENV)
    (e.g.,
    .env.production
    )
  4. .env
Example: In production, if
DATABASE_URL
is defined in both
.env
and
.env.production.local
, the value from
.env.production.local
wins.
Next.js按以下顺序加载文件(位置越靠上优先级越高):
  1. .env.$(NODE_ENV).local
    (例如:
    .env.production.local
  2. .env.local
    (测试环境不加载)
  3. .env.$(NODE_ENV)
    (例如:
    .env.production
  4. .env
示例:在生产环境中,如果
DATABASE_URL
同时在
.env
.env.production.local
中定义,则
.env.production.local
中的值会生效。

Variable Types

变量类型

Client-Side Variables (NEXT_PUBLIC_*)

客户端变量(NEXT_PUBLIC_*)

Exposed to the browser. Must prefix with
NEXT_PUBLIC_
.
bash
undefined
会暴露至浏览器,必须以
NEXT_PUBLIC_
为前缀。
bash
undefined

.env.local

.env.local

NEXT_PUBLIC_API_URL=https://api.example.com NEXT_PUBLIC_ANALYTICS_ID=UA-123456789 NEXT_PUBLIC_SITE_NAME=My Awesome Site NEXT_PUBLIC_ENABLE_FEATURE_X=true

**Access in code**:
```javascript
// Works in both client and server
const apiUrl = process.env.NEXT_PUBLIC_API_URL;

// Usage in components
export default function MyComponent() {
  return <div>API: {process.env.NEXT_PUBLIC_API_URL}</div>;
}
⚠️ Security Warning: NEVER put secrets in
NEXT_PUBLIC_*
variables!
bash
undefined
NEXT_PUBLIC_API_URL=https://api.example.com NEXT_PUBLIC_ANALYTICS_ID=UA-123456789 NEXT_PUBLIC_SITE_NAME=My Awesome Site NEXT_PUBLIC_ENABLE_FEATURE_X=true

**代码中访问方式**:
```javascript
// 在客户端和服务端均可用
const apiUrl = process.env.NEXT_PUBLIC_API_URL;

// 在组件中使用
export default function MyComponent() {
  return <div>API: {process.env.NEXT_PUBLIC_API_URL}</div>;
}
⚠️ 安全警告:绝对不要将密钥放入
NEXT_PUBLIC_*
变量中!
bash
undefined

❌ WRONG - Secret exposed to browser

❌ 错误 - 密钥会暴露至浏览器

NEXT_PUBLIC_API_SECRET=sk_live_abc123
NEXT_PUBLIC_API_SECRET=sk_live_abc123

✅ CORRECT - Secret only on server

✅ 正确 - 密钥仅在服务端可用

API_SECRET=sk_live_abc123
undefined
API_SECRET=sk_live_abc123
undefined

Server-Side Variables

服务端变量

Only available in server-side code (API routes, getServerSideProps, etc.).
bash
undefined
仅在服务端代码中可用(API路由、getServerSideProps等)。
bash
undefined

.env.local

.env.local

DATABASE_URL=postgres://localhost:5432/mydb JWT_SECRET=super-secret-jwt-key-do-not-expose STRIPE_SECRET_KEY=sk_live_abc123 SMTP_PASSWORD=email-password-here

**Access in code**:
```javascript
// ✅ Works in API routes
export default async function handler(req, res) {
  const dbUrl = process.env.DATABASE_URL;
  // Use dbUrl...
}

// ✅ Works in getServerSideProps
export async function getServerSideProps() {
  const secret = process.env.JWT_SECRET;
  // Use secret...
}

// ❌ Does NOT work in components (browser)
export default function MyComponent() {
  const dbUrl = process.env.DATABASE_URL; // undefined!
}
DATABASE_URL=postgres://localhost:5432/mydb JWT_SECRET=super-secret-jwt-key-do-not-expose STRIPE_SECRET_KEY=sk_live_abc123 SMTP_PASSWORD=email-password-here

**代码中访问方式**:
```javascript
// ✅ 在API路由中可用
export default async function handler(req, res) {
  const dbUrl = process.env.DATABASE_URL;
  // 使用dbUrl...
}

// ✅ 在getServerSideProps中可用
export async function getServerSideProps() {
  const secret = process.env.JWT_SECRET;
  // 使用secret...
}

// ❌ 在组件中不可用(浏览器环境)
export default function MyComponent() {
  const dbUrl = process.env.DATABASE_URL; // 结果为undefined!
}

Example Files

示例文件

.env (Committed - Shared Defaults)

.env(已提交 - 共享默认配置)

bash
undefined
bash
undefined

Shared defaults for all environments

所有环境共享的默认配置

NEXT_PUBLIC_APP_NAME=My Next.js App NEXT_PUBLIC_DEFAULT_LOCALE=en
NEXT_PUBLIC_APP_NAME=My Next.js App NEXT_PUBLIC_DEFAULT_LOCALE=en

Database (overridden in .env.local)

数据库配置(会被.env.local覆盖)

DATABASE_URL=postgres://localhost:5432/dev
DATABASE_URL=postgres://localhost:5432/dev

External services (no secrets)

外部服务配置(无密钥)

NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_abc123
undefined
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_abc123
undefined

.env.local (Gitignored - Local Secrets)

.env.local(已忽略 - 本地密钥)

bash
undefined
bash
undefined

Local development secrets

本地开发环境密钥

DATABASE_URL=postgres://localhost:5432/mylocal JWT_SECRET=dev-jwt-secret-change-in-production STRIPE_SECRET_KEY=sk_test_local_key
DATABASE_URL=postgres://localhost:5432/mylocal JWT_SECRET=dev-jwt-secret-change-in-production STRIPE_SECRET_KEY=sk_test_local_key

Local overrides

本地覆盖配置

NEXT_PUBLIC_API_URL=http://localhost:4000/api
undefined
NEXT_PUBLIC_API_URL=http://localhost:4000/api
undefined

.env.production (Committed - Production Defaults)

.env.production(已提交 - 生产环境默认配置)

bash
undefined
bash
undefined

Production environment defaults

生产环境默认配置

NEXT_PUBLIC_API_URL=https://api.production.com NEXT_PUBLIC_ANALYTICS_ID=UA-PROD-123456
NEXT_PUBLIC_API_URL=https://api.production.com NEXT_PUBLIC_ANALYTICS_ID=UA-PROD-123456

These will be overridden by platform env vars

这些配置会被平台环境变量覆盖

DATABASE_URL=set-this-in-vercel JWT_SECRET=set-this-in-vercel
undefined
DATABASE_URL=set-this-in-vercel JWT_SECRET=set-this-in-vercel
undefined

.env.example (Committed - Documentation)

.env.example(已提交 - 配置文档)

bash
undefined
bash
undefined

Copy this to .env.local and fill in actual values

复制此文件为.env.local并填入实际值

Client-side (browser accessible)

客户端变量(可被浏览器访问)

NEXT_PUBLIC_API_URL=https://api.example.com NEXT_PUBLIC_ANALYTICS_ID=your-analytics-id NEXT_PUBLIC_SITE_NAME=Your Site Name
NEXT_PUBLIC_API_URL=https://api.example.com NEXT_PUBLIC_ANALYTICS_ID=your-analytics-id NEXT_PUBLIC_SITE_NAME=Your Site Name

Server-side (secrets)

服务端变量(密钥)

DATABASE_URL=postgres://user:password@host:5432/database # pragma: allowlist secret JWT_SECRET=your-jwt-secret-32-chars-minimum STRIPE_SECRET_KEY=sk_live_your_stripe_key SMTP_HOST=smtp.example.com SMTP_PORT=587 SMTP_USER=your-email@example.com SMTP_PASSWORD=your-smtp-password
undefined
DATABASE_URL=postgres://user:password@host:5432/database # pragma: allowlist secret JWT_SECRET=your-jwt-secret-32-chars-minimum STRIPE_SECRET_KEY=sk_live_your_stripe_key SMTP_HOST=smtp.example.com SMTP_PORT=587 SMTP_USER=your-email@example.com SMTP_PASSWORD=your-smtp-password
undefined

Common Patterns

常见模式

Database Configuration

数据库配置

bash
undefined
bash
undefined

Development (.env.local)

开发环境(.env.local)

DATABASE_URL=postgres://localhost:5432/myapp_dev
DATABASE_URL=postgres://localhost:5432/myapp_dev

Production (Vercel Environment Variables)

生产环境(Vercel环境变量)

DATABASE_URL=postgres://user:pass@prod-host:5432/myapp_prod # pragma: allowlist secret
undefined
DATABASE_URL=postgres://user:pass@prod-host:5432/myapp_prod # pragma: allowlist secret
undefined

API Keys

API密钥

bash
undefined
bash
undefined

Public keys (client-side)

公钥(客户端可用)

NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_abc123
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_abc123

Secret keys (server-side only)

密钥(仅服务端可用)

STRIPE_SECRET_KEY=sk_live_xyz789
undefined
STRIPE_SECRET_KEY=sk_live_xyz789
undefined

Feature Flags

功能开关

bash
undefined
bash
undefined

Toggle features

功能切换

NEXT_PUBLIC_ENABLE_DARK_MODE=true NEXT_PUBLIC_ENABLE_BETA_FEATURES=false
undefined
NEXT_PUBLIC_ENABLE_DARK_MODE=true NEXT_PUBLIC_ENABLE_BETA_FEATURES=false
undefined

Deployment to Vercel

部署至Vercel

Step 1: Add Environment Variables in Vercel

步骤1:在Vercel中添加环境变量

  1. Go to Project Settings → Environment Variables
  2. Add each variable:
    • Key:
      DATABASE_URL
    • Value:
      postgres://...
    • Environments: Production, Preview, Development
  1. 进入项目设置 → 环境变量
  2. 添加每个变量:
    • DATABASE_URL
    • postgres://...
    • 环境:生产环境、预览环境、开发环境

Step 2: Separate Client vs Server Variables

步骤2:区分客户端与服务端变量

Vercel automatically exposes
NEXT_PUBLIC_*
variables at build time.
bash
undefined
Vercel会在构建时自动暴露
NEXT_PUBLIC_*
变量。
bash
undefined

Vercel automatically handles:

Vercel会自动处理:

NEXT_PUBLIC_API_URL=https://api.example.com # ✅ Exposed to browser
NEXT_PUBLIC_API_URL=https://api.example.com # ✅ 暴露至浏览器

Server-only:

仅服务端可用:

DATABASE_URL=postgres://... # ✅ Not exposed to browser
undefined
DATABASE_URL=postgres://... # ✅ 不会暴露至浏览器
undefined

Step 3: Rebuild After Changing NEXT_PUBLIC_ Variables

步骤3:修改NEXT_PUBLIC_变量后重新构建

⚠️ Important:
NEXT_PUBLIC_*
variables are baked into the build at build time.
If changing them in Vercel, redeploy is required:
bash
vercel --prod
⚠️ 重要提示:
NEXT_PUBLIC_*
变量会在构建时嵌入到应用中
如果在Vercel中修改了这些变量,需要重新部署
bash
vercel --prod

Validation Workflow

验证流程

1. Validate Local Environment

1. 验证本地环境

bash
undefined
bash
undefined

Check structure

检查结构

python scripts/validate_env.py .env.local --framework nextjs
python scripts/validate_env.py .env.local --framework nextjs

Compare with .env.example

与.env.example对比

python scripts/validate_env.py .env.local --compare-with .env.example
python scripts/validate_env.py .env.local --compare-with .env.example

Check for security issues

检查安全问题

python scripts/scan_exposed.py --check-gitignore
undefined
python scripts/scan_exposed.py --check-gitignore
undefined

2. Check File Precedence

2. 检查文件优先级

bash
undefined
bash
undefined

List all .env files

列出所有.env文件

ls -la .env*
ls -la .env*

Validate each

逐个验证

for file in .env*; do echo "=== $file ===" python scripts/validate_env.py $file --framework nextjs done
undefined
for file in .env*; do echo "=== $file ===" python scripts/validate_env.py $file --framework nextjs done
undefined

3. Sync to Vercel

3. 同步至Vercel

bash
undefined
bash
undefined

Compare local vs Vercel

对比本地与Vercel的变量

python scripts/sync_secrets.py --platform vercel --compare
python scripts/sync_secrets.py --platform vercel --compare

Sync (dry-run first)

同步(先进行试运行)

python scripts/sync_secrets.py --platform vercel --sync --dry-run
python scripts/sync_secrets.py --platform vercel --sync --dry-run

Actually sync

实际同步

python scripts/sync_secrets.py --platform vercel --sync --confirm
undefined
python scripts/sync_secrets.py --platform vercel --sync --confirm
undefined

Common Issues

常见问题

Issue: Variable Undefined in Browser

问题:变量在浏览器中显示为Undefined

Symptom:
process.env.MY_VAR
is
undefined
in component.
Solution: Add
NEXT_PUBLIC_
prefix:
bash
undefined
症状:在组件中
process.env.MY_VAR
的值为
undefined
解决方案:添加
NEXT_PUBLIC_
前缀:
bash
undefined

❌ Wrong

❌ 错误

✅ Correct

✅ 正确

NEXT_PUBLIC_API_URL=https://api.example.com
undefined
NEXT_PUBLIC_API_URL=https://api.example.com
undefined

Issue: Changed Variable Not Reflected

问题:修改变量后未生效

Symptom: Changed
NEXT_PUBLIC_*
variable in Vercel, but app still uses old value.
Solution: Redeploy (variables are baked into build):
bash
vercel --prod
症状:在Vercel中修改了
NEXT_PUBLIC_*
变量,但应用仍使用旧值。
解决方案:重新部署(变量在构建时已嵌入应用):
bash
vercel --prod

Issue: Works Locally, Not in Production

问题:本地正常运行,生产环境出错

Symptom: App works with
.env.local
, fails in production.
Solution: Ensure all variables from
.env.local
are set in Vercel:
bash
undefined
症状:应用在本地使用
.env.local
正常运行,但在生产环境中失败。
解决方案:确保
.env.local
中的所有变量都已在Vercel中设置:
bash
undefined

Compare

对比

python scripts/sync_secrets.py --platform vercel --compare
python scripts/sync_secrets.py --platform vercel --compare

Find missing vars and add them in Vercel UI

找出缺失的变量并在Vercel界面中添加

undefined
undefined

Security Checklist

安全检查清单

  • .env.local
    in
    .gitignore
  • .env.*.local
    in
    .gitignore
  • No secrets in
    NEXT_PUBLIC_*
    variables
  • No
    .env
    files committed with real secrets
  • .env.example
    has structure, not actual values
  • Secrets set directly in Vercel (not in committed files)
  • .env.local
    已加入
    .gitignore
  • .env.*.local
    已加入
    .gitignore
  • NEXT_PUBLIC_*
    变量中无密钥
  • 已提交的
    .env
    文件中无真实密钥
  • .env.example
    仅包含结构,无实际值
  • 密钥直接在Vercel中设置(而非在已提交的文件中)

References

参考资料


Related: validation.md | security.md | frameworks.md

相关文档validation.md | security.md | frameworks.md

Related Skills

相关技能

When using Nextjs, these skills enhance your workflow:
  • react: Core React patterns and hooks for Next.js components
  • tanstack-query: Server-state management with App Router and Server Components
  • drizzle: Type-safe ORM for Next.js server actions and API routes
  • prisma: Alternative ORM with excellent Next.js integration
  • test-driven-development: Testing Next.js App Router, Server Components, and API routes
[Full documentation available in these skills if deployed in your bundle]
使用Next.js时,以下技能可提升你的工作流:
  • react:Next.js组件的核心React模式与钩子
  • tanstack-query:App Router与Server Components的服务端状态管理
  • drizzle:适用于Next.js服务端操作与API路由的类型安全ORM
  • prisma:与Next.js集成良好的替代ORM
  • test-driven-development:测试Next.js App Router、Server Components与API路由
[如果部署在你的技能包中,可查看完整文档]