Vite 环境变量和模式
什么是环境变量和模式
在 Vite 项目中,环境变量是一些在构建或开发阶段可以动态注入到代码里的键值对。它们通常用来存放与运行环境相关的配置,比如 API 地址、App 标题、调试开关等。模式则决定了 Vite 会加载哪一份环境变量文件,以及如何设置 import.meta.env.MODE 的值。
Vite 使用了 dotenv 来处理环境变量,并默认支持 .env 文件的加载。你可以通过文件名后缀区分不同的模式,真正实现“一次编写,多环境运行”。
内置的环境变量
在任何 Vite 项目中,即使不创建 .env 文件,也可以直接使用以下几个内置变量:
import.meta.env.MODE:当前运行的模式。开发服务器默认为development,构建时默认为production。import.meta.env.BASE_URL:项目部署的基础路径,来自vite.config.js中的base配置。import.meta.env.PROD:布尔值,表示是否处于生产模式。import.meta.env.DEV:布尔值,表示是否处于开发模式。import.meta.env.SSR:布尔值,表示是否在服务端渲染环境中。
这些变量是 Vite 通过静态替换注入的,在构建时会被替换为真正的值,因此不能动态修改,也不能在运行时通过 process.env 获取。
创建自定义环境变量
你需要在项目根目录下创建以下文件:
.env:所有模式下都会加载的公共变量。.env.local:本地覆盖变量,该文件应当被.gitignore忽略,用于存放个人私密配置。.env.[mode]:仅在指定模式下加载,例如.env.development、.env.production。.env.[mode].local:特定模式的本地覆盖变量。
例如,创建一个 .env 文件:
# .env
VITE_API_BASE_URL=https://api.example.com
VITE_APP_TITLE=My Vite App
重要规则:只有以 VITE_ 开头的变量才会被暴露给客户端代码。这是为了防止意外地将敏感变量(如数据库密码)注入到前端代码中。其它变量只有通过 Vite 配置中的 define 或服务端逻辑才能访问。
在 Vue/React 组件或任何 JavaScript 模块中可以直接使用:
console.log(import.meta.env.VITE_API_BASE_URL)
console.log(import.meta.env.VITE_APP_TITLE)
使用 TypeScript 时的类型支持
如果项目使用 TypeScript,可以扩展 ImportMeta 接口以获得类型提示。新建或修改 src/vite-env.d.ts 文件:
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_BASE_URL: string
readonly VITE_APP_TITLE: string
// 更多自定义变量...
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
这样编辑器就能自动补全并校验环境变量的使用。
模式详解
模式(Mode)直接决定了加载哪些 .env 文件。你可以通过命令行参数 --mode 显式指定:
# 开发时使用 staging 模式
vite --mode staging
# 构建时使用 staging 模式
vite build --mode staging
此时 Vite 会尝试加载 .env.staging、.env.staging.local 等文件,并且 import.meta.env.MODE 的值会变成 staging。
常见的模式实践:
- development:开发环境,使用
.env.development,连接本地或测试 API。 - production:生产环境,使用
.env.production,连接正式 API。 - staging / preview:预发布或预览环境,配合 CI/CD 流程。
你还可以在 vite.config.js 中根据模式动态修改配置:
import { defineConfig } from 'vite'
export default defineConfig(({ mode }) => {
const isProd = mode === 'production'
return {
base: isProd ? '/my-app/' : '/',
define: {
__BUILD_TIME__: JSON.stringify(new Date().toISOString())
}
}
})
环境变量加载优先级
当多个文件存在且定义了同一个变量时,Vite 按照以下顺序加载(后面的覆盖前面的):
.env(所有模式公共基础).env.local.env.[mode].env.[mode].local
例如在 production 模式下,如果你有 .env、.env.production 和 .env.production.local,则 .env.production.local 里的值会最终生效。这个机制非常适合本地调试时临时覆盖某些变量。
在 HTML 或配置文件里引用环境变量
虽然大多数场景下我们在 JavaScript 代码里使用环境变量,但有时需要在 index.html 中动态插入值。Vite 支持在 HTML 文件里使用 %VITE_SOME_KEY% 语法:
<title>%VITE_APP_TITLE%</title>
构建或开发时,这个占位符会被替换成实际的环境变量值。
在 Vite 配置文件中,不能直接使用 import.meta.env,因为该对象仅在应用的源代码中可用。如果需要访问环境变量,你可以使用 Node.js 的 process.env,并结合 Vite 提供的 loadEnv 工具函数:
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '')
// 现在 env 里包含了所有前缀匹配的变量,包括非 VITE_ 开头的
return {
define: {
__APP_VERSION__: JSON.stringify(env.APP_VERSION)
}
}
})
loadEnv 的第三个参数可以留空或指定前缀,若设置为空字符串 '',则会加载所有变量(包括没有前缀的),但也需要你手动决定哪些要注入到客户端。
安全注意事项
- 永远不要在客户端代码中暴露敏感数据。只有
VITE_前缀的变量会被打包进前端代码,但即使如此,也不要放密钥、token 等信息,除非你确实需要它公开。 - 敏感变量请保留在服务端,通过 API 间接获取。
.local文件应当始终被 Git 忽略,避免将个人密钥提交到仓库。
常见问题
Q: 修改了 .env 文件后为什么没有生效?
A: 你需要重启 Vite 开发服务器。环境变量在启动时被加载并注入,不会热更新。
Q: 如何在生产构建中动态替换变量?
A: 变量的替换发生在构建时,并不是运行时。如果你需要运行时动态配置,可以将配置文件放在 public 目录下,通过 fetch 异步加载。
Q: 能使用非 VITE_ 开头的变量吗?
A: 默认不会暴露给客户端,但你可以使用 define 在 Vite 配置中手动注入,或是仅在 Node 端使用(比如在 Vite 配置或 SSR 中)。
Q: 多页面应用或库模式下环境变量有何不同?
A: 模式和环境变量机制基本一致,但 import.meta.env.BASE_URL 的取值会依据不同的构建目标(如库模式)而有所不同,要留意官方文档说明。
掌握了 Vite 的环境变量与模式,你就能轻松实现开发、测试、生产等多套环境的无缝切换,让项目配置更加灵活、安全。