环境变量与模式
Vite 通过 .env 文件和模式(Mode)管理环境变量。所有客户端可访问的变量通过 import.meta.env 暴露。
环境变量基础
文件层级
Vite 使用 dotenv 加载 .env 文件,优先级如下:
| 文件 | 用途 | Git 跟踪 |
|---|---|---|
.env |
所有模式下的默认变量 | ✅ 提交(模板值) |
.env.local |
所有模式下的本地变量 | ❌ gitignore |
.env.[mode] |
特定模式的变量 | ✅ 提交 |
.env.[mode].local |
特定模式的本地变量 | ❌ gitignore |
优先级:.env.[mode].local > .env.[mode] > .env.local > .env
模式(Mode)
| 命令 | 默认模式 | NODE_ENV |
|---|---|---|
vite |
development |
development |
vite build |
production |
production |
vite build --mode staging |
staging |
production |
🚨 陷阱:
--mode只改变加载的.env文件,不影响NODE_ENV。NODE_ENV由命令类型决定:vite永远返回development,vite build永远返回production。
环境变量文件格式
# .env(所有模式共享)
VITE_APP_TITLE=My App
VITE_API_BASE_URL=https://api.example.com
# .env.development(仅开发模式)
VITE_API_BASE_URL=http://localhost:8080/api
# .env.production(仅生产模式)
VITE_API_BASE_URL=https://api.prod.com
VITE_ENABLE_ANALYTICS=true
# .env.staging(自定义 staging 模式)
VITE_API_BASE_URL=https://api.staging.com
# .env.local(本地覆盖,不提交到 Git)
VITE_DB_PASSWORD=secret123使用环境变量
在客户端代码中
// 所有以 VITE_ 开头的变量会暴露给客户端
console.log(import.meta.env.VITE_API_BASE_URL)
console.log(import.meta.env.VITE_APP_TITLE)
// 不对:没有 VITE_ 前缀,客户端代码中为 undefined
console.log(import.meta.env.DB_PASSWORD) // undefined
在 vite.config.js 中
// vite.config.js
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ command, mode }) => {
// 加载对应模式的环境变量
const env = loadEnv(mode, process.cwd(), '')
return {
define: {
__APP_MODE__: JSON.stringify(mode),
},
server: {
proxy: {
'/api': env.VITE_API_TARGET,
},
},
}
})loadEnv(mode, root, prefixes) 第三个参数可指定前缀:
// 加载所有前缀的环境变量(包括无前缀的)
const env = loadEnv(mode, process.cwd(), '')
// env.DB_PASSWORD 现在可以访问了
// 加载自定义前缀
const env = loadEnv(mode, process.cwd(), ['VITE_', 'APP_'])import.meta.env 内置变量
| 变量 | 值 |
|---|---|
import.meta.env.MODE |
当前模式:'development' / 'production' / 自定义 |
import.meta.env.BASE_URL |
部署基础路径(由 base 配置决定) |
import.meta.env.PROD |
是否为生产模式(boolean) |
import.meta.env.DEV |
是否为开发模式(boolean) |
import.meta.env.SSR |
是否运行在服务端(SSR 场景) |
// 典型用法
if (import.meta.env.PROD) {
console.log('生产环境,启用 Sentry')
}
if (import.meta.env.DEV) {
console.log('开发环境,启用调试工具')
}
// 创建 Axios / Fetch 实例
const api = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
})自定义环境变量前缀
默认只暴露 VITE_ 开头的变量。可以通过 envPrefix 自定义:
// vite.config.js
export default defineConfig({
envPrefix: ['VITE_', 'APP_', 'PUBLIC_'],
// 现在 APP_API_URL 和 PUBLIC_ASSETS 也会暴露给客户端
})🚨 陷阱:不要用空字符串
''作为envPrefix,这会将所有环境变量暴露给客户端,可能导致密钥泄露。
TypeScript 类型提示
为 import.meta.env 添加类型:
// src/vite-env.d.ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_BASE_URL: string
readonly VITE_APP_TITLE: string
readonly VITE_ENABLE_ANALYTICS: boolean
// ... 其他自定义变量
}
interface ImportMeta {
readonly env: ImportMetaEnv
}💡 最佳实践:为所有自定义环境变量添加类型声明,确保智能提示和拼写检查。
模式详解
development vs production
export default defineConfig(({ mode }) => ({
plugins: [
// 开发环境特定插件
...(mode === 'development' ? [inspectPlugin()] : []),
],
build: {
// 开发时不开 minify
minify: mode !== 'development',
},
}))自定义模式示例
# .env.staging
VITE_API_BASE_URL=https://api.staging.example.com
VITE_ENV=stagingvite build --mode staging # 加载 .env.staging,NODE_ENV=production// vite.config.js
export default defineConfig(({ mode }) => {
console.log('Mode:', mode) // 'staging'
return {
define: {
__ENV__: JSON.stringify(mode),
},
build: {
outDir: `dist-${mode}`,
},
}
})define:编译时常量替换
define 可以在构建时替换代码中的常量:
export default defineConfig({
define: {
__VERSION__: JSON.stringify('1.2.3'),
__DEV__: 'false', // 会被 dead-code elimination 移除
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
// 注意:值必须是可序列化的 JSON 字符串
},
})// 源码中使用
console.log(__VERSION__)
if (__DEV__) {
// 这段代码在生产构建中会被 Tree Shaking 删除
console.log('dev only')
}🚨 陷阱:
define做的是文本替换,不是表达式求值。值必须是 JSON 字符串或字符串字面量。define: { foo: bar }如果bar不是一个有效的 JSON 串就会出错。
define vs env
| 维度 | import.meta.env |
define |
|---|---|---|
| 用途 | 环境变量(运行时) | 编译时常量(构建时) |
| 值类型 | 字符串(来自 .env) | 任何可序列化为 JSON 的值 |
| Tree Shaking | ❌ 无法消除死代码 | ✅ 常量值可被 Tree Shaking |
| 适用场景 | 运行时配置(API 地址等) | 特性开关、版本号、构建标记 |