2.7 环境变量与配置(Environment Variables & Configuration)


2.7 环境变量与配置(Environment Variables & Configuration)

本节摘要:密钥、API 地址、功能开关——不同环境(开发/测试/生产)需要不同配置。本节讲清 .env 文件体系、NEXT_PUBLIC_ 前缀的安全边界、next.config.js 的常用配置,以及"哪些配置绝不能暴露给浏览器"。

学习目标

阅读完本节,你应当能够:

  1. 用 .env/.env.development/.env.production 区分环境
  2. 理解 NEXT_PUBLIC_ 前缀的安全含义
  3. 在服务器组件与客户端组件中读取环境变量
  4. 配置 next.config.js 的常用项
  5. 避免密钥泄露到浏览器

问题与直觉:配置为什么不能写死在代码里

数据库密码、API 密钥、接口地址——写死在代码里:换环境要改代码、密钥进 Git 泄露、多人协作冲突。环境变量的做法:代码里用 process.env.XXX 读取,值放在 .env 文件(不入 Git),部署时按环境注入。

直觉类比:环境变量像"钥匙柜"——代码是"取钥匙的人",.env 是"钥匙柜",不同环境(开发/生产)是不同的钥匙柜。代码不认识具体钥匙,只负责"去柜子里拿"。

💡 关键直觉:NEXT_PUBLIC_ 前缀是"暴露开关"——带这个前缀的变量会内联进浏览器代码(公开);不带前缀的只在服务器可用(保密)。这是 Next.js 环境变量体系最需要记住的一条安全规则。

核心原理:环境变量体系

2.1 .env 文件

.env # 所有环境共享(基础配置) .env.development # 开发环境覆盖 .env.production # 生产环境覆盖 .env.local # 本地私有(不入 Git)
# .env DATABASE_URL=postgresql://user:pass@localhost:5432/app NEXT_PUBLIC_API_BASE=https://api.example.com SECRET_KEY=my-secret-key

优先级.env.local > .env.development/.env.production > .env

2.2 读取环境变量

// 服务器组件/Route Handlers —— 所有变量可读 export async function GET() { const dbUrl = process.env.DATABASE_URL; // 服务器端,安全 return Response.json({ dbUrl: !!dbUrl }); } // 客户端组件 —— 只能读 NEXT_PUBLIC_ 前缀 "use client"; export function ClientWidget() { const base = process.env.NEXT_PUBLIC_API_BASE; // 公开变量 return <div>API: {base}</div>; }

安全边界

变量 服务器组件 客户端组件 说明
DATABASE_URL 密钥,绝不暴露
SECRET_KEY 密钥
NEXT_PUBLIC_API_BASE 公开(API 地址无妨)
NEXT_PUBLIC_ANALYTICS_ID 公开

2.3 .env 与 Git

# .gitignore .env.local .env.*.local

纪律.env 可以提交(放非敏感默认值),.env.local 必须忽略(放真实密钥);仓库里提供 .env.example 模板供新同事复制。

工程实践要点:next.config.js

// next.config.ts import type { NextConfig } from "next"; const nextConfig: NextConfig = { images: { remotePatterns: [{ protocol: "https", hostname: "cdn.example.com" }], }, redirects: async () => [ { source: "/old-path", destination: "/new-path", permanent: true }, ], // 运行时环境变量(对 NEXT_PUBLIC_ 注入更可控) env: { CUSTOM_KEY: process.env.CUSTOM_KEY, }, }; export default nextConfig;

常用配置项

配置 用途
images.remotePatterns 允许的远程图片域名
redirects/rewrites URL 重定向/重写
output: "standalone" 独立部署产物(Docker 优化)
experimental 实验特性(按版本)
env 显式注入环境变量

常见误区与排查

误区 现象 正解
在客户端用非 PUBLIC 变量 值为 undefined 只读 NEXT_PUBLIC_ 前缀
密钥提交 Git 泄露 .env.local 加 gitignore
改 .env 不生效 变量还是旧值 重启 dev 服务器(改 .env 需重启)
生产变量缺失 页面报错 部署平台配置环境变量
把整个 .env 提交 全量泄露 只提交 .env.example

动手演练:安全的配置读取

// lib/config.ts —— 统一读取配置(服务器端) export function getServerConfig() { return { databaseUrl: process.env.DATABASE_URL!, secretKey: process.env.SECRET_KEY!, apiBase: process.env.NEXT_PUBLIC_API_BASE!, }; } // 使用(只能在服务器组件/Route Handler/Server Action 中) // app/api/health/route.ts export async function GET() { const { databaseUrl } = getServerConfig(); return Response.json({ db: !!databaseUrl }); }

规则总结:密钥类配置只在服务器侧使用;需要暴露给浏览器的才加 NEXT_PUBLIC_;统一封装读取函数,避免 process.env 散落各处——配置管理清晰、安全边界明确

本节速览

  • 环境体系:.env / .env.development / .env.production / .env.local。
  • NEXT_PUBLIC_:暴露前缀,带它才进浏览器代码,否则只在服务器。
  • 读取:服务器组件可读全部;客户端组件只能读 PUBLIC。
  • Git 纪律:.env.local 忽略,提供 .env.example。
  • next.config.js:图片域名、重定向、standalone 等。
  • 统一封装:getServerConfig 集中管理配置读取。

深入理解:环境变量的读取时机与安全

环境变量的两种读取时机

关键区分

  • NEXT_PUBLIC_ 前缀变量:构建时内联进客户端代码(浏览器可见,公开信息如 API 地址);
  • 无前缀变量:运行时从服务器进程环境读取(仅服务器可见,密钥类)。

注意:NEXT_PUBLIC_ 变量是"构建时"的——改它的值需要重新构建,不是改环境变量就生效。

安全实践清单

  1. 密钥绝不加 NEXT_PUBLIC_:数据库地址、密钥、令牌全部无前缀;
  2. .env.local 加 gitignore:真实密钥不入仓库;提交 .env.example 模板;
  3. 按环境隔离:开发/预览/生产用不同密钥,泄露影响面最小化;
  4. 最小暴露:客户端只需要 API 地址、分析 ID 等公开信息;
  5. 定期轮换:生产密钥定期更换,怀疑泄露立即轮换。

配置中心化

// lib/config.ts —— 服务器侧配置统一出口 export const serverConfig = { databaseUrl: process.env.DATABASE_URL!, authSecret: process.env.AUTH_SECRET!, }; // lib/public-config.ts —— 客户端可见配置 export const publicConfig = { apiBase: process.env.NEXT_PUBLIC_API_BASE!, analyticsId: process.env.NEXT_PUBLIC_ANALYTICS_ID!, };

一句话:环境变量的纪律是"该公开的显式公开(NEXT_PUBLIC_),该保密的默认保密(无前缀)"——前缀就是安全边界,写代码时先想清楚这个值要不要给浏览器看到。

常见问题速答

问:改 .env 后需要重启吗?
需要。Next.js 在启动/构建时读取环境变量(NEXT_PUBLIC_ 构建时内联),运行中修改不生效。重启 dev 或重新 build。

问:NEXT_PUBLIC_ 变量会暴露给所有人吗?
会。它内联进客户端 JS,任何访问者都能在浏览器源码里看到。所以只放"公开信息"(API 地址、分析 ID),绝不放密钥

问:多个环境怎么管理?
.env(公共)+ .env.development/.env.production(按环境覆盖)+ .env.local(本机私有)。部署平台(Vercel)的环境变量配置优先级更高。

问:数据库地址能放 NEXT_PUBLIC_ 吗?
绝对不能。数据库地址是敏感信息,放无前缀变量,只在服务器侧读取。

问:next.config 的 env 配置和 .env 有什么区别?
next.config 的 env 是"构建时硬编码注入"(每次改都要重新 build);.env 由 Node 运行时加载,更灵活。新项目优先用 .env。

一句话总结

环境变量的安全边界就是 NEXT_PUBLIC_ 前缀——带前缀进浏览器(公开),无前缀只在服务器(保密)。密钥绝不加前缀、.env.local 不入 Git、按环境隔离。配置统一封装(lib/config.ts),让"这个值能不能给浏览器"成为写代码时的第一反应。

动手练习建议

验证环境变量的安全边界:在 .env 里定义 SECRET_KEY=abcNEXT_PUBLIC_SITE_NAME=我的站,在服务器组件里打印两者(都能读到),在客户端组件里打印两者(只有 PUBLIC 能读到,另一个为 undefined)。理解"前缀即边界"。

再实践配置中心化:写 lib/config.ts 统一读取服务器配置,lib/public-config.ts 读取公开配置,并在项目各处使用——不再散落 process.env。最后把 .env.local 加入 .gitignore,提供 .env.example 模板,模拟团队协作的配置交接。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U