Vite 环境变量与 import.meta.env
说明 Vite 的 mode、.env 文件加载顺序、VITE_ 前缀与 import.meta.env 在开发/构建中的替换语义。
#type / concept
#status / growing
#tech / dev / frontend
#resource / javascript
[!info] 关联笔记
- 所属:Vite 基础 MOC
- 前置:Mode 模式 · 双路径
- 后续:开发服务器与代理
- 实战坑:Nx 与 env 冲突
Vite 环境变量与 import.meta.env
这个概念为什么出现
前端不能像服务端那样随便把密钥打进浏览器包。项目又需要:
- 开发 / 预发 / 生产 API 地址不同
- 功能开关随环境变化
- 构建期注入版本号
Vite 用 mode + .env* + import.meta.env 给出约定,而不是让业务代码直接读任意 process.env。
[!abstract] 一句话理解 只有暴露给客户端的变量(默认
VITE_前缀)会进入import.meta.env,并在构建时被静态替换;mode 决定加载哪套.env文件。
最小可运行示例
场景:库存后台在本地连 mock,预发连测试网关
# .env
VITE_APP_TITLE=库存后台
# .env.development
VITE_API_BASE_URL=http://localhost:3000
# .env.staging
VITE_API_BASE_URL=https://api.staging.example.com
// src/api/client.ts
// 业务意图:所有列表请求打到当前环境的 API 根路径。
// 教学点:只读取 VITE_ 变量;缺省时要显式处理,不能假设一定有值。
const apiBase = import.meta.env.VITE_API_BASE_URL
export async function fetchLowStockItems() {
if (!apiBase) {
// 失败路径:配置缺失应尽早暴露,避免请求打到相对路径的错误服务
throw new Error('VITE_API_BASE_URL is not defined')
}
const response = await fetch(`${apiBase}/inventory/low-stock`)
if (!response.ok) {
throw new Error(`low-stock request failed: ${response.status}`)
}
return response.json()
}
// 教学点:MODE/DEV/PROD 是内置键
export function envBanner() {
return `${import.meta.env.VITE_APP_TITLE} @ ${import.meta.env.MODE}`
}
建议运行:
pnpm dev # mode=development,加载 .env + .env.development
pnpm build --mode staging
pnpm preview
期望:
dev 横幅类似:库存后台 @ development
staging 构建后 API 指向测试网关;
源码中不会出现未以 VITE_ 暴露的私密变量。
结合场景再看三个关注点
- 前缀是安全边界,不是风格偏好。
- mode 选文件,
NODE_ENV不承担全部环境命名。 - 构建期替换:不要指望改服务器 env 文件就能改已构建的静态包。
核心规则
- 加载顺序(同名后者覆盖,细节以官方为准):
.env→.env.[mode]→.env.local/.env.[mode].local - 客户端暴露:默认仅
VITE_*(可用envPrefix配置,但更要谨慎) - 内置:
MODE、BASE_URL、PROD、DEV、SSR - TypeScript:在
vite-env.d.ts扩展ImportMetaEnv
边界与反直觉
- 未定义的
import.meta.env.VITE_X为undefined,不自动抛错 .local文件通常不入库,避免把个人密钥提交- 服务端密钥应放在 BFF/网关,不要
VITE_暴露
常见误区
[!warning] 常见误区:把 mode 当成 NODE_ENV 的别名
staging可以是自定义 mode;生产构建时NODE_ENV仍可能是 production。以官方 mode 文档为准。
工程实践
- API 根路径、Sentry DSN 等“本来就要进前端”的配置才用
VITE_ - CI 用
--mode选择环境,而不是手工改文件 - monorepo 注意工具链重复加载 env 的冲突(见既有 debug 笔记)
本节总结
环境变量系统是 Vite 工程化的开关面板:mode 选文件,VITE_ 控暴露,import.meta.env 在构建时落地。
自测题
- 数据库密码能否放进
.env.production并以VITE_读取? - 为什么改
.env后有时要重启 dev server?
参考答案
- 不能;会打进前端包,等于公开。
- env 在服务启动时加载;多数改动不会热更新进已运行进程。
延伸阅读
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Env Variables and Modes | 官方 | 加载与前缀规则 |