Skip to content

Next.js 与 Vite 环境变量加载顺序差异解析 ​

译注:本文翻译自 dev.to 文章《Why your .env.local change did nothing in Next.js or Vite》,作者 Arthur031221,原文发布于 2026 年 10 月 1 日。原文链接见文末。

你修改了 .env.local,重启了开发服务器,但旧值依然生效。造成这种情况的原因通常有两个:变量已经在 shell 中被设置,或者文件加载顺序与你设想的不一致。

两个框架的规则并不相同 ​

在 Next.js 和 Vite 中,shell 里已存在的变量优先级高于所有 .env 文件。在此之后,两者的顺序开始出现分歧。

在 Next.js 中(非测试模式),优先级从高到低依次为 .env.[mode].local、.env.local、.env.[mode]、.env。在测试模式下,.env.local 会被跳过。

在 Vite 中,顺序为 .env.[mode].local、.env.[mode]、.env.local、.env。.env.local 位于模式专属文件之下,与 Next.js 正好相反。Vite 还接受任意模式名,因此 vite --mode staging 会读取 .env.staging。

作者表示,他对照了加载器本身(@next/env 与 Vite 的 loadEnv)来核实这两个顺序,而不仅仅是查阅文档。此外,Vite 文档在 9 月也曾有一个 issue 要求澄清这一顺序。

一条命令查看哪个来源生效 ​

envwhy 可以针对单个 key 给出答案:

plaintext
npx github:Arthur031221/envwhy API_URL

在项目目录中运行即可。它会从 package.json 识别框架,按优先级构建来源列表,并标出胜出者所在的文件与行号。每个被遮蔽的定义都会标注其值是否相同,方便你一眼看出过期的副本是否要紧。除非传入 --show-values,否则值会被隐藏,因此输出可以安全地粘贴到 bug 报告中。

加上 --mode production 可以查看构建时答案如何变化。不带 key 运行则会列出所有在多个位置定义的 key。

它会自我校验 ​

构建完表格后,envwhy 会在独立进程中运行项目中安装的 @next/env 或 vite 包,加载同一个 key 并进行比对。最后一行会显示 verified、unverified 或 skipped。如果显示 unverified,请把表格当作猜测。

它的局限 ​

它只对 Next.js 和 Vite 建模。它不处理 $VAR 展开,看不到 npm 脚本内部设置的变量,且默认只读取一个目录,除非传入 --env-dir。当发现带有 envDir 或 envPrefix 的 vite.config、Bun 项目,或包裹在 dotenv、cross-env 中的脚本时,它会打印提示,因为这些情况可能改变结果。

代码采用 MIT 许可,无运行时依赖:https://github.com/Arthur031221/envwhy

如果你的项目布局导致结果错误,可以附上文件和输出提交 issue。

原文链接 ​

https://dev.to/arthur031221/why-your-envlocal-change-did-nothing-in-nextjs-or-vite-16lp