env-manager-js
Version:
A flexible environment management tool for frontend applications with dynamic API switching
318 lines (249 loc) • 8.59 kB
Markdown
# env-manager-js
🌍 一个灵活的前端环境管理工具,支持动态API切换、URL参数控制和本地存储持久化。
[](https://badge.fury.io/js/env-manager-js)
[](https://opensource.org/licenses/MIT)
## ✨ 特性
- 🚀 **动态环境切换** - 通过URL参数实时切换API环境,无需重新打包
- 💾 **持久化存储** - 使用localStorage保存环境选择,避免频繁输入
- 🔗 **URL同步显示** - 在URL中显示当前环境,一目了然
- 🛡️ **安全域名判断** - 基于域名自动判断默认环境,防止误操作生产数据
- 📱 **SSR兼容** - 完美支持服务端渲染环境
- 🎯 **TypeScript支持** - 完整的类型定义,提供最佳开发体验
- ⚡ **零依赖** - 轻量级实现,无外部依赖
- 🔧 **高度可配置** - 支持多项目、多环境灵活配置
## 📦 安装
```bash
npm install env-manager-js
```
```bash
yarn add env-manager-js
```
```bash
pnpm add env-manager-js
```
## 🚀 快速开始
### JavaScript 使用
```javascript
import createEnvManager from 'env-manager-js';
// 创建环境管理器
const envManager = createEnvManager({
envConfig: {
dev: { baseURL: "//localhost:3000" },
prod: { baseURL: "//api.example.com" }
}
});
// 获取当前环境配置
const config = envManager.getConfig();
console.log('当前API地址:', config.baseURL);
```
### TypeScript 使用
```typescript
import createEnvManager, {
EnvManagerConfig,
EnvManager
} from 'env-manager-js';
const config: EnvManagerConfig = {
envConfig: {
dev: { baseURL: "//localhost:3000", timeout: 10000 },
test: { baseURL: "//test-api.example.com", timeout: 8000 },
prod: { baseURL: "//api.example.com", timeout: 5000 }
},
productionDomains: ['www.example.com'],
paramName: 'apiSwitch',
defaultEnv: 'dev'
};
const envManager: EnvManager = createEnvManager(config);
```
## 📖 API 文档
### createEnvManager(config)
创建环境管理器实例。
#### 参数
| 参数 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `envConfig` | `Object` | `{}` | 环境配置映射对象 |
| `productionDomains` | `string[]` | `[]` | 生产域名列表 |
| `paramName` | `string` | `'apiSwitch'` | URL参数名 |
| `storageKey` | `string` | `paramName` | localStorage键名 |
| `defaultEnv` | `string` | `'pre'` | 默认环境 |
| `productionEnv` | `string` | `'prod'` | 生产环境名称 |
| `showUrlParams` | `boolean` | `true` | 是否在非生产域名显示URL参数 |
| `syncDelay` | `number` | `100` | URL同步延时(ms) |
| `enableLog` | `boolean` | `true` | 是否启用控制台日志 |
#### 返回值
返回环境管理器对象,包含以下方法:
| 方法 | 返回值 | 描述 |
|------|--------|------|
| `getCurrentEnv()` | `string` | 获取当前环境名称 |
| `getConfig(key?)` | `any` | 获取当前环境的配置,可指定配置项 |
| `isProduction()` | `boolean` | 判断是否是生产环境 |
| `isProductionDomain()` | `boolean` | 判断是否是生产域名 |
| `switchEnv(env)` | `boolean` | 手动切换环境 |
| `getAvailableEnvs()` | `string[]` | 获取所有可用环境 |
| `syncUrlParams(env)` | `void` | 同步URL参数 |
## 🎯 使用场景
### 1. React 项目集成
```jsx
import React, { useState, useEffect } from 'react';
import createEnvManager from 'env-manager-js';
import axios from 'axios';
const envManager = createEnvManager({
envConfig: {
dev: { baseURL: "//localhost:3000", timeout: 10000 },
test: { baseURL: "//test-api.example.com", timeout: 8000 },
prod: { baseURL: "//api.example.com", timeout: 5000 }
},
productionDomains: ['example.com']
});
// 获取当前环境配置
const config = envManager.getConfig();
console.log('当前API地址:', config.baseURL);
// 创建axios实例
const apiClient = axios.create({
baseURL: envManager.getConfig(),
timeout: 10000
});
// 获取当前环境配置
const config = envManager.getConfig();
console.log('当前API地址:', config.baseURL);
function App() {
const [currentEnv, setCurrentEnv] = useState('');
useEffect(() => {
setCurrentEnv(envManager.getCurrentEnv());
}, []);
const handleSwitchEnv = (env) => {
envManager.switchEnv(env);
setCurrentEnv(env);
// 重新创建axios实例或刷新页面
window.location.reload();
};
return (
<div>
<p>当前环境: {currentEnv}</p>
{envManager.getAvailableEnvs().map(env => (
<button key={env} onClick={() => handleSwitchEnv(env)}>
切换到{env}环境
</button>
))}
</div>
);
}
```
### 2. Vue 项目集成
```javascript
// api/config.js
import createEnvManager from 'env-manager-js';
export const envManager = createEnvManager({
envConfig: {
dev: { baseURL: "//localhost:8080", timeout: 10000 },
test: { baseURL: "//test-api.example.com", timeout: 8000 },
prod: { baseURL: "//api.example.com", timeout: 5000 }
},
productionDomains: ['example.com']
});
export const config = envManager.getConfig();
```
```javascript
// api/request.js
import axios from 'axios';
import { config } from './config.js';
const request = axios.create({
baseURL: config.url,
timeout: 10000
});
export default request;
```
### 3. 多项目配置
```javascript
// 项目A的环境管理
const projectAEnvManager = createEnvManager({
envConfig: {
local: { baseURL: "//localhost:8080", timeout: 10000 },
staging: { baseURL: "//staging-a.company.com", timeout: 8000 },
production: { baseURL: "//api-a.company.com", timeout: 5000 }
},
productionDomains: ['app-a.company.com'],
paramName: 'apiEnv',
storageKey: 'projectA_env',
defaultEnv: 'local'
});
// 获取项目A的配置
const configA = projectAEnvManager.getConfig();
console.log('项目A API地址:', configA.baseURL);
// 项目B的环境管理
const projectBEnvManager = createEnvManager({
envConfig: {
local: { baseURL: "//localhost:9000", timeout: 10000 },
staging: { baseURL: "//staging-b.company.com", timeout: 8000 },
production: { baseURL: "//api-b.company.com", timeout: 5000 }
},
productionDomains: ['app-b.company.com'],
paramName: 'bEnv',
storageKey: 'projectB_env',
defaultEnv: 'local'
});
// 获取项目B的配置
const configB = projectBEnvManager.getConfig();
console.log('项目B API地址:', configB.baseURL);
```
## 🔄 环境切换逻辑
环境切换按以下优先级顺序执行:
1. **域名默认环境** - 根据当前域名判断默认环境
2. **localStorage覆盖** - 本地存储的环境选择覆盖默认环境
3. **URL参数最高优先级** - URL参数中的环境设置覆盖所有其他设置
### 示例
```
当前域名: app.example.com (生产域名)
localStorage: test
URL参数: ?apiSwitch=dev
最终环境: dev (URL参数优先级最高)
```
## 🛡️ 安全特性
- **生产域名保护** - 在生产域名下不会在URL中显示环境参数,保持URL干净
- **环境验证** - 只允许切换到配置中存在的环境
- **SSR兼容** - 在服务端渲染环境中安全降级
## 🔧 高级配置
### 自定义日志
```javascript
const envManager = createEnvManager({
envConfig: {
dev: { baseURL: "//localhost:3000" },
prod: { baseURL: "//api.example.com" }
},
enableLog: false, // 关闭默认日志
});
// 自定义日志处理
const originalGetConfig = envManager.getConfig;
envManager.getConfig = function(key) {
const config = originalGetConfig.call(this, key);
console.log(`🔧 自定义日志: 获取配置`, key ? `${key}: ${config}` : config);
return config;
};
```
### 环境切换回调
```javascript
const envManager = createEnvManager({
envConfig: {
dev: { baseURL: "//localhost:3000" },
prod: { baseURL: "//api.example.com" }
}
});
// 监听环境切换
const originalSwitchEnv = envManager.switchEnv;
envManager.switchEnv = function(env) {
const success = originalSwitchEnv.call(this, env);
if (success) {
console.log(`环境已切换到: ${env}`);
// 执行自定义逻辑,如重新加载数据
window.dispatchEvent(new CustomEvent('envChanged', { detail: env }));
}
return success;
};
```
## 🤝 贡献
欢迎提交 Issue 和 Pull Request!
## 📄 许可证
[MIT](LICENSE) © woyangv
## 🔗 相关链接
- [GitHub Repository](https://github.com/woyangv/env-manager-js)
- [npm Package](https://www.npmjs.com/package/env-manager-js)
- [Issues](https://github.com/woyangv/env-manager-js/issues)