npm package: @qjmyrs/vite-plugin-runtime-env
Description: Vite 插件：支持运行时环境配置
Author: qjmyrs
Latest version: 1.0.1

# @company/vite-plugin-runtime-env

Vite 插件，支持在单一构建产物中包含多环境配置，运行时动态选择。

## 特性

- ✅ 完全兼容现有 `.env`、`.env.production` 等配置文件
- ✅ 一次构建，部署到所有环境
- ✅ 支持自定义环境检测逻辑
- ✅ 支持 Vite 2/3/4/5
- ✅ 提供虚拟模块 `@runtime-env` 便捷访问配置

## 安装

```bash
npm install @company/vite-plugin-runtime-env --save-dev
```

## 使用

### 基础配置

```javascript
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vitePluginRuntimeEnv from '@company/vite-plugin-runtime-env';

export default defineConfig({
  plugins: [
    vue(),
    vitePluginRuntimeEnv({
      // 项目根目录，默认 process.cwd()
      root: __dirname,
      
      // 需要包含的环境列表
      envs: ['development', 'test', 'staging', 'production'],
      
      // 环境变量前缀，Vite 默认是 VITE_
      prefix: 'VITE_',
      
      // 是否启用调试日志
      debug: false
    })
  ]
});
```

### 自定义环境检测

```javascript
// vite.config.js
import vitePluginRuntimeEnv from '@company/vite-plugin-runtime-env';

export default defineConfig({
  plugins: [
    vue(),
    vitePluginRuntimeEnv({
      envs: ['development', 'test', 'staging', 'production'],
      prefix: 'VITE_',
      
      // 自定义环境检测函数（字符串形式）
      envDetector: `
        function() {
          // 方案 1: 优先使用 URL 参数
          var params = new URLSearchParams(window.location.search);
          var envParam = params.get('env');
          if (envParam) return envParam;
          
          // 方案 2: 使用 localStorage（本地调试）
          var localEnv = localStorage.getItem('DEBUG_ENV');
          if (localEnv) return localEnv;
          
          // 方案 3: 基于域名
          var hostname = window.location.hostname;
          if (hostname.includes('test')) return 'test';
          if (hostname.includes('staging')) return 'staging';
          if (hostname === 'localhost') return 'development';
          
          return 'production';
        }
      `
    })
  ]
});
```

## 使用方式

### 方式 1：使用虚拟模块（推荐）

```javascript
// 在 Vue 组件或 JS 文件中
import { getConfig, getEnvValue, getCurrentEnv } from '@runtime-env';

// 获取当前环境名称
const env = getCurrentEnv();
console.log('当前环境:', env);

// 获取完整配置对象
const config = getConfig();
console.log('API URL:', config.VITE_API_URL);

// 获取单个配置值（带默认值）
const apiUrl = getEnvValue('VITE_API_URL', 'http://localhost:3000');
```

### 方式 2：直接访问 window 对象

```javascript
// 查看所有环境配置
console.log(window.__RUNTIME_ENV__);

// 获取当前环境
const env = window.__RUNTIME_ENV__.getCurrentEnv();

// 获取当前环境的配置
const config = window.__RUNTIME_ENV__.getConfig();
console.log(config.VITE_API_URL);

// 手动切换环境（用于调试）
window.__RUNTIME_ENV__.setEnv('test');
```

### 方式 3：配合 @company/runtime-env-core

```javascript
import { initRuntimeEnv, getEnvValue } from '@company/runtime-env-core';

// 初始化
initRuntimeEnv();

// 获取配置
const apiUrl = getEnvValue('VITE_API_URL');
```

## 配置选项

| 选项 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `root` | `string` | `process.cwd()` | 项目根目录 |
| `envs` | `string[]` | `['development', 'test', 'staging', 'production']` | 要读取的环境列表 |
| `envFilePattern` | `string` | `'.env'` | 环境文件命名模式 |
| `envKey` | `string` | `'__RUNTIME_ENV__'` | 注入到 window 的键名 |
| `prefix` | `string` | `'VITE_'` | 环境变量前缀 |
| `includeBase` | `boolean` | `true` | 是否包含基础 .env 文件 |
| `envDetector` | `string` | 默认检测器 | 自定义环境检测函数 |
| `debug` | `boolean` | `false` | 是否输出调试信息 |

## 完整示例

### 项目配置文件

```bash
# .env
VITE_APP_TITLE=My App

# .env.development
VITE_API_URL=http://localhost:3000
VITE_ENV=development

# .env.test
VITE_API_URL=https://api-test.company.com
VITE_ENV=test

# .env.staging
VITE_API_URL=https://api-staging.company.com
VITE_ENV=staging

# .env.production
VITE_API_URL=https://api.company.com
VITE_ENV=production
```

### Vue 3 组件使用

```vue
<template>
  <div>
    <h1>{{ title }}</h1>
    <p>当前环境: {{ currentEnv }}</p>
    <p>API 地址: {{ apiUrl }}</p>
    
    <!-- 调试工具 -->
    <div v-if="isDev">
      <button @click="switchEnv('development')">开发环境</button>
      <button @click="switchEnv('test')">测试环境</button>
      <button @click="switchEnv('staging')">预发环境</button>
      <button @click="switchEnv('production')">生产环境</button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { getCurrentEnv, getEnvValue, setEnv } from '@runtime-env';

const title = ref('');
const currentEnv = ref('');
const apiUrl = ref('');
const isDev = ref(false);

onMounted(() => {
  currentEnv.value = getCurrentEnv();
  apiUrl.value = getEnvValue('VITE_API_URL');
  title.value = getEnvValue('VITE_APP_TITLE');
  isDev.value = currentEnv.value === 'development';
});

function switchEnv(env) {
  setEnv(env);
  location.reload();
}
</script>
```

### API 调用示例

```javascript
// src/api/request.js
import axios from 'axios';
import { getEnvValue } from '@runtime-env';

// 创建 axios 实例
const request = axios.create({
  baseURL: getEnvValue('VITE_API_URL'),
  timeout: 10000
});

export default request;
```

### Vue 插件封装

```javascript
// src/plugins/runtime-env.js
import { initRuntimeEnv, getRuntimeEnv } from '@company/runtime-env-core';

export default {
  install(app) {
    // 初始化
    initRuntimeEnv();
    
    // 注入到全局属性
    const runtimeEnv = getRuntimeEnv();
    app.config.globalProperties.$env = runtimeEnv;
    
    // 提供注入
    app.provide('runtimeEnv', runtimeEnv);
  }
};

// main.js
import { createApp } from 'vue';
import App from './App.vue';
import runtimeEnvPlugin from './plugins/runtime-env';

const app = createApp(App);
app.use(runtimeEnvPlugin);
app.mount('#app');
```

## TypeScript 支持

```typescript
// env.d.ts
/// <reference types="vite/client" />
/// <reference types="@company/vite-plugin-runtime-env/src/index" />

interface ImportMetaEnv {
  readonly VITE_API_URL: string;
  readonly VITE_ENV: string;
  // 其他环境变量...
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}
```

## 工作原理

1. **构建时**：插件读取所有 `.env.*` 文件，生成包含所有环境配置的 JavaScript 代码
2. **注入时**：在 HTML 的 `<head>` 标签中注入配置代码
3. **运行时**：根据环境检测器选择对应环境的配置
4. **访问时**：通过虚拟模块 `@runtime-env` 或全局对象 `window.__RUNTIME_ENV__` 访问

## 注意事项

1. ⚠️ 所有环境的配置都会打包到前端代码中，**不要在 .env 中存放敏感信息**
2. ⚠️ 构建时只需执行一次 `npm run build`，无需指定环境
3. ✅ 部署时不需要任何特殊处理，直接部署到对应环境即可
4. ✅ 确保环境变量以 `VITE_` 开头（或你配置的 prefix）

## 调试技巧

```javascript
// 在浏览器控制台中
// 1. 查看所有配置
console.log(window.__RUNTIME_ENV__);

// 2. 查看当前环境
console.log(window.__RUNTIME_ENV__.getCurrentEnv());

// 3. 临时切换环境
localStorage.setItem('DEBUG_ENV', 'test');
location.reload();

// 4. 清除调试环境
localStorage.removeItem('DEBUG_ENV');
location.reload();
```

## License

MIT