专题归档 · 2026 年 2 月(编辑分组,非实际写作日期)
为什么 Vite 的 .env.development.local 没赢过 .env?一次 Nx 加载顺序追查
记录 Nx 与 Vite 两层环境变量加载的交互:文件优先级不等于已经注入 process.env 的值会被覆盖。
当时在 Nx Monorepo 中使用 Vite,我遇到过一个反直觉的现象:按 Vite 的说明,.env.development.local 应该优先于通用 .env,实际读到的却像是通用文件里的旧值。
最初的旧 Note 是一段向 AI 提问后的解释。它提出了 Nx 与 Vite 的二次加载问题,但没有留下项目配置和修复前后的进程环境快照。因此这篇只能写成排查思路,不能宣称已经定位、修复了唯一原因。
两种优先级叠在一起
Vite 的规则是:Mode 专属的文件优先于通用文件。但官方文档还指出一个例外:Vite 启动时 process.env 里已经存在的变量优先级更高,不会被后来的 .env 文件覆盖。
Nx 自己也有一套按项目、Target、Configuration、local 文件排序的环境变量加载规则。Nx 可能先将变量写入当前进程,随后 Vite 在这个环境内启动。如果那时某个键已经存在,即便 Vite 后面加载了看起来优先级更高的文件,也可能保留先前的值。
这并不意味着 Nx 永远“让 .env 压过 .env.local”。官方规则恰好也说明 Nx 倾向优先加载项目范围的 local 文件。要解释特定工程里的现象,必须同时确认文件所在目录、实际命中的 Nx Target、Vite 的 Mode,以及调用之前已有的进程变量。
我更希望怎么排查
- 在启动 Vite 前确认该键是否已经存在于
process.env; - 查 Nx 当前的 Target、Configuration 和项目根目录;
- 核对通用与 Mode 专属环境文件实际放在哪里;
- 清掉外层 Shell/脚本注入的同名变量,再进行对照实验;
- 记录最终
import.meta.env中读出的结果,不把打印一行日志当成完整修复验收。
还要注意:以 VITE_ 开头、能够进入前端打包产物的变量不能放真实密钥。真正的凭据必须留在服务端。
这次最有价值的学习点是:“文件加载优先级”只描述一层规则;工具链前面已经设置的进程变量同样参与最终结果。
官方资料:Nx 环境变量加载规则 · Vite 环境变量与 Mode。