环境变量与模式
环境变量基础
Vite 在特殊的 import.meta.env 对象上暴露环境变量。这些常量在开发时定义为全局变量,在构建时静态替换以实现 tree-shaking。
内置常量
| 常量 | 类型 | 说明 |
|---|---|---|
import.meta.env.MODE | string | 应用运行的模式 |
import.meta.env.BASE_URL | string | 应用的基础 URL,由 base 配置决定 |
import.meta.env.PROD | boolean | 是否为生产环境 |
import.meta.env.DEV | boolean | 是否为开发环境(PROD 的相反值) |
import.meta.env.SSR | boolean | 是否在服务端渲染 |
使用示例
// 根据环境执行不同逻辑
if (import.meta.env.DEV) {
// 开发环境代码,生产构建时会被 tree-shaking 移除
console.log('开发模式')
}
if (import.meta.env.PROD) {
// 生产环境代码
console.log('生产模式')
}
// 获取基础 URL
const baseUrl = import.meta.env.BASE_URL
自定义环境变量
变量前缀
只有以 VITE_ 开头的环境变量才会暴露给客户端代码:
# .env
VITE_API_URL=https://api.example.com
DB_PASSWORD=secret # 不会暴露给客户端
// ✅ 可以访问
console.log(import.meta.env.VITE_API_URL)
// ❌ undefined
console.log(import.meta.env.DB_PASSWORD)
自定义前缀
可以通过 envPrefix 配置自定义前缀:
// vite.config.js
export default defineConfig({
envPrefix: 'APP_', // 现在以 APP_ 开头的变量会被暴露
})
# .env
APP_API_URL=https://api.example.com
.env 文件
Vite 使用 dotenv 从以下文件加载环境变量:
.env # 所有情况下都会加载
.env.local # 所有情况下都会加载,但会被 git 忽略
.env.[mode] # 只在指定模式下加载
.env.[mode].local # 只在指定模式下加载,但会被 git 忽略
加载优先级
环境变量的加载优先级(从高到低):
- 进程已有的环境变量(最高优先级)
.env.[mode].local.env.[mode].env.local.env(最低优先级)
模式特定变量
# .env.development
VITE_API_URL=http://localhost:8080
# .env.production
VITE_API_URL=https://api.example.com
变量扩展
Vite 支持在 .env 文件中使用变量扩展:
# .env
VITE_APP_NAME=MyApp
VITE_APP_TITLE=Welcome to ${VITE_APP_NAME}
注意:如果值中包含 $,需要用 \ 转义:
KEY=123
NEW_KEY=test\$foo # 结果为: test$foo
模式(Mode)
默认模式
vite(开发服务器):development模式vite build:production模式
自定义模式
可以通过 --mode 选项覆盖默认模式:
# 使用 staging 模式构建
vite build --mode staging
创建对应的 .env 文件:
# .env.staging
VITE_APP_TITLE=My App (Staging)
VITE_API_URL=https://staging-api.example.com
常见模式配置
.env # 共享配置
.env.local # 本地覆盖(不提交到 git)
.env.development # 开发环境
.env.development.local # 本地开发覆盖
.env.production # 生产环境
.env.production.local # 本地生产覆盖
.env.staging # 预发布环境
.env.test # 测试环境
NODE_ENV 与 Mode 的区别
NODE_ENV 和 mode 是两个不同的概念:
| 命令 | 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" |
对 import.meta.env 的影响
| NODE_ENV | import.meta.env.PROD | import.meta.env.DEV |
|---|---|---|
| production | true | false |
| development | false | true |
| 其他 | false | true |
| Mode | import.meta.env.MODE |
|---|---|
| --mode production | "production" |
| --mode development | "development" |
| --mode staging | "staging" |
TypeScript 类型支持
扩展 ImportMetaEnv 接口
为获得自定义环境变量的类型提示,需要扩展 ImportMetaEnv 接口:
// vite-env.d.ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_API_URL: string
readonly VITE_API_TIMEOUT: string
// 更多环境变量...
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
严格类型检查
启用严格类型检查,禁止未知键:
// vite-env.d.ts
interface ViteTypeOptions {
strictImportMetaEnv: unknown
}
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
}
注意事项
不要在 vite-env.d.ts 中使用 import 语句,否则会破坏类型扩展:
// ❌ 错误
import { SomeType } from './types'
interface ImportMetaEnv {
readonly VITE_DATA: SomeType
}
// ✅ 正确
interface ImportMetaEnv {
readonly VITE_DATA: string
}
HTML 中的环境变量
Vite 支持在 HTML 文件中使用 %VAR_NAME% 语法替换环境变量:
<!doctype html>
<html>
<head>
<title>%VITE_APP_TITLE%</title>
</head>
<body>
<h1>Vite is running in %MODE%</h1>
<p>API: %VITE_API_URL%</p>
<!-- 不存在的变量会被忽略 -->
<p>%NON_EXISTENT%</p> <!-- 保持原样 -->
</body>
</html>
在配置中使用环境变量
加载 .env 文件
Vite 故意延迟加载 .env 文件直到用户配置解析完成后。如果需要在配置中使用环境变量,可以手动加载:
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
// 加载当前模式的环境变量
const env = loadEnv(mode, process.cwd(), '')
return {
server: {
port: env.VITE_PORT ? Number(env.VITE_PORT) : 3000,
},
define: {
__APP_VERSION__: JSON.stringify(env.VITE_APP_VERSION),
},
}
})
loadEnv 参数
loadEnv(mode, envDir, prefixes)
| 参数 | 类型 | 说明 |
|---|---|---|
mode | string | 应用运行的模式 |
envDir | string | 环境文件所在的目录 |
prefixes | string | string[] | 变量前缀,默认 "VITE_"。空字符串加载所有变量 |
最佳实践
1. 敏感信息处理
永远不要将敏感信息存储在客户端环境变量中:
# ❌ 错误 - 这些会被打包到客户端代码中
VITE_API_KEY=sk-1234567890
VITE_DB_PASSWORD=secret
# ✅ 正确 - 仅在服务端使用
API_KEY=sk-1234567890 # 不以 VITE_ 开头
对于需要保密的 API 密钥,应该:
- 使用后端服务器或 serverless 函数
- 使用环境变量但不添加
VITE_前缀 - 通过代理转发请求
2. 类型安全
始终为环境变量定义 TypeScript 类型:
// vite-env.d.ts
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_API_URL: string
readonly VITE_API_TIMEOUT: string
readonly VITE_ENABLE_MOCK: string
}
3. 默认值处理
在代码中提供默认值:
const apiUrl = import.meta.env.VITE_API_URL || 'http://localhost:8080'
const timeout = Number(import.meta.env.VITE_API_TIMEOUT) || 5000
const enableMock = import.meta.env.VITE_ENABLE_MOCK === 'true'
4. 环境变量命名
使用清晰的命名规范:
VITE_APP_NAME # 应用名称
VITE_APP_VERSION # 应用版本
VITE_API_URL # API 基础 URL
VITE_API_TIMEOUT # API 超时时间
VITE_ENABLE_FEATURE # 功能开关
5. 文档化
在项目中记录所有环境变量:
## 环境变量
| 变量名 | 说明 | 默认值 | 必需 |
|--------|------|--------|------|
| VITE_APP_TITLE | 应用标题 | - | 是 |
| VITE_API_URL | API 基础 URL | - | 是 |
| VITE_API_TIMEOUT | API 超时时间(ms) | 5000 | 否 |
小结
本章我们学习了 Vite 的环境变量系统:
- 内置常量:
MODE、BASE_URL、PROD、DEV、SSR - 自定义变量:以
VITE_为前缀的变量会暴露给客户端 - .env 文件:支持多种模式和环境特定的配置
- 模式系统:通过
--mode自定义构建模式 - TypeScript 支持:扩展
ImportMetaEnv接口获得类型提示 - HTML 替换:在 HTML 中使用
%VAR_NAME%语法 - 配置中使用:使用
loadEnv在配置文件中加载环境变量
合理使用环境变量可以让你的应用在不同环境中灵活运行,同时保持代码的可维护性和安全性。