loadEnvFile 的作用,是在 Next.js 默认加载完 env 之后 ,再按你自定义的 APP_ENV 读取对应的 .env.* 文件,并覆盖 process.env 里的同名变量。
它干什么用
javascript
function loadEnvFile(appEnv: string) {
const envPath = resolve(process.cwd(), `.env.${appEnv}`);
if (!existsSync(envPath)) return;
// ... 解析 KEY=VALUE ...
process.env[key] = value;
}
const APP_ENV = process.env.APP_ENV ?? 'development';
loadEnvFile(APP_ENV);
你们用 APP_ENV 区分多套环境(development / test / production),但 Next.js 只认 NODE_ENV:
|---------------------------------------|---------------|--------------------|
| 命令 | NODE_ENV | Next.js 默认加载 |
| pnpm dev / pnpm dev:test | development | .env.development |
| pnpm build:prod / pnpm start:prod | production | .env.production |
所以 pnpm dev:test 时,Next.js 仍会先加载 .env.development,不会 自动加载 .env.test。
loadEnvFile 就是为了补上这一层:
APP_ENV=test → 再读 .env.test,把里面的值写进 process.env。
和 Next.js 原有机制的关系
不会关掉 Next.js 的 env 加载,两者是叠加关系:
1. Next.js 自动加载(按 NODE_ENV) .env → .env.local → .env.development → .env.development.local 2. next.config.ts 执行 loadEnvFile(APP_ENV) → 读取 .env.${APP_ENV},覆盖同名变量 3. next.config 里再用这些值 env: { NEXT_PUBLIC_API_URL: apiUrl, ... }
例如 pnpm dev:test:
-
Next.js 先加载
.env.development→API_URL=``http://localhost:3000 -
loadEnvFile('test')加载.env.test→ 覆盖为API_URL=``https://api.test.winpoker.com
这是有意覆盖,不是 bug。
会不会「破坏」原有配置?
一般不会破坏,但有几处要注意:
1. 会覆盖同名变量(预期行为)
.env.test 里和 Next.js 已加载变量同名的 key,会以 loadEnvFile 为准。
这正是 dev:test 能切到测试 API 的原因。
2. 只读一个文件,没有完整层级
Next.js 原生会按优先级加载多个文件:
.env .env.local .env.[mode] .env.[mode].local
loadEnvFile 只读 .env.${APP_ENV} 这一个文件,不会再去读:
-
.env(基础配置) -
.env.local(本地覆盖) -
.env.test.local等
如果 .env.local 里改了某个值,但 .env.test 里也有同名 key,loadEnvFile 会用 .env.test 的值盖掉 .env.local。
3. 解析能力比 dotenv 弱
手写解析,只支持简单的 KEY=VALUE:
-
不支持
${OTHER_VAR}变量展开 -
不支持
export KEY=VALUE -
不支持多行值
-
带
#的行会当注释跳过
复杂写法可能和 Next.js 原生 dotenv 行为不一致。
4. 执行时机只在 next.config.ts 加载时
loadEnvFile 在 Next 启动/构建、加载 next.config.ts 时执行一次。
对 next.config 里的 env、rewrites 足够;应用代码里直接读 process.env 一般也能拿到更新后的值(同一 Node 进程)。
5. 和你们 env 配置的配合
你们把非 NEXT_PUBLIC_ 变量通过 env 注入前端:
env: { NEXT_PUBLIC_APP_ENV: APP_ENV, NEXT_PUBLIC_API_URL: apiUrl, NEXT_PUBLIC_PRIVY_APP_ID: appID, },
这里 apiUrl、appID 是在 loadEnvFile 之后读取的,所以能拿到正确环境的值。
若删掉 loadEnvFile,dev:test 又会回到 .env.development 的值。
总结
|----------------|-------------------------------------------------------------------------------|
| 问题 | 答案 |
| 干什么用? | 按 APP_ENV 加载 .env.test / .env.production 等,弥补 Next.js 只认 NODE_ENV 的不足 |
| 会破坏 Next.js 吗? | 不会禁用原有加载,只是在后面覆盖同名变量 |
| 主要风险? | 覆盖 .env.local;解析比原生简单;只读单个文件 |
一句话: loadEnvFile 是自定义的「第二层 env 加载」,让 APP_ENV=test 时能用 .env.test,不会破坏 Next.js 机制,但会覆盖同名变量,且不如原生 env 文件层级完整。
如果以后想更稳,可以考虑用 dotenv-cli 或在脚本里指定 env 文件,减少手写解析带来的差异。