开发、测试、预发、生产环境各不相同:API 地址、密钥、调试开关都要换。 主流脚手架都用 .env 文件来解决这件事,它遵循 .env.[mode].[local] 的命名规则,加载时有严格的优先级与覆盖关系。

原文发布在掘金 · 十一个章节完整拆解

下面是这套机制的骨架与结论,完整的场景示例与陷阱清单请到掘金阅读。

在掘金阅读全文

一句话要点

  • 优先级:.env.[mode].local > .env.[mode] > .env.local > .env,后加载的覆盖先加载的。
  • 客户端变量必须带前缀才会被注入:Vite 用 VITE_、CRA 用 REACT_APP_、Vue CLI 用 VUE_APP_。
  • 变量替换发生在构建时,值是字符串;不要用它传任何真正的机密。

一、四个文件,一套规则

.env                # 所有环境都会加载的公共变量
.env.local          # 所有环境都会加载的本地私有变量(通常被 .gitignore 忽略)
.env.[mode]         # 只在特定模式下加载,如 .env.development
.env.[mode].local   # 只在特定模式加载的本地私有变量

mode 由运行时指定的 --mode 参数决定: vite dev 默认 development,vite build 默认 production, vite build --mode staging 就是自定义的 staging。

二、加载顺序与优先级

以 vite build --mode staging 为例,实际加载顺序是:

  1. .env(公共基础)
  2. .env.local(本地覆盖,被 git 忽略)
  3. .env.staging(模式特定,可提交)
  4. .env.staging.local(模式特定本地覆盖,被忽略)
团队共享的基础配置放 .env 或 .env.[mode] 并提交; 个人差异写进 .local,两者互不干扰。

三、前缀是硬性规则

# 仅 VITE_ 开头的变量会被注入到客户端代码
VITE_API_BASE=http://localhost:3000/api
VITE_DEBUG=true

# 这个不会注入,只在 Node 端构建时可用
DB_HOST=localhost

注意 .env 里的值都是字符串,需要布尔或数字时务必显式转换, 比如 VITE_DEBUG === 'true'。

四、团队协作:怎么保证拉下来就能跑

这是最常见的痛点。解法是把变量明确分成两类:

  • 公共配置(API 地址、功能开关、环境标识、Mock 开关)→ 写进 .env.development / .env.production 并提交到仓库。
  • 私密配置(第三方密钥、个人 Token)→ 放在 .env.local,不提交。

再提供一个不含真实值的 .env.example 并提交,新成员加入时的流程就变成: 克隆 → cp .env.example .env.local → 填自己的密钥 → npm run dev。

线上构建同理:CI/CD 环境不需要 .env.local 文件, 而是在平台的环境变量界面注入同名变量,构建时自动读取。

五、四个容易踩的坑

  • 变量替换在构建时发生,无法在运行时动态读取整个 import.meta.env,必须写成具体字段。
  • 忘记加前缀的变量不会被注入客户端,只能在 Node 侧访问。
  • 带前缀的变量会直接打包进浏览器代码,任何人都能看到源码。
  • 值都是字符串,布尔与数字要手动转换。

小结

这套机制优雅的地方在于:用文件名的层级表达配置的层级。 记住三件事就够了——按 --mode 加载、后加载覆盖先加载、客户端变量必须带前缀。

© 2026 HOLZWEGE 返回随笔列表