Skip to content
环境变量与模式

环境变量与模式

Vite 通过 .env 文件和模式(Mode)管理环境变量。所有客户端可访问的变量通过 import.meta.env 暴露。


环境变量基础

文件层级

Vite 使用 dotenv 加载 .env 文件,优先级如下:

文件 用途 Git 跟踪
.env 所有模式下的默认变量 ✅ 提交(模板值)
.env.local 所有模式下的本地变量 ❌ gitignore
.env.[mode] 特定模式的变量 ✅ 提交
.env.[mode].local 特定模式的本地变量 ❌ gitignore

优先级:.env.[mode].local > .env.[mode] > .env.local > .env

模式(Mode)

命令 默认模式 NODE_ENV
vite development development
vite build production production
vite build --mode staging staging production

🚨 陷阱--mode 只改变加载的 .env 文件,不影响 NODE_ENVNODE_ENV 由命令类型决定:vite 永远返回 developmentvite build 永远返回 production


环境变量文件格式

# .env(所有模式共享)
VITE_APP_TITLE=My App
VITE_API_BASE_URL=https://api.example.com

# .env.development(仅开发模式)
VITE_API_BASE_URL=http://localhost:8080/api

# .env.production(仅生产模式)
VITE_API_BASE_URL=https://api.prod.com
VITE_ENABLE_ANALYTICS=true

# .env.staging(自定义 staging 模式)
VITE_API_BASE_URL=https://api.staging.com

# .env.local(本地覆盖,不提交到 Git)
VITE_DB_PASSWORD=secret123

使用环境变量

在客户端代码中

// 所有以 VITE_ 开头的变量会暴露给客户端
console.log(import.meta.env.VITE_API_BASE_URL)
console.log(import.meta.env.VITE_APP_TITLE)

// 不对:没有 VITE_ 前缀,客户端代码中为 undefined
console.log(import.meta.env.DB_PASSWORD)  // undefined

在 vite.config.js 中

// vite.config.js
import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ command, mode }) => {
  // 加载对应模式的环境变量
  const env = loadEnv(mode, process.cwd(), '')

  return {
    define: {
      __APP_MODE__: JSON.stringify(mode),
    },
    server: {
      proxy: {
        '/api': env.VITE_API_TARGET,
      },
    },
  }
})

loadEnv(mode, root, prefixes) 第三个参数可指定前缀:

// 加载所有前缀的环境变量(包括无前缀的)
const env = loadEnv(mode, process.cwd(), '')
// env.DB_PASSWORD 现在可以访问了

// 加载自定义前缀
const env = loadEnv(mode, process.cwd(), ['VITE_', 'APP_'])

import.meta.env 内置变量

变量
import.meta.env.MODE 当前模式:'development' / 'production' / 自定义
import.meta.env.BASE_URL 部署基础路径(由 base 配置决定)
import.meta.env.PROD 是否为生产模式(boolean)
import.meta.env.DEV 是否为开发模式(boolean)
import.meta.env.SSR 是否运行在服务端(SSR 场景)
// 典型用法
if (import.meta.env.PROD) {
  console.log('生产环境,启用 Sentry')
}

if (import.meta.env.DEV) {
  console.log('开发环境,启用调试工具')
}

// 创建 Axios / Fetch 实例
const api = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
})

自定义环境变量前缀

默认只暴露 VITE_ 开头的变量。可以通过 envPrefix 自定义:

// vite.config.js
export default defineConfig({
  envPrefix: ['VITE_', 'APP_', 'PUBLIC_'],
  // 现在 APP_API_URL 和 PUBLIC_ASSETS 也会暴露给客户端
})

🚨 陷阱:不要用空字符串 '' 作为 envPrefix,这会将所有环境变量暴露给客户端,可能导致密钥泄露。


TypeScript 类型提示

import.meta.env 添加类型:

// src/vite-env.d.ts
/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_API_BASE_URL: string
  readonly VITE_APP_TITLE: string
  readonly VITE_ENABLE_ANALYTICS: boolean
  // ... 其他自定义变量
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

💡 最佳实践:为所有自定义环境变量添加类型声明,确保智能提示和拼写检查。


模式详解

development vs production

export default defineConfig(({ mode }) => ({
  plugins: [
    // 开发环境特定插件
    ...(mode === 'development' ? [inspectPlugin()] : []),
  ],
  build: {
    // 开发时不开 minify
    minify: mode !== 'development',
  },
}))

自定义模式示例

# .env.staging
VITE_API_BASE_URL=https://api.staging.example.com
VITE_ENV=staging
vite build --mode staging    # 加载 .env.staging,NODE_ENV=production
// vite.config.js
export default defineConfig(({ mode }) => {
  console.log('Mode:', mode)  // 'staging'

  return {
    define: {
      __ENV__: JSON.stringify(mode),
    },
    build: {
      outDir: `dist-${mode}`,
    },
  }
})

define:编译时常量替换

define 可以在构建时替换代码中的常量:

export default defineConfig({
  define: {
    __VERSION__: JSON.stringify('1.2.3'),
    __DEV__: 'false',                      // 会被 dead-code elimination 移除
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
    // 注意:值必须是可序列化的 JSON 字符串
  },
})
// 源码中使用
console.log(__VERSION__)
if (__DEV__) {
  // 这段代码在生产构建中会被 Tree Shaking 删除
  console.log('dev only')
}

🚨 陷阱define 做的是文本替换,不是表达式求值。值必须是 JSON 字符串或字符串字面量。define: { foo: bar } 如果 bar 不是一个有效的 JSON 串就会出错。

define vs env

维度 import.meta.env define
用途 环境变量(运行时) 编译时常量(构建时)
值类型 字符串(来自 .env) 任何可序列化为 JSON 的值
Tree Shaking ❌ 无法消除死代码 ✅ 常量值可被 Tree Shaking
适用场景 运行时配置(API 地址等) 特性开关、版本号、构建标记