📌 核心概念
Dotenv - 零依赖模块,将环境变量从 .env 文件加载到 process.env,遵循 The Twelve-Factor App 原则。
📦 安装与版本要求
# 安装最新版本(推荐16.0.0+)
npm install dotenv
# 指定版本
npm install dotenv@16
# yarn
yarn add dotenv
# pnpm
pnpm add dotenv
# 版本建议
# - 新项目:dotenv 16.0.0+(支持override选项)
# - 现有项目:至少使用dotenv 10.0.0+
🚀 基础使用
1. 快速开始
// 方式1:CommonJS - 在入口文件最早处加载
require('dotenv').config();
console.log(process.env.DB_HOST);
// 方式2:ES Module - 推荐控制式加载
import dotenv from 'dotenv';
import path from 'path';
// 根据环境条件加载
if (process.env.NODE_ENV !== 'production') {
dotenv.config({
path: path.resolve(process.cwd(), '.env.development')
});
}
// 方式3:即时执行(不推荐用于生产)
import 'dotenv/config'; // 这会立即执行配置
2. 环境文件示例
# .env 文件示例
DB_HOST=localhost
DB_PORT=5432
DB_USER=admin
DB_PASS="super_secret_password!@#" # 特殊字符用引号包裹
APP_ENV=development
APP_DEBUG=true
API_KEY=your_api_key_here
# 注释以 # 开头
# 支持空行分隔
# 数组格式(自定义解析)
ALLOWED_ORIGINS= https://localhost:3000 ,https://example.com
# JSON配置(自定义解析)
FEATURE_FLAGS={"newDashboard":true,"darkMode":false}
⚙️ 配置选项详解
config() 方法参数
const result = require('dotenv').config({
path: '/custom/path/.env', // 自定义文件路径
encoding: 'utf8', // 编码格式(默认utf8)
debug: process.env.NODE_ENV !== 'production', // 调试模式
override: false // 是否覆盖已存在的环境变量
});
// 返回值结构
console.log(result);
// {
// parsed: { DB_HOST: 'localhost', ... }, // 解析的变量
// error: Error | null // 错误信息
// }
override 选项重要说明
// ⚠️ 重要行为理解:
// override: false(默认)- 不覆盖已存在的环境变量
// override: true - 强制覆盖
// 示例场景:
// 系统环境变量:PORT=3000(通过shell设置)
// .env 文件:PORT=8080
dotenv.config({ override: false });
console.log(process.env.PORT); // 3000(使用系统变量)
dotenv.config({ override: true });
console.log(process.env.PORT); // 8080(使用.env文件变量)
// 生产环境建议:override: false
// 开发环境建议:override: true
📁 多环境配置策略
推荐的文件结构
├── .env # 本地开发环境(不提交到git)
├── .env.example # 环境变量模板(提交到git)
├── .env.development # 开发环境配置
├── .env.staging # 预发布环境配置
├── .env.production # 生产环境配置
├── .env.test # 测试环境配置
└── config/
└── env.js # 环境配置加载逻辑
自动化智能加载
// config/env-loader.js
const path = require('path');
const dotenv = require('dotenv');
const fs = require('fs');
/**
* 智能加载环境变量
* 优先级:.env.local > .env.[NODE_ENV] > .env
*/
function loadEnv() {
const env = process.env.NODE_ENV || 'development';
const envFiles = [
`.env.${env}.local`,
`.env.${env}`,
'.env.local',
'.env'
];
let loadedVars = {};
envFiles.forEach(file => {
const envPath = path.resolve(process.cwd(), file);
if (fs.existsSync(envPath)) {
const result = dotenv.config({
path: envPath,
override: env === 'test' // 测试环境强制覆盖
});
if (result.error) {
console.warn(`加载 ${file} 失败:`, result.error.message);
} else if (result.parsed) {
loadedVars = { ...loadedVars, ...result.parsed };
}
}
});
console.log(`环境 ${env} 加载完成,加载了 ${Object.keys(loadedVars).length} 个变量`);
return loadedVars;
}
// 单例模式,避免重复加载
let isEnvLoaded = false;
module.exports = function initEnv() {
if (!isEnvLoaded) {
loadEnv();
isEnvLoaded = true;
}
return process.env;
};
🔧 高级用法
1. 类型安全的配置对象
// config/env.js
class EnvConfig {
constructor() {
this.loadEnv();
}
loadEnv() {
// 确保环境变量已加载
if (!process.env.NODE_ENV) {
require('dotenv').config({ path: '.env' });
}
}
// 应用配置
get app() {
return {
env: process.env.NODE_ENV || 'development',
port: this.parseInt('PORT', 3000),
name: process.env.APP_NAME || 'My App',
debug: this.parseBool('DEBUG', false),
url: process.env.APP_URL,
};
}
// 数据库配置
get database() {
return {
host: process.env.DB_HOST,
port: this.parseInt('DB_PORT', 5432),
name: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
url: process.env.DATABASE_URL,
pool: {
max: this.parseInt('DB_POOL_MAX', 10),
min: this.parseInt('DB_POOL_MIN', 2),
}
};
}
// 解析辅助方法
parseInt(key, defaultValue = 0) {
const value = process.env[key];
if (!value) return defaultValue;
const parsed = parseInt(value, 10);
return isNaN(parsed) ? defaultValue : parsed;
}
parseBool(key, defaultValue = false) {
const value = process.env[key];
if (value === undefined || value === null) return defaultValue;
return value === 'true' || value === '1' || value === 'yes';
}
parseArray(key, delimiter = ',', defaultValue = []) {
const value = process.env[key];
if (!value) return defaultValue;
return value.split(delimiter).map(item => item.trim());
}
parseJson(key, defaultValue = {}) {
const value = process.env[key];
if (!value) return defaultValue;
try {
return JSON.parse(value);
} catch (error) {
console.warn(`解析JSON环境变量 ${key} 失败:`, error);
return defaultValue;
}
}
}
// 创建单例并冻结
const config = new EnvConfig();
Object.freeze(config);
export default config;
2. 环境变量验证系统
// utils/env-validator.js
class EnvValidator {
static required(vars, customMessage = null) {
const missing = vars.filter(v => !process.env[v]);
if (missing.length > 0) {
const message = customMessage ||
`缺少必需的环境变量: ${missing.join(', ')}\n请检查您的 .env 文件。`;
throw new Error(message);
}
}
static validateRules(rules) {
const errors = [];
rules.forEach(({ key, required = false, type, pattern, min, max, customValidator }) => {
const value = process.env[key];
// 检查必需性
if (required && (value === undefined || value === '')) {
errors.push(`环境变量 ${key} 是必需的`);
return;
}
// 类型检查
if (value && type) {
switch (type) {
case 'number':
if (isNaN(Number(value))) errors.push(`${key} 必须是数字`);
break;
case 'boolean':
const lowerValue = value.toLowerCase();
if (!['true', 'false', '1', '0', 'yes', 'no'].includes(lowerValue)) {
errors.push(`${key} 必须是布尔值 (true/false)`);
}
break;
case 'url':
try {
new URL(value);
} catch {
errors.push(`${key} 必须是有效的URL`);
}
break;
}
}
// 正则匹配
if (value && pattern && !pattern.test(value)) {
errors.push(`${key} 格式不正确`);
}
// 范围检查
if (value && type === 'number') {
const num = Number(value);
if (min !== undefined && num < min) errors.push(`${key} 不能小于 ${min}`);
if (max !== undefined && num > max) errors.push(`${key} 不能大于 ${max}`);
}
// 自定义验证器
if (value && customValidator) {
const result = customValidator(value, key);
if (result !== true) errors.push(result);
}
});
if (errors.length > 0) {
throw new Error(`环境变量验证失败:\n${errors.join('\n')}`);
}
}
}
// 使用示例
EnvValidator.required(['DB_HOST', 'API_KEY', 'SECRET_KEY']);
EnvValidator.validateRules([
{ key: 'PORT', type: 'number', min: 1, max: 65535 },
{ key: 'DB_PORT', type: 'number', required: true },
{ key: 'API_URL', type: 'url', required: true },
{ key: 'ADMIN_EMAIL', pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ },
{
key: 'PASSWORD_MIN_LENGTH',
type: 'number',
customValidator: (value) => {
const len = parseInt(value, 10);
return len >= 8 ? true : '密码最小长度不能小于8';
}
}
]);
3. 动态环境变量扩展
// utils/env-expander.js
class EnvExpander {
/**
* 扩展环境变量中的引用
* 支持 ${VAR} 和 ${VAR:-default} 语法
*/
static expand(str, maxDepth = 5) {
let result = str;
let depth = 0;
while (result.includes('${') && depth < maxDepth) {
result = result.replace(/\${([^{}]+)}/g, (match, expression) => {
// 处理默认值语法:${VAR:-default}
if (expression.includes(':-')) {
const [varName, defaultValue] = expression.split(':-');
return process.env[varName] || defaultValue || '';
}
// 简单变量引用
return process.env[expression] || '';
});
depth++;
}
// 检查是否达到最大深度(防止无限循环)
if (depth >= maxDepth && result.includes('${')) {
console.warn('环境变量扩展达到最大深度,可能存在循环引用');
}
return result;
}
/**
* 批量扩展所有环境变量
*/
static expandAll(vars = process.env) {
const expanded = {};
Object.entries(vars).forEach(([key, value]) => {
if (typeof value === 'string') {
expanded[key] = this.expand(value);
} else {
expanded[key] = value;
}
});
return expanded;
}
}
// 使用示例
// .env 文件中:
// API_URL=https://${DOMAIN}/api/v1
// DB_URL=postgres://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}
const expanded = EnvExpander.expandAll();
console.log(expanded.API_URL); // 已扩展的URL
🛡️ 安全最佳实践
1. 版本控制策略
# .gitignore - 必须排除的文件
.env
.env.local
*.env.*.local
.env.production
.env.staging
secrets/
*.pem
*.key
# 必须提交的文件
.env.example # 模板文件
.env.test # 测试配置(不含真实密码)
2. 敏感信息保护
// utils/secrets-manager.js
const crypto = require('crypto');
class SecretsManager {
/**
* 加密敏感环境变量(开发环境使用)
*/
static encryptEnvFile(envPath, key) {
const fs = require('fs');
const envContent = fs.readFileSync(envPath, 'utf8');
// 提取敏感变量
const lines = envContent.split('\n');
const sensitiveVars = [];
lines.forEach(line => {
if (line.match(/PASSWORD|SECRET|KEY|TOKEN|PRIVATE/i) && !line.startsWith('#')) {
sensitiveVars.push(line);
}
});
if (sensitiveVars.length > 0) {
console.warn('发现敏感变量,建议使用加密存储:', sensitiveVars);
}
// 实际项目中,这里应该实现加密逻辑
// const encrypted = this.encrypt(envContent, key);
// fs.writeFileSync(`${envPath}.encrypted`, encrypted);
}
/**
* 运行时解密(生产环境使用)
*/
static async loadEncryptedEnv(encryptedPath, key) {
// 从加密文件加载
// const encrypted = fs.readFileSync(encryptedPath);
// const decrypted = this.decrypt(encrypted, key);
// 解析并设置到 process.env
// 或者:从云服务加载
return await this.loadFromCloud();
}
/**
* 从AWS Secrets Manager或Azure Key Vault加载
*/
static async loadFromCloud() {
// AWS Secrets Manager 示例
const { SecretsManagerClient, GetSecretValueCommand } = require('@aws-sdk/client-secrets-manager');
const client = new SecretsManagerClient({
region: process.env.AWS_REGION,
});
try {
const response = await client.send(
new GetSecretValueCommand({
SecretId: process.env.AWS_SECRET_ID,
})
);
return JSON.parse(response.SecretString);
} catch (error) {
console.error('从Secrets Manager加载失败:', error);
throw error;
}
}
/**
* 安全日志记录(屏蔽敏感信息)
*/
static safeLogEnv() {
const env = { ...process.env };
const sensitivePatterns = [
/PASSWORD/i,
/SECRET/i,
/KEY/i,
/TOKEN/i,
/PRIVATE/i,
/CREDENTIAL/i,
/AUTH/i
];
Object.keys(env).forEach(key => {
if (sensitivePatterns.some(pattern => pattern.test(key))) {
env[key] = '***REDACTED***';
}
});
console.log('环境变量(敏感信息已屏蔽):', env);
}
}
3. 生产环境配置策略
# Docker Compose 示例
version: '3.8'
services:
app:
build: .
env_file:
- .env.production # 非敏感配置
environment:
- NODE_ENV=production
- LOG_LEVEL=info
secrets:
- db_password
- api_keys
# 配置优先级:environment > env_file
secrets:
db_password:
external: true # 从Docker Secrets加载
api_keys:
file: ./secrets/api_keys.txt
# Kubernetes Secret 示例
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
db-password: c3VwZXJfc2VjcmV0X3Bhc3N3b3JkCg== # base64编码
api-key: bXlfYXBpX2tleQo=
📊 环境变量类型转换参考
| 类型 |
获取方法 |
示例 |
注意事项 |
| 字符串 |
process.env.VAR |
"production" |
默认类型 |
| 数字 |
parseInt(process.env.PORT, 10) |
3000 |
指定基数 |
| 布尔值 |
process.env.DEBUG === 'true' |
true/false |
严格比较 |
| 数组 |
process.env.ALLOWED_ORIGINS.split(',') |
['a.com','b.com'] |
处理空格 |
| JSON |
JSON.parse(process.env.CONFIG) |
{key: 'value'} |
错误处理 |
| URL |
new URL(process.env.API_URL) |
URL对象 |
验证有效性 |
🔄 框架特定集成
Next.js
// Next.js 自动加载顺序:
// 1. .env.${NODE_ENV}.local
// 2. .env.local
// 3. .env.${NODE_ENV}
// 4. .env
// 客户端可访问的变量(浏览器端)
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_GA_ID=UA-XXXXX-Y
// 仅服务器端访问
DATABASE_URL=postgres://...
SECRET_KEY=your_secret_key
// 访问方式
console.log(process.env.NEXT_PUBLIC_API_URL); // 客户端和服务器
console.log(process.env.DATABASE_URL); // 仅服务器
Vite
// Vite 环境变量必须以 VITE_ 开头才能在客户端访问
VITE_API_KEY=xxx
VITE_API_URL=https://api.example.com
// 服务器端变量(无前缀)
DATABASE_URL=postgres://...
// 访问方式
console.log(import.meta.env.VITE_API_KEY); // 客户端
console.log(process.env.DATABASE_URL); // 服务器端
// vite.config.js 中加载
import { loadEnv } from 'vite';
export default ({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
return {
// 配置...
};
};
Create React App
// 必须使用 REACT_APP_ 前缀
REACT_APP_API_ENDPOINT=https://api.example.com
REACT_APP_DEBUG=true
// 访问方式
console.log(process.env.REACT_APP_API_ENDPOINT);
// 构建时替换
// .env.development 和 .env.production 自动识别
🐛 常见问题与解决方案
问题1:环境变量未加载
// 调试脚本
const dotenv = require('dotenv');
const path = require('path');
console.log('当前目录:', process.cwd());
console.log('NODE_ENV:', process.env.NODE_ENV);
const envPath = path.resolve(process.cwd(), '.env');
console.log('尝试加载:', envPath);
const result = dotenv.config({
path: envPath,
debug: true
});
if (result.error) {
console.error('加载失败:', result.error);
} else {
console.log('加载成功,变量:', Object.keys(result.parsed || {}));
}
问题2:Windows 兼容性问题
// Windows特殊字符处理
// .env 文件
PASSWORD="abc123!@#" # 特殊字符用引号
MULTILINE="line1\nline2" # Windows换行符问题
// 解决方案:使用cross-env设置变量
// package.json
{
"scripts": {
"dev:win": "set NODE_ENV=development&& node app.js",
"dev:unix": "NODE_ENV=development node app.js",
"dev": "cross-env NODE_ENV=development node app.js"
}
}
// 或者在代码中规范化
function normalizePath(path) {
return process.platform === 'win32'
? path.replace(/\\/g, '/')
: path;
}
问题3:测试环境污染
// jest.setup.js 或测试配置
const dotenv = require('dotenv');
// 每个测试前重置环境
beforeEach(() => {
jest.resetModules();
// 保存原始环境变量
global.originalEnv = { ...process.env };
// 加载测试环境
dotenv.config({
path: '.env.test',
override: true
});
});
afterEach(() => {
// 恢复原始环境
if (global.originalEnv) {
Object.keys(process.env).forEach(key => {
if (!(key in global.originalEnv)) {
delete process.env[key];
}
});
Object.assign(process.env, global.originalEnv);
}
});
// 或者在package.json中指定测试环境
// "test": "cross-env NODE_ENV=test jest"
问题4:环境变量大小限制
// ⚠️ 系统限制:单个变量通常最大128KB,总环境空间最大2MB
// 错误示例(可能超过限制)
LARGE_CONFIG={"huge": "json object..."}
// 解决方案
// 1. 拆分成多个变量
CONFIG_PART1={...}
CONFIG_PART2={...}
// 2. 存为文件,环境变量存储文件路径
CONFIG_FILE=/path/to/config.json
// 3. 使用外部配置服务
async function loadLargeConfig() {
const response = await fetch(process.env.CONFIG_SERVICE_URL);
return response.json();
}
🎯 推荐工作流
开发环境
# 1. 克隆项目
git clone project && cd project
# 2. 安装依赖
npm install
# 3. 复制环境模板
cp .env.example .env
cp .env.example .env.development
# 4. 编辑配置(使用安全编辑器)
code .env.development
# 5. 启动开发服务器
npm run dev
# 6. 验证环境变量
npm run env:check
CI/CD 管道
# GitHub Actions 示例
name: Deploy
on: [push]
env:
NODE_ENV: production
NODE_VERSION: 18
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install dependencies
run: npm ci
- name: Load environment variables
run: |
echo "DB_URL=${{ secrets.DB_URL }}" >> .env
echo "API_KEY=${{ secrets.API_KEY }}" >> .env
- name: Run tests
run: npm test
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- name: Deploy to production
run: |
# 从AWS Secrets Manager加载生产环境变量
aws secretsmanager get-secret-value \
--secret-id production/env \
--query SecretString \
--output text > .env.production
# 部署命令
npm run deploy:prod
生产环境部署
# 方案1:Docker + 环境变量
docker run -d \
--name myapp \
-e NODE_ENV=production \
-e DB_URL="$DB_URL" \
-e API_KEY="$API_KEY" \
-p 3000:3000 \
myapp:latest
# 方案2:Kubernetes ConfigMap + Secret
kubectl create secret generic app-secrets \
--from-literal=db-password='xxx' \
--from-literal=api-key='xxx'
kubectl create configmap app-config \
--from-literal=log-level=info \
--from-literal=app-name=MyApp
# 方案3:云服务商特定方案
# AWS: Parameter Store + Secrets Manager
# Azure: App Configuration + Key Vault
# GCP: Secret Manager
🔗 相关工具生态系统
| 工具 |
用途 |
安装 |
| dotenv-cli |
命令行加载环境变量 |
npm install -g dotenv-cli |
| dotenv-expand |
支持变量扩展 |
npm install dotenv-expand |
| dotenv-safe |
验证必需变量 |
npm install dotenv-safe |
| envalid |
类型安全的环境验证 |
npm install envalid |
| convict |
配置管理框架 |
npm install convict |
| config |
多环境配置管理 |
npm install config |
| cross-env |
跨平台环境变量设置 |
npm install cross-env |
| env-cmd |
执行命令前加载env文件 |
npm install env-cmd |
| dotenv-flow |
多环境管理增强 |
npm install dotenv-flow |
| @dotenvx/dotenvx |
官方扩展工具集 |
npm install @dotenvx/dotenvx |
📝 TypeScript 完整支持
// env.d.ts - 环境变量类型声明
declare namespace NodeJS {
interface ProcessEnv {
// 基础配置
NODE_ENV: 'development' | 'production' | 'test';
PORT: string;
HOST: string;
// 数据库
DB_HOST: string;
DB_PORT: string;
DB_USER: string;
DB_PASSWORD: string;
DB_NAME: string;
DATABASE_URL: string;
// 应用配置
APP_NAME: string;
APP_VERSION: string;
LOG_LEVEL: 'debug' | 'info' | 'warn' | 'error';
// 第三方服务
API_KEY?: string;
API_SECRET?: string;
// 功能开关
FEATURE_NEW_UI?: string;
FEATURE_EXPERIMENTAL?: string;
// 框架特定
NEXT_PUBLIC_API_URL?: string; // Next.js
VITE_API_URL?: string; // Vite
REACT_APP_API_URL?: string; // CRA
}
}
// 使用示例 - 获得完整类型提示
const config = {
port: parseInt(process.env.PORT, 10), // PORT类型为string
env: process.env.NODE_ENV, // 枚举类型
debug: process.env.LOG_LEVEL === 'debug'
};
// 类型安全的配置工厂
class TypedConfig {
static getRequired<T extends keyof NodeJS.ProcessEnv>(key: T): string {
const value = process.env[key];
if (!value) {
throw new Error(`环境变量 ${key} 未定义`);
}
return value;
}
static getOptional<T extends keyof NodeJS.ProcessEnv>(key: T, defaultValue?: string): string | undefined {
return process.env[key] || defaultValue;
}
}
const dbHost = TypedConfig.getRequired('DB_HOST');
const apiKey = TypedConfig.getOptional('API_KEY');
🚨 关键安全警告
必须避免的陷阱
- ❌ 永远不要提交
.env 文件到版本控制
- ❌ 不要在客户端代码中暴露敏感环境变量
- ❌ 避免在日志中记录完整的环境变量
- ❌ 不要硬编码回退值作为真实凭证
- ❌ 避免使用过于简单的密码或密钥
安全检查清单
📈 性能优化建议
// 1. 避免重复加载
let envCache = null;
function getEnv() {
if (!envCache) {
const start = Date.now();
envCache = dotenv.config();
console.log(`加载环境变量耗时: ${Date.now() - start}ms`);
}
return envCache;
}
// 2. 按需加载
function lazyLoadEnv(section) {
const sections = {
db: ['DB_HOST', 'DB_PORT', 'DB_USER', 'DB_PASSWORD'],
api: ['API_URL', 'API_KEY'],
app: ['NODE_ENV', 'PORT', 'LOG_LEVEL']
};
const requiredVars = sections[section] || [];
requiredVars.forEach(key => {
if (!process.env[key]) {
// 加载包含此变量的最小env文件
}
});
}
// 3. 预解析常用变量
const preParsedConfig = {
port: parseInt(process.env.PORT || '3000', 10),
isProduction: process.env.NODE_ENV === 'production',
isDebug: process.env.LOG_LEVEL === 'debug'
};
🔄 迁移策略
从硬编码值迁移
// 迁移前
const config = {
db: {
host: 'localhost',
port: 5432,
user: 'admin',
password: 'hardcoded_password' // ❌
}
};
// 迁移步骤
// 1. 创建.env.example文件
// 2. 逐步替换硬编码值为process.env引用
// 3. 添加环境变量验证
// 4. 更新部署文档
// 5. 培训团队成员
// 迁移后
const config = {
db: {
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT, 10),
user: process.env.DB_USER,
password: process.env.DB_PASSWORD // ✅
}
};
从其他配置库迁移
// 如果之前使用config库
const oldConfig = require('config');
// 逐步迁移策略
// 1. 创建.env文件对应原有配置
// 2. 创建适配层
class ConfigAdapter {
static get(key) {
// 优先使用环境变量,回退到旧配置
return process.env[key.toUpperCase()] || oldConfig.get(key);
}
}
// 3. 逐步替换代码中的引用
// 4. 最终移除旧配置库依赖
🎓 总结:架构师视角的最佳实践
核心原则
- 安全性优先:敏感信息永远不进入代码仓库
- 环境隔离:开发、测试、生产环境完全独立
- 可追溯性:环境变更应有记录和审计
- 简单性:配置系统不应成为应用的复杂性来源
- 可观测性:能够监控和告警配置问题
12-Factor App 合规性
- ✅ III. 配置:在环境中存储配置
- ✅ IV. 后端服务:通过配置连接
- ✅ V. 构建、发布、运行:严格分离
- ✅ VI. 进程:无状态,共享 nothing
现代架构建议
// 对于大型分布式系统
const Architecture = {
// 第一层:本地.env文件(开发用)
LocalEnv: '.env*',
// 第二层:配置服务(生产用)
ConfigService: {
AWS: 'Parameter Store + Secrets Manager',
Azure: 'App Configuration + Key Vault',
HashiCorp: 'Consul + Vault',
SelfHosted: 'etcd + confd'
},
// 第三层:功能标志服务
FeatureFlags: {
LaunchDarkly: '商业方案',
Unleash: '开源方案',
Flagsmith: '自托管方案'
},
// 监控层
Monitoring: {
Validation: '启动时验证所有配置',
ChangeDetection: '配置变更监控',
Rollback: '配置回滚机制'
}
};
未来趋势
- GitOps 配置管理:环境变量作为代码管理
- 动态配置:运行时无需重启更新配置
- 配置即服务:集中式配置管理中心
- AI辅助优化:智能配置推荐和验证
📋 快速参考卡片
紧急情况处理
# 1. 环境变量泄露
# 立即:轮换所有泄露的密钥
# 然后:审计访问日志,更新.env文件
# 2. 配置错误导致服务宕机
# 使用:配置版本管理,快速回滚
# 3. 缺少环境变量
# 检查:启动时验证脚本是否运行
# 修复:更新部署脚本或CI/CD配置
新项目快速开始
# 初始化环境配置
mkdir config
touch .env.example
touch .env.development
touch .env.test
# 安装核心依赖
npm install dotenv
npm install -D @types/node # TypeScript项目
# 创建配置加载器
# 参考本文的 config/env-loader.js