Vite 环境变量终极指南:从原理到企业级实战

在前端工程化中,环境变量(Env)是连接"静态代码"与"动态运行环境"的桥梁。很多开发者在使用 Vite 时,往往只停留在"知道怎么写"的阶段,对背后的运行机制、安全红线以及生产环境的动态部署一知半解。

今天,我们就结合企业级项目的真实场景,一次性把 Vite 的环境变量彻底讲透。

一、 核心概念:Vite 内置的 dotenv 机制

在 Webpack 时代,我们需要手动安装 dotenv 库来解析 .env 文件。但在 Vite 中,这一切都被内置了。Vite 在底层自动集成了 dotenvdotenv-expand,能够自动读取项目根目录下的环境配置文件。

核心安全红线:

为了防止数据库密码、私钥等敏感信息意外暴露到浏览器端,Vite 规定:只有以 VITE_ 为前缀的环境变量,才会被暴露给客户端代码(即你在 Vue/React 组件里写的代码)。

bash 复制代码
# .env
VITE_API_BASE_URL=https://api.example.com   # ✅ 会暴露给前端
DB_PASSWORD=secret123                       # ❌ 不会暴露,前端读取为 undefined

二、 文件加载机制:一半固定,一半自定义

Vite 的环境变量文件必须放在项目的根目录(和 package.json 同级)。它的加载机制是**"合并与覆盖"**。

1. 基础与模式文件

Vite 默认认识两个固定的模式文件:

  • .env:所有环境都会加载的公共基础配置。
  • .env.development:执行 npm run dev 时加载。
  • .env.production:执行 npm run build 时加载。

2. 自定义模式

除了上述两个,其他的名字你完全可以自定义,比如 .env.test.env.staging。你只需要在 package.json 中通过 --mode 参数明确告诉 Vite 即可:

bash 复制代码
"scripts": {
  "dev": "vite",
  "build": "vite build",
  "build:test": "vite build --mode test" // 自定义加载 .env.test
}

3. 加载优先级

当执行构建时,Vite 会先加载 .env,再加载对应模式的文件。如果存在同名变量,模式文件的值会覆盖 .env 的值 。此外,.env.local 文件通常用于本地私有配置,优先级最高,且建议加入 .gitignore

三、 生产环境动态 IP 部署方案

这是企业级项目中最常遇到的痛点:开发环境对接测试服务器,但生产环境部署到客户现场时,IP 和端口是动态的,无法提前写死。

核心认知:

Vite 的 server.proxy 仅仅在本地开发环境生效!当你执行 npm run build 后,生成的是纯静态文件,代理配置自然失效。

优雅解决方案:相对路径 + Nginx 反向代理

第一步:在 .env 中配置统一的相对路径前缀

bash 复制代码
# .env.development
VITE_API_BASE_URL=/dev-api

# .env.production
VITE_API_BASE_URL=/api

第二步:在 Axios 封装中使用

bash 复制代码
const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL, // 读取相对路径
  timeout: 10000
})

第三步:服务器(Nginx)配置拦截

无论你的项目部署在 http://192.168.1.100:8080 还是 https://www.customer.com,浏览器发出的请求都会自动拼接为 当前域名/api/xxx。此时只需在 Nginx 中配置反向代理,将 /api 转发到现场真实的后端服务 IP 即可:

bash 复制代码
location /api {
    proxy_pass http://现场真实的后端IP:端口;
    proxy_set_header Host $host;
}

通过这种架构,前端代码真正做到了"一次打包,到处运行"。

四、 运行环境的本质差异:import.meta.env vs loadEnv

很多开发者在 vite.config.js 中尝试使用 import.meta.env 却报错,这是因为没有理解 Vite 的两种运行环境。

  • import.meta.env(客户端环境) :运行在浏览器中。Vite 在打包时,会把代码里所有的 import.meta.env.VITE_XXX 静态替换成具体的字符串。它只能用在 src/ 目录下的业务代码中。
  • loadEnv(服务端环境) :运行在 Node.js 中。vite.config.js 是在打包开始前执行的,此时 Vite 还没开始干活,自然没有生成 import.meta.env。因此,必须使用 loadEnv 主动读取。

loadEnv 参数详解:

bash 复制代码
import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => {
  // loadEnv(当前模式, 当前工作目录, 变量前缀)
  const env = loadEnv(mode, process.cwd(), '')
  
  return {
    // 将环境变量注入到全局,供 vite.config.js 内部使用
    define: {
      __APP_SECRET__: JSON.stringify(env.APP_SECRET)
    }
  }
})

这里必须提到 process.cwd()(Current Working Directory)。它获取的是你执行 node 命令时所在的目录,而不是代码文件所在的目录。在 Vite 中,我们约定必须在项目根目录执行 npm run dev,因此 process.cwd() 永远指向项目根目录,确保能准确找到 .env 文件。

五、 企业级项目的标准配置模板

在企业级项目中,环境变量不宜过多,核心是解决接口通信和应用基础标识。以下是经过实战检验的必备变量模板:

1. 基础配置(.env)

bash 复制代码
# 应用标题(用于动态修改网页 title)
VITE_APP_TITLE=企业级管理系统
# 接口请求的统一前缀
VITE_API_BASE_URL=/api
# 接口超时时间(毫秒)
VITE_API_TIMEOUT=15000

2. 开发环境(.env.development)

bash 复制代码
# 是否开启 Mock 数据
VITE_ENABLE_MOCK=true
# 是否打印调试日志
VITE_ENABLE_DEBUG=true
# 覆盖基础配置中的 API 前缀(直连测试服务器)
VITE_API_BASE_URL=/dev-api

3. 生产环境(.env.production)

bash 复制代码
# 关闭 Mock 和调试日志,确保生产环境干净利落
VITE_ENABLE_MOCK=false
VITE_ENABLE_DEBUG=false
VITE_API_BASE_URL=/api

六、 进阶最佳实践:动态网页标题

很多项目习惯在 index.html 中写死 <title>,但这在单页应用(SPA)中体验极差。最佳实践是结合 Vue Router 动态更新标题。

1. 路由配置中定义标题

bash 复制代码
const routes = [
  {
    path: '/dashboard',
    component: () => import('@/views/Dashboard.vue'),
    meta: { title: '控制台' }
  }
]

2. 在 main.ts 中监听路由变化

bash 复制代码
import router from './router'

router.afterEach((to) => {
  const defaultTitle = import.meta.env.VITE_APP_TITLE
  // 动态拼接:页面标题 - 默认标题
  document.title = to.meta.title ? `${to.meta.title} - ${defaultTitle}` : defaultTitle
})

这种方式既保留了环境变量中的默认标题,又实现了页面级别的精准标题管理,是企业级中后台系统的标配。

总结

Vite 的环境变量设计兼顾了开发效率与生产安全。掌握 .env 的加载机制、理解 import.meta.envloadEnv 的边界、熟练运用相对路径配合 Nginx 解决动态 IP 部署,是每一个现代前端工程师的必修课。希望这篇指南能帮你彻底理清思路,写出更优雅、更健壮的工程化代码。

相关推荐
刘婉晴1 小时前
【Web漏洞】SQL 注入实战技巧
前端·数据库·sql
di24k24k1 小时前
多个 el-form 共用同一 ref 导致表单校验部分失效
前端·javascript·vue.js·elementui
NutShell Wang2 小时前
每帧重建整条路径、每秒倾倒 48MB 给 GC:实时折线图渲染架构的实测复盘
前端·性能优化·架构·图形渲染·数据可视化·vibe coding
小彤花园2 小时前
和 AI 结对写网站:从 JSON 到一整个工具集
前端·人工智能·程序员
RD_daoyi2 小时前
Google核心算法不再通知!全年持续滚动更新
大数据·服务器·前端·网络·搜索引擎·.net
এ慕ོ冬℘゜2 小时前
纯 CSS 实现自定义 Switch 开关(商品上下架滑块)
前端·css
再吃一根胡萝卜2 小时前
dompdf.js 分页功能完整实现指南
前端
wordbaby2 小时前
App 热更新(OTA)原理深解 —— 以 React Native 为例
前端·react native
再吃一根胡萝卜3 小时前
Vue + dompdf.js 实现简历分页导出的完整踩坑记录
前端