next.config.ts当中loadEnvFile的作用

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

  1. Next.js 先加载 .env.developmentAPI_URL=``http://localhost:3000

  2. 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 里的 envrewrites 足够;应用代码里直接读 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, },

这里 apiUrlappID 是在 loadEnvFile 之后读取的,所以能拿到正确环境的值。

若删掉 loadEnvFiledev: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 文件,减少手写解析带来的差异。