跳到主要内容

环境变量与模式

环境变量基础

Vite 在特殊的 import.meta.env 对象上暴露环境变量。这些常量在开发时定义为全局变量,在构建时静态替换以实现 tree-shaking。

内置常量

常量类型说明
import.meta.env.MODEstring应用运行的模式
import.meta.env.BASE_URLstring应用的基础 URL,由 base 配置决定
import.meta.env.PRODboolean是否为生产环境
import.meta.env.DEVboolean是否为开发环境(PROD 的相反值)
import.meta.env.SSRboolean是否在服务端渲染

使用示例

// 根据环境执行不同逻辑
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 忽略

加载优先级

环境变量的加载优先级(从高到低):

  1. 进程已有的环境变量(最高优先级)
  2. .env.[mode].local
  3. .env.[mode]
  4. .env.local
  5. .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 buildproduction 模式

自定义模式

可以通过 --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_ENVmode 是两个不同的概念:

命令NODE_ENVMode
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_ENVimport.meta.env.PRODimport.meta.env.DEV
productiontruefalse
developmentfalsetrue
其他falsetrue
Modeimport.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)
参数类型说明
modestring应用运行的模式
envDirstring环境文件所在的目录
prefixesstring | 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 的环境变量系统:

  1. 内置常量MODEBASE_URLPRODDEVSSR
  2. 自定义变量:以 VITE_ 为前缀的变量会暴露给客户端
  3. .env 文件:支持多种模式和环境特定的配置
  4. 模式系统:通过 --mode 自定义构建模式
  5. TypeScript 支持:扩展 ImportMetaEnv 接口获得类型提示
  6. HTML 替换:在 HTML 中使用 %VAR_NAME% 语法
  7. 配置中使用:使用 loadEnv 在配置文件中加载环境变量

合理使用环境变量可以让你的应用在不同环境中灵活运行,同时保持代码的可维护性和安全性。