目录
快速开始
三步上手
第一步:创建 .env 文件
bash
# .env.development
VITE_API_URL=http://localhost:3000
# .env.production
VITE_API_URL=https://api.example.com
第二步:在代码中访问
typescript
// 任意 .vue、.tsx、.js 文件中
const apiUrl = import.meta.env.VITE_API_URL;
console.log(apiUrl); // 开发环境输出: http://localhost:3000
第三步:运行项目
bash
npm run dev # 自动加载 .env.development
npm run build # 自动加载 .env.production
核心要点
- ✅ 变量名必须以
VITE_开头 - ✅ 修改
.env文件后需重启开发服务器 - ✅ 使用
import.meta.env.变量名访问
核心概念
Vite 环境变量的工作原理
Vite 在构建时会读取 .env 文件,并将环境变量注入到你的应用中。
关键特性:
- 前缀限制 :只有以
VITE_开头的变量才会暴露给客户端代码 - 构建时注入:环境变量在构建时就已经被静态替换到代码中
- 模式驱动 :通过
mode参数决定加载哪个.env.[mode]文件
为什么需要 VITE_ 前缀?
这是一个安全机制,防止敏感信息(如数据库密码、API 密钥)意外暴露到客户端代码中。
bash
# ✅ 会暴露给客户端
VITE_API_URL=https://api.example.com
# ❌ 不会暴露给客户端(仅在 vite.config.ts 中可用)
DATABASE_PASSWORD=secret123
API_SECRET_KEY=xyz789
两种访问方式
客户端代码(浏览器):
typescript
// 只能访问 VITE_ 开头的变量
const apiUrl = import.meta.env.VITE_API_URL;
const mode = import.meta.env.MODE;
const isDev = import.meta.env.DEV;
配置文件(Node.js):
typescript
// vite.config.ts - 可以访问所有变量
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
console.log(env.VITE_API_URL); // ✅ 可以访问
console.log(env.DATABASE_PASSWORD); // ✅ 也可以访问
return { /* ... */ };
});
环境变量文件系统
文件命名规则
Vite 支持以下环境变量文件(按优先级从低到高):
bash
1. .env # 所有环境都会加载(最低优先级)
2. .env.local # 所有环境都会加载,但会被 git 忽略
3. .env.[mode] # 只在指定 mode 时加载
4. .env.[mode].local # 只在指定 mode 时加载,但会被 git 忽略(最高优先级)
加载顺序
后加载的文件会覆盖前面加载的文件中相同的变量
示例:运行 vite --mode development 时
markdown
1. .env → 加载(基础配置)
2. .env.local → 加载(本地覆盖,如果存在)
3. .env.development → 加载(开发环境配置)
4. .env.development.local → 加载(开发环境本地覆盖,如果存在,最高优先级)
文件优先级表
| 优先级 | 文件名 | 何时加载 | Git 状态 | 用途 |
|---|---|---|---|---|
| 1(最低) | .env |
所有模式 | 通常提交 | 公共配置 |
| 2 | .env.local |
所有模式 | 不提交 | 本地公共覆盖 |
| 3 | .env.[mode] |
指定 mode | 通常提交 | 环境特定配置 |
| 4(最高) | .env.[mode].local |
指定 mode | 不提交 | 环境特定本地覆盖 |
| - | .env.example |
从不加载 | 提交 | 仅作示例模板 |
.env.example 说明
.env.example 文件不会被 Vite 自动读取,它只是一个示例模板文件,用于:
- 告诉开发者需要配置哪些环境变量
- 作为文档说明
- 通常提交到 Git 仓库
- 开发者可以复制它来创建实际的
.env文件
命令与环境对应
默认命令行为
| 命令 | NODE_ENV | mode | 读取的 .env 文件 |
|---|---|---|---|
vite |
development |
development |
.env → .env.local → .env.development → .env.development.local |
vite build |
production |
production |
.env → .env.local → .env.production → .env.production.local |
vite preview |
production |
production |
不读取(使用构建时的值) |
vitest |
test |
test |
.env → .env.local → .env.test → .env.test.local |
补充说明 1:vite preview 不读取环境变量
vite preview 不会读取新的 .env 文件,原因:
vite preview只是预览已经构建好的dist目录- 环境变量在
vite build时就已经注入到代码中 preview阶段不会重新构建,所以不会重新读取.env
如果需要不同的预览环境,需要在构建时指定不同的 --mode:
bash
# 构建时使用不同的 mode
vite build --mode staging
vite preview
补充说明 2:NODE_ENV vs mode
细心的读者会注意到,上面的表格中有 NODE_ENV 和 mode 两列,它们是两个独立的概念,容易混淆:
process.env.NODE_ENV
- Node.js 环境变量,控制构建优化(代码压缩、tree-shaking)
- 由 Vite 根据命令自动设置:
vite→development,vite build→production - 在
vite.config.ts中通过process.env.NODE_ENV访问
mode(模式)
- Vite 的模式参数,决定加载哪个
.env.[mode]文件 - 可以是任意自定义值(如
staging、test) - 通过
--mode参数指定,在客户端通过import.meta.env.MODE访问
关键区别:
| 命令 | NODE_ENV | mode | 说明 |
|---|---|---|---|
vite |
development |
development |
默认相同 |
vite build |
production |
production |
默认相同 |
vite build --mode staging |
production |
staging |
可以不同 ⚠️ |
NODE_ENV=test vite build |
test |
production |
可以不同 ⚠️ |
💡 推荐做法 :在 Vite 项目中,优先使用 import.meta.env.MODE 来判断环境,而不是依赖 process.env.NODE_ENV。
最佳实践
1. 完整的文件结构
bash
project/
├── .env # 所有环境的公共配置(提交)
├── .env.development # 开发环境配置(提交)
├── .env.production # 生产环境配置(提交)
├── .env.local # 本地覆盖配置(不提交)
├── .env.example # 示例模板(提交)
└── .gitignore # 添加 .env*.local
示例内容:
bash
# .env - 公共配置
VITE_APP_NAME=My App
# .env.development
VITE_API_URL=http://localhost:3000
VITE_DEBUG=true
# .env.production
VITE_API_URL=https://api.example.com
VITE_DEBUG=false
# .env.example - 示例模板
VITE_API_URL=
VITE_APP_NAME=
2. 命名规范
bash
# ✅ 正确写法
VITE_API_BASE_URL=https://api.example.com
VITE_APP_TITLE=My App
VITE_ENABLE_MOCK=true
# ❌ 错误写法(客户端无法访问)
API_BASE_URL=https://api.example.com
appTitle=My App
规则:
- 必须以
VITE_开头 - 使用全大写字母
- 单词间用下划线分隔
3. 客户端代码使用
typescript
// 访问环境变量
const apiUrl = import.meta.env.VITE_API_URL;
// 内置变量
const mode = import.meta.env.MODE; // 当前模式
const isDev = import.meta.env.DEV; // 是否开发环境
const isProd = import.meta.env.PROD; // 是否生产环境
const baseUrl = import.meta.env.BASE_URL; // 公共基础路径
// 带默认值
const debug = import.meta.env.VITE_DEBUG || 'false';
4. 在 vite.config.ts 中使用
typescript
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ mode }) => {
// 加载环境变量
const env = loadEnv(mode, process.cwd(), '');
return {
// 方式1: 使用 define 注入全局常量
define: {
__APP_VERSION__: JSON.stringify('1.0.0'),
__API_URL__: JSON.stringify(env.VITE_API_URL),
},
// 方式2: 根据环境变量配置插件
server: {
port: Number(env.VITE_PORT) || 3000,
proxy: env.VITE_API_URL ? {
'/api': {
target: env.VITE_API_URL,
changeOrigin: true,
}
} : undefined,
},
};
});
5. TypeScript 类型支持
创建 env.d.ts 为环境变量添加类型:
typescript
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string;
readonly VITE_APP_NAME: string;
readonly VITE_DEBUG: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
常见问题
Q: 为什么我的环境变量在客户端访问不到? A: 确保变量名以 VITE_ 开头,并且重新启动开发服务器。
Q: 如何在不同环境使用不同的配置? A: 创建 .env.development、.env.production 等文件,或使用 --mode 参数。
Q: vite preview 能读取新的环境变量吗? A: 不能,环境变量在构建时就已经注入,需要重新构建才能更新。
Q: .env.example 会被 Vite 加载吗? A: 不会,它只是示例模板,需要复制为实际的 .env 文件。
扩展:其他加载方式
在非 Vite 项目或 Node.js 脚本中,你可能需要其他方式加载环境变量。
方式对比
| 方式 | 适用场景 | 使用方法 | 说明 |
|---|---|---|---|
| Vite 内置 | Vite 项目 | 自动加载,无需配置 | ✅ 推荐 |
| dotenv 库 | Node.js 脚本 | require('dotenv').config() |
需要安装依赖 |
| Node.js 原生 | Node.js 20.6+ | node --env-file=.env app.js |
无需依赖,原生支持 |
| tsx | TypeScript 文件 | tsx --env-file=.env app.ts |
直接运行 .ts 文件 |
dotenv 库使用
bash
npm install dotenv
typescript
// 基本用法
import dotenv from 'dotenv';
dotenv.config();
// 指定文件
dotenv.config({ path: '.env.development' });
// 访问变量
console.log(process.env.DB_HOST);
Node.js 原生支持(20.6+)
bash
# 命令行使用
node --env-file=.env app.js
# package.json
{
"scripts": {
"dev": "node --env-file=.env.development src/index.js"
}
}
TypeScript 类型声明
typescript
// env.d.ts
declare global {
namespace NodeJS {
interface ProcessEnv {
DB_HOST: string;
API_KEY: string;
}
}
}
export {};
适用版本:Vite 5.x+, Node.js 20.6+