Vue3——使用Vite配置环境变量(Vite中的环境变量和模式、如何使用Vite配置环境变量、不同.env文件的优先级、使用Vite配置环境变量的安全注意事项、树摇、Vite和Vue3的关系)
文章目录
如果想了解更多与 Vue3 有关的内容,可以查看 Vue3 专栏: Vue3
1. Vite中的环境变量和模式
我们先来看一下Vite官方对环境变量和模式的解释:https://cn.vitejs.dev/guide/env-and-mode
https://cn.vitejs.dev/guide/env-and-mode
Vite 在特殊的
import.meta.env对象下暴露了一些常量。这些常量在开发阶段被定义为全局变量,并在构建阶段被静态替换,以使树摇(tree-shaking)更有效。

1.1 内置常量
一些内置常量在所有情况下都可用:
| 变量名 | 类型 | 说明 |
|---|---|---|
import.meta.env.MODE | {string} | 应用运行的模式 |
import.meta.env.BASE_URL | {string} | 部署应用时的基本 URL。由 base 配置项决定 |
import.meta.env.PROD | {boolean} | 应用是否运行在生产环境(使用 NODE_ENV='production' 运行开发服务器或构建应用时使用 NODE_ENV='production') |
import.meta.env.DEV | {boolean} | 应用是否运行在开发环境(永远与 import.meta.env.PROD 相反) |
import.meta.env.SSR | {boolean} | 应用是否运行在 server 上 |
1.2 环境变量
Vite 自动将环境变量暴露在 import.meta.env 对象下,作为字符串
为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码
例如下面这些环境变量:
VITE_SOME_KEY=123
DB_PASSWORD=foobar
只有 VITE_SOME_KEY 会被暴露为 import.meta.env.VITE_SOME_KEY 提供给客户端源码,而 DB_PASSWORD 则不会
console.log(import.meta.env.VITE_SOME_KEY) // "123"
console.log(import.meta.env.DB_PASSWORD) // undefined
如上所示,
VITE_SOME_KEY是一个数字,但在解析时会返回一个字符串。布尔类型的环境变量也会发生同样的情况。在代码中使用时,请确保转换为所需的类型
2. 如何使用Vite配置环境变量
2.1 在项目的根目录下创建一个名为.env的文件
在项目的根目录下创建一个名为.env的文件

2.2 编写.env文件
.env 文件使用 KEY=VALUE 的格式,每行一个变量,不需要加引号,变量命名以VITE_开头
VITE_BACKEND_URL=https://api.default.com
2.3 在代码中使用环境变量
在 Vue 组件中使用环境变量
const backendUrl = import.meta.env.VITE_BACKEND_URL
2.4 示例代码
HomeView.vue
<template>
<div class="home-container">
<div class="content-wrapper">
<!-- 上半部分:内置常量 -->
<div class="section-card">
<div class="section-header">
<h2 class="section-title">内置常量</h2>
<p class="section-subtitle">Vite 内置的环境变量</p>
</div>
<div class="constants-grid">
<div class="constant-item">
<span class="constant-label">MODE</span>
<span class="constant-value">{{ mode }}</span>
</div>
<div class="constant-item">
<span class="constant-label">BASE_URL</span>
<span class="constant-value">{{ baseURL }}</span>
</div>
<div class="constant-item">
<span class="constant-label">PROD</span>
<span class="constant-value boolean">{{ prod }}</span>
</div>
<div class="constant-item">
<span class="constant-label">DEV</span>
<span class="constant-value boolean">{{ dev }}</span>
</div>
<div class="constant-item">
<span class="constant-label">SSR</span>
<span class="constant-value boolean">{{ ssr }}</span>
</div>
</div>
</div>
<!-- 下半部分:环境变量 -->
<div class="section-card">
<div class="section-header">
<h2 class="section-title">环境变量</h2>
<p class="section-subtitle">自定义的环境变量配置</p>
</div>
<div class="env-grid">
<div class="env-item">
<span class="env-label">VITE_BACKEND_URL</span>
<span class="env-value">{{ backendUrl }}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
const mode = import.meta.env.MODE
const baseURL = import.meta.env.BASE_URL
const prod = import.meta.env.PROD
const dev = import.meta.env.DEV
const ssr = import.meta.env.SSR
const backendUrl = import.meta.env.VITE_BACKEND_URL
</script>
<style scoped>
.home-container {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 40px 20px;
box-sizing: border-box;
}
.content-wrapper {
max-width: 800px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 30px;
}
.section-card {
background: rgba(255, 255, 255, 0.95);
border-radius: 24px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
padding: 40px;
transition: all 0.3s ease;
border: 1px solid rgba(255, 255, 255, 0.2);
animation: slideUp 0.6s ease-out;
}
.section-card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
}
.section-header {
text-align: center;
margin-bottom: 30px;
}
.section-title {
font-size: 2.5rem;
font-weight: 800;
color: #2d3748;
margin: 0 0 10px 0;
letter-spacing: -1px;
}
.section-subtitle {
font-size: 1.1rem;
color: #718096;
margin: 0;
font-weight: 400;
}
.constants-grid,
.env-grid {
display: grid;
gap: 20px;
}
.constants-grid {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.env-grid {
grid-template-columns: 1fr;
max-width: 500px;
margin: 0 auto;
}
.constant-item,
.env-item {
background: rgba(102, 126, 234, 0.08);
border: 1px solid rgba(102, 126, 234, 0.2);
border-radius: 16px;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
transition: all 0.3s ease;
}
.constant-item:hover,
.env-item:hover {
background: rgba(102, 126, 234, 0.12);
transform: translateY(-2px);
}
.constant-label,
.env-label {
font-weight: 700;
color: #4c51bf;
font-size: 1rem;
font-family: 'Courier New', monospace;
}
.constant-value,
.env-value {
font-weight: 600;
color: #2d3748;
font-size: 1.1rem;
font-family: 'Courier New', monospace;
background: rgba(255, 255, 255, 0.8);
padding: 8px 16px;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.1);
}
.constant-value.boolean {
color: #38a169;
background: rgba(56, 161, 105, 0.1);
border-color: rgba(56, 161, 105, 0.3);
}
.env-value {
color: #667eea;
background: rgba(102, 126, 234, 0.1);
border-color: rgba(102, 126, 234, 0.3);
}
/* 响应式设计 */
@media (max-width: 768px) {
.home-container {
padding: 20px 15px;
}
.section-card {
padding: 30px 20px;
}
.section-title {
font-size: 2rem;
}
.section-subtitle {
font-size: 1rem;
}
.constants-grid {
grid-template-columns: 1fr;
}
.constant-item,
.env-item {
flex-direction: column;
text-align: center;
gap: 10px;
}
.constant-label,
.env-label {
font-size: 0.9rem;
}
.constant-value,
.env-value {
font-size: 1rem;
}
}
@media (max-width: 480px) {
.section-title {
font-size: 1.75rem;
}
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
开发环境

生产环境(将项目打包后将文件上传到 Nginx 或 Tomcat 等 Web 服务器上)

3. 不同.env文件的优先级
当多个 .env 文件定义了相同的变量时,优先级高的文件会覆盖优先级低的文件中的同名变量
3.1 优先级顺序(.env、.env.local、.env.[mode]、.env.[mode].local)
✅ 最高优先级的是
.env.[mode].local,它会覆盖前面所有文件中同名的变量
以下是 Vite 的 .env 文件加载优先级顺序(从低到高):
.env.env.local.env.[mode].env.[mode].local
假设当前模式是 production,Vite 会按以下顺序加载并合并环境变量:
.env→ 基础变量.env.local→ 本地通用覆盖.env.production→ 生产环境专属变量.env.production.local→ 生产环境本地覆盖(最高优先级)
如果多个文件都定义了 VITE_API_URL,最终生效的是 .env.production.local 中的值
3.2 示例说明
下面我们通过一个具体例子来说明 Vite 中 .env 文件的加载优先级
🎯 场景设定
假设项目当前运行在 **production **模式下,执行命令:
vite build
Vite 默认使用 production 模式,因此会加载与 production 相关的 .env 文件
假设项目根目录下有以下 4 个文件:
.env
.env.local
.env.production
.env.production.local
📄 各文件内容如下:
.env(所有环境通用)
VITE_API_URL=https://api.env.com
.env.local(本地通用覆盖)
VITE_API_URL=https://api.local.com
VITE_DEBUG=false
.env.production(生产环境专用)
VITE_API_URL=https://api.production.com
.env.production.local(生产环境本地覆盖,最高优先级)
VITE_API_URL=https://api.production-local.com
✅ 最终生效的环境变量(在 import.meta.env 中)
import.meta.env.VITE_API_URL // "https://api.production-local.com"
⚠️ 注意
虽然 .env.[mode].local 优先级最高,但它属于全局本地覆盖,建议只用于本地调试,不要提交到版本控制
3.3 已存在的环境变量与.env文件中定义的环境变量的优先级
Vite 执行时已经存在的环境变量(例如操作系统级别的环境变量)有最高的优先级,不会被 .env 类文件覆盖
如果添加操作系统级别的环境变量后显示的还是.env文件中的环境变量,可能是因为 IDE 有缓存,重启 IDE 后再次启动项目就可以了
4. 使用Vite配置环境变量的安全注意事项

安全注意事项
.env.*.local文件应是本地的,可以包含敏感变量。你应该将*.local添加到你的.gitignore中,以避免它们被 git 检入- 由于任何暴露给 Vite 源码的变量最终都将出现在客户端包中,
VITE_*变量应该不包含任何敏感信息
🔐 哪些变量是安全的?哪些是危险的?
✅ 可以暴露的(安全):
这些信息本来就是前端运行所必需的,即使被看到也无妨
- 前端需要调用的 API 地址(如
VITE_API_URL) - 用于配置 UI 的变量(如
VITE_APP_NAME,VITE_THEME_COLOR) - 第三方服务的公开密钥(如 Google Maps 的 前端可用 API Key)
❌ 绝对不能暴露的(危险):
这些必须只存在于服务器端,永远不要出现在前端代码中!
- 后端 API 的认证密钥(如 JWT secret)
- 数据库连接字符串
- 支付接口的私钥(如 Stripe Secret Key)
- 任何需要保密的身份凭证(tokens, passwords, private keys)
5. 补充:树摇(tree-shaking)
5.1 🔍 什么是“树摇”(Tree Shaking)?
树摇(Tree Shaking) 是一种在打包过程中移除未使用代码(dead code elimination)的优化技术
树摇的名字来源于这样一个比喻:想象一棵树,你摇一摇它,那些枯掉的、没用的叶子(未使用的代码)就会掉下来,剩下的只有有用的枝叶(真正被使用的代码)
5.2 🌲 树摇是怎么工作的?
树摇主要依赖于 ES6 模块系统(ESM)的静态结构,也就是说:
import和export是静态声明(不能在运行时动态改变)- 打包工具(如 Vite、Rollup、Webpack)可以在打包前分析哪些模块被导入了,哪些函数/变量根本没被用到
✅ 举个例子:
// utils.js
export const fetchUser = () => { /* ... */ }
export const fetchProduct = () => { /* ... */ }
export const debugLog = () => { console.log("Debug!") }
// main.js
import { fetchUser } from './utils.js'
fetchUser()
在打包时,打包工具发现:
fetchProduct没被用debugLog没被用
👉 所以它们会被“摇掉”——不会被打包进最终的生产代码中,从而减小包体积
5.3 🔄 Vite 如何利用树摇优化 import.meta.env?
Vite 在构建时会把 import.meta.env 中的变量静态替换成实际值,例如:
if (import.meta.env.DEV) {
console.log('这是开发环境')
}
会被构建工具替换为:
if (true) { // 因为当前是开发环境
console.log('这是开发环境')
}
然后,构建工具(如 Rollup)会进一步优化:
- 如果某个
if (false)的分支,整个代码块都会被移除 - 这样对应的代码就不会被打包进去
✅ 举个实际例子:
if (import.meta.env.MODE === 'development') {
console.log('开发调试信息')
}
在生产构建中,MODE 是 'production',所以这行代码会被替换为:
if ('production' === 'development') { // false
console.log('开发调试信息')
}
然后构建工具发现这是一个永远不成立的 if (false),于是整个 console.log 代码块被完全移除
👉 这就是树摇的威力:不仅删掉了没用的函数,还能删掉根据环境判断的无用逻辑
5.4 ✅ 树摇的好处
| 好处 | 说明 |
|---|---|
| 📦 包体积更小 | 没用的代码不会被打包,加载更快 |
| ⚡ 性能更好 | 浏览器下载和解析的代码更少 |
| 🧹 代码更干净 | 生产环境不会包含开发调试代码 |
5.5 ❗ 注意:树摇只对 ESM 有效
- ✅ 使用
import / export(ES 模块) → 支持树摇 - ❌ 使用
require / module.exports(CommonJS) → 通常不支持树摇(因为是动态的)
所以现代前端项目推荐使用 ES 模块语法
5.6 ✅ 对树摇的总结
树摇(Tree Shaking) = 打包时自动删除未使用的代码
Vite 利用树摇来:
- 移除没有用到的函数、模块
- 移除基于
import.meta.env的无效分支(如开发日志) - 让最终的客户端代码更轻量、更高效
6. 补充:Vite和Vue3的关系
Vite 是一个“通用”工具,而 Vue 3 是一个“框架”
- Vite 是构建工具:它不关心你用的是什么框架。你可以用 Vite 来开发 React、Preact、Svelte、Lit 等任何现代前端框架项目。它负责处理文件编译、服务启动、热更新、生产打包等工程化问题
- Vue 3 是前端框架:它提供了一套用于构建用户界面的核心库和编程范式(响应式、组件化、路由、状态管理等)。它本身不关心你用什么工具来打包和构建它
Vite 最初就是为了更好地开发 Vue 3 而创建的。尤雨溪在设计 Vue 3 的 Composition API 和 SFC(Single File Component,单文件组件)时,希望有一个能充分发挥其潜力的构建工具,因此,Vite 对 Vue 提供了一等公民的支持:
- 开箱即用:使用
npm create vue@latest(官方脚手架)创建的 Vue 3 项目,默认就是使用 Vite 作为构建工具。你不需要任何复杂配置,就能立即获得极速的开发体验 - 内置对
.vue文件的支持:Vite 内部集成了@vitejs/plugin-vue,这个插件负责在开发时即时编译.vue文件,使其能被浏览器通过 ESM 加载 - HMR 针对 Vue 优化:Vite 的 HMR 策略与 Vue 的组件更新机制完美结合,确保组件更新时的高效和状态保留
- ESM(ECMAScript Modules,ECMAScript 模块):一种官方的、标准化的 JavaScript 模块系统,让你可以在一个 JavaScript 文件中导入(
import)和导出(export)代码,从而实现代码的拆分和复用 - HMR(Hot Module Replacement,热模块替换):一种开发时功能,允许你在修改代码后,将发生变化的模块实时更新到浏览器中,而无需刷新整个页面
更多推荐


所有评论(0)