一、前言
在 Vue3 项目开发中,我们经常需要区分开发环境与生产环境,用来做环境差异化逻辑:
- 开发环境:开启调试日志、本地接口、热更新、错误提示
- 生产环境:关闭日志、使用线上接口、开启压缩、屏蔽调试代码
不同于 Vue2 + Webpack 的 process.env,Vite 环境机制完全不同,原生不支持 process.env,很多开发者直接沿用旧写法导致报错、环境判断失效。
本文整理 Vite 项目中三种环境判断方案,包含官方推荐写法、模式配置、旧方案兼容适配,附带完整可落地代码与避坑要点。
二、核心概念:开发环境 & 生产环境
- 开发环境(development) :本地运行
npm run dev,用于调试、开发、联调 - 生产环境(production) :项目打包
npm run build,用于服务器上线、线上部署
Vite 内置环境区分机制,可通过自定义环境变量、内置MODE变量、兼容process.env三种方式实现判断。
三、方案一:自定义环境变量(官方最推荐、企业级首选)
Vite 支持根目录配置 .env 系列环境变量文件,可自定义环境标识,灵活度最高、适配性最强,是目前项目通用标准方案。
1、创建环境变量配置文件
在项目根目录新建两个环境配置文件:
.env.development:开发环境变量.env.production:生产环境变量
注意:Vite 环境变量必须以 VITE_ 开头,否则无法在客户端读取
① 开发环境配置 .env.development
ini
# 开发环境
VITE_APP_ENV=development
# 可继续配置开发接口地址、密钥等
VITE_APP_BASE_URL=http://localhost:3000
② 生产环境配置 .env.production
ini
# 生产环境
VITE_APP_ENV=production
# 线上接口地址
VITE_APP_BASE_URL=https://api.prod.com
2、代码中读取环境变量并判断
Vite 项目通过 import.meta.env 读取所有自定义环境变量,支持在 js/ts/vue 文件中直接使用。
arduino
// 判断当前是否为生产环境
if (import.meta.env.VITE_APP_ENV === 'production') {
console.log('✅ 当前为【生产/线上环境】')
// 执行线上逻辑:关闭日志、使用线上接口、开启埋点等
} else {
console.log('✅ 当前为【开发/本地环境】')
// 执行开发逻辑:开启调试、打印日志、本地接口
}
四、方案二:使用 Vite 内置 MODE 模式判断(极简无需自定义变量)
Vite 内置MODE 模式机制,无需手动定义环境变量,执行不同打包命令会自动切换模式,可直接用于环境判断。
1、配置 package.json 打包命令
通过 --mode 参数指定当前运行模式,对应 development / production。
json
{
"scripts": {
"dev": "vite", // 默认 development 模式
"build:prod": "vite build --mode production", // 打包生产环境
"build:dev": "vite build --mode development", // 打包开发环境
"preview": "vite preview --mode production"
}
}
2、通过内置 MODE 判断环境
Vite 内置 import.meta.env.MODE 属性,自动读取当前运行模式,无需额外配置。
arduino
// 利用内置 MODE 判断环境
if (import.meta.env.MODE === 'production') {
console.log('✅ 当前是生产环境')
} else {
console.log('✅ 当前是开发环境')
}
优势:零配置、开箱即用,适合简单项目快速区分环境。
五、方案三:process.env 兼容写法(不推荐、仅做兼容)
Vite 官方不推荐在客户端使用 process.env。
原因:process 是 Node.js 全局变量,仅服务端生效,浏览器客户端默认不存在 process 对象,直接使用会报 process is not defined。
但如果是老项目迁移、需要兼容 Webpack 旧代码,可通过自定义 Vite 插件手动注入环境变量,适配 process.env 写法。
1、自定义环境变量兼容插件
在项目根目录新建 vite-plugin-env-compatible.js 插件文件。
typescript
// vite-plugin-env-compatible.js
import { createFilter } from 'vite'
import { readFileSync } from 'fs'
import path from 'path'
export default ({ command, mode }) => {
// 是否为构建打包阶段
const isBuild = command === 'build'
// 匹配需要替换的文件类型
const filter = createFilter(
['**/*.js', '**/*.ts', '**/*.vue'],
['node_modules/**']
)
return {
name: 'vite-plugin-env-compatible',
transform(code, id) {
// 过滤不需要处理的文件
if (!filter(id) || !isBuild) return
// 根据当前模式读取对应的环境配置文件
const envPath = path.resolve(process.cwd(), `.env.${mode}`)
let envContent = ''
try {
envContent = readFileSync(envPath, 'utf-8')
} catch (err) {
return
}
// 解析环境变量键值对
const envMatches = envContent.match(/[^#\r\n]+/g) || []
const envObj: Record<string, string> = {}
envMatches.forEach((line) => {
const [key, value] = line.split('=')
if (key) {
envObj[key.trim()] = JSON.stringify(value?.trim() || '')
}
})
// 替换代码中 process.env.xxx 变量
Object.keys(envObj).forEach((key) => {
const reg = new RegExp(`process\.env\.${key}`, 'g')
code = code.replace(reg, envObj[key])
})
return code
}
}
}
2、在 vite.config.ts 中注册插件
javascript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import envCompatible from './vite-plugin-env-compatible'
export default defineConfig({
plugins: [vue(), envCompatible()]
})
3、项目中使用 process.env(兼容旧写法)
arduino
if (process.env.VITE_APP_ENV === 'production') {
console.log('生产环境')
}
⚠️ 强烈不推荐新项目使用,仅用于老旧项目迁移兼容。
六、三种方案优劣对比 & 选用规范
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 自定义环境变量 | 灵活、可扩展、官方推荐、稳定 | 需手动创建配置文件 | 所有正式项目、企业级项目(首选) |
| 内置MODE判断 | 零配置、简单快捷 | 无法扩展自定义环境参数 | 简单项目、快速开发 |
| process.env兼容 | 兼容旧Webpack代码 | 需自定义插件、性能差、不规范 | 老旧项目迁移过渡使用 |
七、企业级开发避坑总结
- Vite环境变量强制前缀 :自定义变量必须以
VITE_开头,否则客户端无法读取 - 严禁新项目使用process.env:Vite客户端无process对象,原生使用直接报错
- 环境文件优先级:本地 .env.local 优先级高于 .env.development,可用于个人本地差异化配置
- 环境变量不支持嵌套:所有环境变量均为顶级键值对,无法嵌套对象
- 打包模式必须对应:打包命令 --mode 必须和环境文件名对应,否则读取不到变量
八、最终总结
- 正式项目首选:自定义 VITE_ 环境变量,灵活可控、规范统一、适配性最强
- 简单项目快速用:import.meta.env.MODE,零配置快速区分环境
- 摒弃 process.env 写法,仅做旧项目兼容过渡,新项目禁止使用
掌握以上三种方案,可完美解决 Vite + Vue3 项目所有环境判断场景,适配本地开发、测试环境、线上生产环境的差异化业务逻辑。