Vite 环境变量与运行时配置最佳实践:从 .env 到一份包跑多环境
在前端项目开发中,我们经常需要针对不同环境(开发/测试/预发/生产)切换 API 地址或应用配置等。Vite 提供了 .env 文件机制在构建时注入环境变量到 import.meta.env,但构建后的产物配置是静态的、不可再修改。
在实际生产部署中,常常需要“一份包跑多个环境”,例如相同构建产物要部署到测试/预发/生产,这就需要 运行时配置覆盖 来实现灵活性。 .env 与 vite.config.js组件,就能实现 开发方便 + 部署灵活 的最佳实践方案。
.env 文件加载规则
Vite 会根据 mode 加载对应的 .env 文件,并按顺序合并。
- .env 所有情况下都会加载
- .env.local 所有情况下都会加载,但会被 git 忽略
- .env.[mode] 只在指定模式下加载
- .env.[mode].local 只在指定模式下加载,但会被 git 忽略
加载顺序(后覆盖前):
.env → .env.local → .env.[mode] → .env.[mode].local
Vite 总是会加载 .env 和 .env.local 文件,除此之外还会加载模式特定的 .env.[mode] 文件。在模式特定文件中声明的变量优先级高于通用文件中的变量,但仅在 .env 或 .env.local 中定义的变量仍然可以在环境中使用。
另外,Vite 执行时已经存在的环境变量有最高的优先级,不会被 .env 类文件覆盖。例如当运行 VITE_SOME_KEY=123 vite build 的时候。
.env 类文件会在 Vite 启动一开始时被加载,而改动会在重启服务器后生效。
与命令的关系
{
"scripts": {
"dev": "vite", // 默认 mode=development
"build": "vite build", // 默认 mode=production
"build:staging": "vite build --mode staging", // 使用 .env.staging
"preview": "vite preview" // 预览 dist 产物
}
}
对应关系如下:
npm run dev→.env.developmentnpm run build→.env.productionnpm run build:staging→.env.stagingnpm run preview→ 仅预览打包产物(不会重新加载.env)
环境变量命名规则
必须以 VITE_ 开头才会注入前端
VITE_API_BASE_URL="https://api.example.com"
- 以
VITE_ 开头的变量才会注入到import.meta.env。 - 不以 VITE_ 开头的变量仍可写在
.env,但只能在vite.config.js中通过loadEnv读取
注意:不要把私密信息(token、密码)放在 VITE_ 变量里,会暴露到前端。
所有值必须是字符串
const enabled = import.meta.env.VITE_FEATURE_ENABLED === 'true'
const timeout = Number(import.meta.env.VITE_TIMEOUT_MS || '5000')
如需使用对象:
VITE_FLAGS='{"newUI":true,"abTest":0.3}'
// 获取方式
const flags = JSON.parse(import.meta.env.VITE_FLAGS || '{}')
允许在 .env 中引用已有变量,避免重复:
VITE_API_HOST="https://api.example.com"
VITE_API_VERSION="v1"
VITE_API_BASE_URL="${VITE_API_HOST}/${VITE_API_VERSION}"
结果:VITE_API_BASE_URL=https://api.example.com/v1
内置变量
Vite 提供一些内置变量:
import.meta.env.MODE // "development" | "production" | "staging"
import.meta.env.DEV // true | false
import.meta.env.PROD // true | false
import.meta.env.BASE_URL // 部署时的基础路径
在 vite.config.js 中读取 loadEnv
Vite 提供了 loadEnv(mode, root, prefix) 方法来读取 .env 文件中的变量。
import {
defineConfig, loadEnv
} from 'vite'
export default defineConfig(({ mode
}) => {
const env = loadEnv(mode, process.cwd(), '') // 读取全部变量
console.log(env) // 打印所有环境变量
return {
server: {
proxy: {
'/api': {
target: env.VITE_API_PROXY_TARGET,
changeOrigin: true,
rewrite: (p) => p.replace(/^\/api/, ''),
},
},
},
}
})
参数说明
- mode:当前运行模式,例如 development、production、staging。Vite 会根据这个值去加载对应的 .env.[mode] 文件。
- root:项目根目录路径。一般写 process.cwd(),表示当前 Node.js 进程的工作目录。这告诉 Vite 从哪里开始查找 .env 文件。
- prefix:用于过滤变量前缀。默认是 'VITE_',只会返回 VITE_ 开头的变量。如果写成 ''(空字符串),则返回所有 .env 文件中的变量,包括非 VITE_ 的。
示例
// .env.development
NODE_ENV=development
APP_SECRET=123456 # 不会注入客户端
VITE_API_BASE_URL=http://localhost:3000/api
// vite.config.js
export default defineConfig(({ mode
}) => {
const env = loadEnv(mode, process.cwd(), '')
console.log(env.NODE_ENV) // "development"
console.log(env.APP_SECRET) // "123456"
console.log(env.VITE_API_BASE_URL) // "http://localhost:3000/api"
return {
define: {
__APP_SECRET__: JSON.stringify(env.APP_SECRET), // 可选择性注入
}
}
})
自定义暴露前缀
除了默认的 VITE_,你还可以通过 vite.config.js 中的 envPrefix 配置,允许其它前缀的变量也暴露到客户端代码中:
export default defineConfig({
envPrefix: ['VITE_', 'APP_']
})
这样,在 .env 文件中定义:
APP_TITLE="我的应用"
VITE_API_BASE_URL="https://api.example.com"
就可以在前端代码里直接访问:
console.log(import.meta.env.APP_TITLE) // "我的应用"
console.log(import.meta.env.VITE_API_BASE_URL) // "https://api.example.com"
envPrefix vs loadEnv 的区别
envPrefix(vite.config.js 配置项)
- 控制哪些变量可以被注入到 客户端代码(import.meta.env) 中。
- 默认只允许
VITE_前缀的变量暴露给前端。 - 修改
envPrefix可以增加其它前缀,例如APP_。
影响:运行时前端能不能访问。
loadEnv(mode, root, prefix)(函数参数)
用于在 vite.config.js 里读取 .env 文件。
prefix 参数决定返回的变量前缀过滤:
'VITE_'→ 只返回 VITE_ 开头的变量。''(空字符串) → 返回所有变量(包括非 VITE_ 的)。
影响:配置阶段你能拿到哪些变量。
// .env.development
SECRET_KEY=123456
APP_TITLE="我的应用"
VITE_API_BASE_URL="http://localhost:3000/api"
// vite.config.js
import {
defineConfig, loadEnv
} from 'vite'
export default defineConfig(({ mode
}) => {
const env = loadEnv(mode, process.cwd(), '') // 拿到全部变量
console.log(env.SECRET_KEY) // 123456
console.log(env.APP_TITLE) // 我的应用
console.log(env.VITE_API_BASE_URL) // http://localhost:3000/api
return {
envPrefix: ['VITE_', 'APP_'] // 允许 APP_ 前缀变量暴露到前端
}
})
// 前端使用
console.log(import.meta.env.VITE_API_BASE_URL) // ✅ 可访问
console.log(import.meta.env.APP_TITLE) // ✅ 可访问
console.log(import.meta.env.SECRET_KEY) // ❌ undefined (没有被暴露)
总结
loadEnv(..., prefix)→ 影响 vite.config.js 构建阶段能读到哪些变量。envPrefix→ 影响 import.meta.env 暴露到客户端的变量范围。
两者并不冲突,而是可以配合使用。
- 开发阶段可以读取全部变量(
loadEnv(mode, root, ''))。 - 只想暴露部分变量给前端(通过
envPrefix控制)。
TypeScript 的智能提示
默认情况下,Vite 在 vite/client.d.ts 中为 import.meta.env 提供了类型定义。随着在 .env[mode] 文件中自定义了越来越多的环境变量,你可能想要在代码中获取这些以 VITE_ 为前缀的用户自定义环境变量的 TypeScript 智能提示。
要想做到这一点,你可以在 src 目录下创建一个 vite-env.d.ts 文件,接着按下面这样增加 ImportMetaEnv 的定义:
/// <reference types="vite/client" /> interface ImportMetaEnv { readonly VITE_APP_TITLE: string // 更多环境变量... } interface ImportMeta { readonly env: ImportMetaEnv }
如果你的代码依赖于浏览器环境的类型,比如 DOM 和 WebWorker,你可以在 tsconfig.json 中修改 lib 字段来获取类型支持。
{
"lib": ["WebWorker"]
}
在 `vite-env.d.ts` 文件中使用 `/// <reference types="vite/client" />` 的目的是引入 Vite 的类型定义。这条指令告诉 TypeScript 解析 Vite 提供的类型,包括对 `import.meta` 和其他 Vite 特性的支持。


HTML 环境变量替换
Vite 还支持在 HTML 文件中替换环境变量。import.meta.env 中的任何属性都可以通过特殊的 %CONST_NAME% 语法在 HTML 文件中使用:
<h1>Vite is running in %MODE%</h1>
<p>Using data from %VITE_API_URL%</p>
如果环境变量在 import.meta.env 中不存在,比如不存在的 %NON_EXISTENT%,则会将被忽略而不被替换,这与 JS 中的 import.meta.env.NON_EXISTENT 不同,JS 中会被替换为 undefined。
NODE_ENV 和 模式
在某些情况下,若想在 vite build 时运行不同的模式来渲染不同的标题,你可以通过传递 --mode 选项标志来覆盖命令使用的默认模式。例如,如果你想在 staging (预发布)模式下构建应用:
vite build --mode staging
需要注意的是,NODE_ENV(process.env.NODE_ENV)和模式是两个不同的概念。以下是不同命令如何影响 NODE_ENV 和模式:
| Command | NODE_ENV | Mode |
|---|---|---|
vite build |
"production" |
"production" |
vite build --mode development |
"production" |
"development" |
NODE_ENV=development vite build |
"development" |
"production" |
NODE_ENV=development vite build --mode development |
"development" |
"development" |
NODE_ENV 和模式的不同值也会反映在相应的 import.meta.env 属性上:
| Command | import.meta.env.PROD | import.meta.env.DEV |
|---|---|---|
NODE_ENV=production |
true |
false |
NODE_ENV=development |
false |
true |
NODE_ENV=other |
false |
true |
.env 文件中的 NODE_ENV
NODE_ENV=... 可以在命令中设置,也可以在 .env 文件中设置。
如果在 .env.[mode] 文件中指定了 NODE_ENV,则可以使用模式来控制其值。不过,NODE_ENV 和模式仍然是两个不同的概念。
命令中使用 NODE_ENV=... 的主要好处是,它允许 Vite 提前检测到该值。这也使你能够在 Vite 配置中读取 process.env.NODE_ENV,因为 Vite 只有在解析配置之后才能加载环境变量文件。
在 Vite 中,`mode` 和 `NODE_ENV` 都可以用来指定不同的环境配置,但它们有不同的用途。
- `mode`:用于指定 Vite 的运行模式(如 `development`、`production`、`test` 等),影响 Vite 的行为和配置。
- `NODE_ENV`:通常用于表示 Node.js 环境(如 `development`、`production`),在很多库和框架中用于条件判断。
在 Vite 中,`mode` 会覆盖 `NODE_ENV`,但 `NODE_ENV` 仍然可以被用作一些通用工具或库的环境判断。总的来说,`mode` 在 Vite 中更为重要。

浙公网安备 33010602011771号