Skip to content

环境变量管理

本文档介绍如何在 VitePress 项目中配置和使用环境变量,实现开发环境和生产环境的配置分离。

基础概念

什么是环境变量?

环境变量是在应用程序运行时可以访问的动态值,常用于:

  • 区分开发/生产环境
  • 存储敏感信息(API 密钥等)
  • 配置不同环境的参数
  • 避免在代码中硬编码

Vite 环境变量

VitePress 基于 Vite,继承了 Vite 的环境变量系统:

  • import.meta.env - 暴露环境变量
  • .env 文件 - 存储环境变量
  • VITE_ 前缀 - 客户端访问的前缀

环境变量文件

文件类型

VitePress 支持以下环境变量文件:

文件名说明
.env所有环境默认加载
.env.local所有环境,但被 git 忽略
.env.[mode]指定模式加载
.env.[mode].local指定模式,被 git 忽略

创建环境文件

bash
# 项目根目录
docs/
├── .env              # 通用环境变量
├── .env.local        # 本地私有变量(不提交)
├── .env.development  # 开发环境变量
├── .env.production   # 生产环境变量
└── .vitepress/

环境文件内容

bash
# .env - 通用配置
VITE_APP_TITLE=VitePress 学习指南
VITE_APP_VERSION=1.0.0

# .env.development - 开发环境
VITE_API_BASE_URL=http://localhost:3000/api
VITE_ENABLE_DEBUG=true

# .env.production - 生产环境
VITE_API_BASE_URL=https://api.example.com
VITE_ENABLE_DEBUG=false

# .env.local - 本地私有配置(敏感信息)
VITE_ALGOLIA_API_KEY=your-secret-key
VITE_GA_ID=G-XXXXXXXXXX

注意

只有以 VITE_ 开头的变量才会暴露给客户端代码。

使用环境变量

在配置文件中使用

ts
// docs/.vitepress/config.mts
import { defineConfig, loadEnv } from 'vitepress'

// 加载环境变量
const env = loadEnv('', process.cwd())

export default defineConfig({
  title: env.VITE_APP_TITLE || '默认标题',
  
  head: [
    // 使用环境变量配置 Google Analytics
    ...(env.VITE_GA_ID ? [
      [
        'script',
        { async: '', src: `https://www.googletagmanager.com/gtag/js?id=${env.VITE_GA_ID}` }
      ],
      [
        'script',
        {},
        `window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', '${env.VITE_GA_ID}');`
      ]
    ] : [])
  ]
})

在 Vue 组件中使用

vue
<script setup>
import { ref } from 'vue'

// 访问环境变量
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL
const isDev = import.meta.env.DEV
const isProd = import.meta.env.PROD
const mode = import.meta.env.MODE

console.log('API 地址:', apiBaseUrl)
console.log('开发模式:', isDev)
console.log('生产模式:', isProd)
</script>

<template>
  <div>
    <p>环境: {{ mode }}</p>
    <p v-if="isDev">当前为开发环境</p>
  </div>
</template>

在 Markdown 中使用

markdown
<script setup>
const appVersion = import.meta.env.VITE_APP_VERSION
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL
</script>

当前应用版本: {{ appVersion }}

API 基础地址: {{ apiBaseUrl }}

内置环境变量

VitePress 提供以下内置环境变量:

变量说明示例值
import.meta.env.MODE运行模式development / production
import.meta.env.DEV是否为开发环境true / false
import.meta.env.PROD是否为生产环境true / false
import.meta.env.SSR是否为服务端渲染true / false
import.meta.env.BASE_URL部署基础路径/

使用示例

vue
<script setup>
import { computed } from 'vue'

const envLabel = computed(() => {
  if (import.meta.env.DEV) return '开发环境'
  if (import.meta.env.PROD) return '生产环境'
  return '未知环境'
})
</script>

<template>
  <div class="env-badge">
    {{ envLabel }}
  </div>
</template>

define 配置

静态替换

使用 define 在构建时进行静态替换:

ts
// docs/.vitepress/config.mts
export default defineConfig({
  define: {
    __APP_VERSION__: JSON.stringify('1.0.0'),
    __BUILD_TIME__: JSON.stringify(new Date().toISOString()),
    __DEBUG__: process.env.NODE_ENV === 'development'
  }
})

在代码中使用:

ts
// 类型声明
declare const __APP_VERSION__: string
declare const __BUILD_TIME__: string
declare const __DEBUG__: boolean

console.log('应用版本:', __APP_VERSION__)
console.log('构建时间:', __BUILD_TIME__)

if (__DEBUG__) {
  console.log('调试信息...')
}

TypeScript 类型支持

创建类型声明文件:

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

interface ImportMetaEnv {
  readonly VITE_APP_TITLE: string
  readonly VITE_APP_VERSION: string
  readonly VITE_API_BASE_URL: string
  readonly VITE_ENABLE_DEBUG: string
  readonly VITE_ALGOLIA_API_KEY?: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

// define 变量类型
declare const __APP_VERSION__: string
declare const __BUILD_TIME__: string

模式管理

默认模式

VitePress 有两个默认模式:

  • development - 运行 vitepress dev
  • production - 运行 vitepress build

自定义模式

bash
# 使用自定义模式运行
vitepress dev docs --mode staging

# 使用自定义模式构建
vitepress build docs --mode staging

创建对应的环境文件:

bash
# .env.staging
VITE_API_BASE_URL=https://staging-api.example.com
VITE_ENV=staging

在 package.json 中配置

json
{
  "scripts": {
    "dev": "vitepress dev docs",
    "dev:staging": "vitepress dev docs --mode staging",
    "build": "vitepress build docs",
    "build:staging": "vitepress build docs --mode staging",
    "preview": "vitepress preview docs"
  }
}

敏感信息处理

不要暴露敏感信息

安全警告

永远不要在客户端代码中暴露真正的敏感信息,如:

  • 数据库密码
  • 私钥
  • OAuth 密钥
  • 第三方服务的 Secret Key

安全实践

bash
# .env.local - 仅用于非敏感配置
VITE_ALGOLIA_APP_ID=your-app-id  # 可以暴露(只读)

# .env.production - 敏感信息通过服务端注入
# ALGOLIA_ADMIN_KEY=xxx  # 不要使用 VITE_ 前缀,构建时注入

使用占位符

对于敏感信息,使用占位符或运行时注入:

ts
// docs/.vitepress/config.mts
export default defineConfig({
  head: [
    [
      'script',
      {},
      `window.ALGOLIA_API_KEY = '${process.env.ALGOLIA_API_KEY || 'placeholder'}';`
    ]
  ]
})

然后在构建时注入:

bash
# CI/CD 中
ALGOLIA_API_KEY=xxx npm run build

环境变量加载优先级

优先级从高到低:

  1. 命令行注入
  2. .env.[mode].local
  3. .env.[mode]
  4. .env.local
  5. .env
bash
# 命令行注入优先级最高
VITE_APP_TITLE="测试标题" npm run docs:dev

实际应用示例

多环境 API 配置

vue
<script setup>
import { ref } from 'vue'

const apiBaseUrl = import.meta.env.VITE_API_BASE_URL

async function fetchData() {
  const response = await fetch(`${apiBaseUrl}/posts`)
  const data = await response.json()
  return data
}
</script>

条件渲染

vue
<template>
  <div>
    <!-- 仅在开发环境显示调试面板 -->
    <div v-if="import.meta.env.DEV" class="debug-panel">
      <h3>调试信息</h3>
      <pre>{{ debugData }}</pre>
    </div>
    
    <!-- 生产环境显示统计代码 -->
    <Analytics v-if="import.meta.env.PROD" />
  </div>
</template>

动态配置主题

ts
// docs/.vitepress/config.mts
import { defineConfig, loadEnv } from 'vitepress'

const env = loadEnv('', process.cwd())

export default defineConfig({
  title: env.VITE_APP_TITLE,
  description: env.VITE_APP_DESCRIPTION,
  
  themeConfig: {
    // 根据环境配置不同的社交链接
    socialLinks: env.VITE_ENABLE_SOCIAL === 'true' ? [
      { icon: 'github', link: 'https://github.com/xxx' }
    ] : []
  }
})

检查环境变量

打印当前环境变量

vue
<script setup>
const env = import.meta.env
</script>

<template>
  <div class="env-debug">
    <h3>环境变量</h3>
    <ul>
      <li v-for="(value, key) in env" :key="key">
        <strong>{{ key }}:</strong> {{ value }}
      </li>
    </ul>
  </div>
</template>

验证必需变量

ts
// docs/.vitepress/config.mts
import { defineConfig, loadEnv } from 'vitepress'

const env = loadEnv('', process.cwd())

// 验证必需的环境变量
const requiredEnvVars = ['VITE_APP_TITLE', 'VITE_API_BASE_URL']

requiredEnvVars.forEach(varName => {
  if (!env[varName]) {
    console.warn(`警告: 缺少环境变量 ${varName}`)
  }
})

export default defineConfig({
  // ...
})

.gitignore 配置

确保敏感文件不被提交:

gitignore
# 环境变量文件
.env.local
.env.*.local

# 包含敏感信息的文件
.env.production.local

常见问题

Q: 为什么我的环境变量读不到?

A: 检查以下几点:

  1. 变量名是否以 VITE_ 开头
  2. 文件位置是否正确(项目根目录或 docs 目录)
  3. 是否重启了开发服务器

Q: 如何在构建时注入变量?

A: 使用命令行或 CI/CD 环境:

bash
VITE_VAR=value npm run build

Q: 开发环境和生产环境配置不同怎么办?

A: 使用不同的 .env 文件,或使用 define 配置:

ts
export default defineConfig({
  define: {
    __API_URL__: JSON.stringify(
      process.env.NODE_ENV === 'production' 
        ? 'https://api.example.com' 
        : 'http://localhost:3000'
    )
  }
})

下一步

学习 Markdown 扩展语法 了解更多内容编写技巧。

贡献者

加载中...

想要成为贡献者?

在 CNB 上参与贡献