Multi-environment variable configuration management
The Necessity of Multi-Environment Variable Configuration Management
Modern frontend projects typically need to run in different environments, such as development, testing, staging, and production. Each environment may require different API endpoints, feature flags, log levels, and other configurations. Hardcoding these variables makes the code difficult to maintain and increases the likelihood of deployment errors. Through environment variable configuration management, flexible adaptation of a single codebase across different environments can be achieved.
Basic Webpack Environment Variable Configuration
Webpack provides the DefinePlugin
to define global constants, which is the foundational method for environment variable management. In webpack.config.js
:
const webpack = require('webpack');
module.exports = {
// ...other configurations
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development'),
'API_URL': JSON.stringify('https://dev.api.example.com')
})
]
}
These variables can be accessed directly in the code:
console.log(process.env.NODE_ENV); // Outputs 'development'
fetch(`${API_URL}/users`).then(...)
Multi-Environment Configuration File Solution
A more professional approach is to create separate configuration files for each environment. A typical directory structure looks like this:
config/
├── dev.env.js
├── test.env.js
├── stage.env.js
├── prod.env.js
└── index.js
Example content of dev.env.js
:
module.exports = {
NODE_ENV: '"development"',
API_URL: '"https://dev.api.example.com"',
DEBUG_MODE: true,
AUTH_ENABLED: false
}
config/index.js
serves as the unified entry point:
const env = process.env.NODE_ENV || 'development'
module.exports = require(`./${env}.env.js`)
Managing Sensitive Variables with dotenv
For variables containing sensitive information, use the dotenv-webpack
plugin:
npm install dotenv-webpack --save-dev
Create a .env
file in the project root:
API_KEY=your_api_key_here
DB_PASSWORD=secure_password
Webpack configuration:
const Dotenv = require('dotenv-webpack');
module.exports = {
plugins: [
new Dotenv({
path: './.env', // Default path
safe: true // Loads .env.example to check for required variables
})
]
}
Environment Variable Injection Strategy
Dynamically inject variables based on the build environment:
// webpack.config.js
const envConfig = require('./config')
module.exports = (env) => {
return {
// ...other configurations
plugins: [
new webpack.DefinePlugin({
'process.env': envConfig[env.NODE_ENV]
})
]
}
}
Example build commands:
{
"scripts": {
"build:dev": "webpack --env.NODE_ENV=development",
"build:prod": "webpack --env.NODE_ENV=production"
}
}
Type-Safe Environment Variables
In TypeScript projects, define environment variable types:
// src/types/env.d.ts
declare namespace NodeJS {
interface ProcessEnv {
readonly NODE_ENV: 'development' | 'production' | 'test';
readonly API_URL: string;
readonly GA_TRACKING_ID?: string;
}
}
Usage example:
const apiUrl: string = process.env.API_URL;
if (process.env.NODE_ENV === 'development') {
console.log('Development mode');
}
Environment-Specific Code Optimization
Conditional compilation using environment variables:
if (process.env.NODE_ENV === 'production') {
// Production-specific code
enableAnalytics();
disableDebugLogs();
} else {
// Development-specific code
mockAPIResponses();
}
Webpack's TerserPlugin
can remove dead code based on environment variables:
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
dead_code: true,
global_defs: {
'process.env.NODE_ENV': 'production'
}
}
}
})
]
}
Cross-Platform Environment Variable Handling
Handling differences in environment variables across operating systems:
// Unified boolean parsing
function parseBool(value) {
if (typeof value === 'boolean') return value;
if (typeof value === 'string') {
return value.toLowerCase() === 'true';
}
return false;
}
// Usage example
const shouldLog = parseBool(process.env.ENABLE_LOGGING);
Runtime Environment Variable Injection
For scenarios requiring post-deployment variable modification, use a config.js
in the public directory:
// public/config.js
window.__env__ = {
API_URL: 'https://runtime.api.example.com',
FEATURE_FLAGS: {
newDashboard: true
}
};
Include in HTML:
<script src="%PUBLIC_URL%/config.js"></script>
Access in code:
const apiUrl = window.__env__.API_URL || process.env.API_URL;
Environment Variable Validation
Add validation to ensure required variables exist:
// config/validator.js
function validateEnv(env) {
const requiredVars = ['API_URL', 'AUTH_DOMAIN'];
const missingVars = requiredVars.filter(varName => !env[varName]);
if (missingVars.length > 0) {
throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`);
}
}
module.exports = validateEnv;
Use in Webpack configuration:
const validateEnv = require('./config/validator');
const envConfig = require('./config');
validateEnv(envConfig[env.NODE_ENV]);
Environment Variable Encryption
Encrypt sensitive variables:
// config/encrypt.js
const crypto = require('crypto');
function encrypt(text, key) {
const cipher = crypto.createCipher('aes-256-cbc', key);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
function decrypt(encrypted, key) {
const decipher = crypto.createDecipher('aes-256-cbc', key);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
module.exports = { encrypt, decrypt };
Usage example:
const { encrypt, decrypt } = require('./config/encrypt');
const encrypted = encrypt(process.env.DB_PASSWORD, 'secret-key');
const decrypted = decrypt(encrypted, 'secret-key');
Environment Variables and Feature Flags
Implement feature flags:
// src/features.js
export const features = {
newCheckout: process.env.FEATURE_NEW_CHECKOUT === 'true',
darkMode: process.env.FEATURE_DARK_MODE === 'true',
experimentalAPI: process.env.FEATURE_EXPERIMENTAL_API === 'true'
};
// Usage example
if (features.newCheckout) {
renderNewCheckout();
} else {
renderLegacyCheckout();
}
Environment Variable Naming Conventions
Recommended naming conventions:
// Basic configurations
APP_NAME
API_BASE_URL
// Feature flags
FEATURE_[FEATURE_NAME]_ENABLED
// Third-party services
AWS_S3_BUCKET
GOOGLE_ANALYTICS_ID
// Security-related
AUTH0_CLIENT_ID
ENCRYPTION_KEY
Environment Variable Documentation
Generate documentation using JSDoc:
/**
* @env {string} API_BASE_URL - Base API URL
* @env {boolean} FEATURE_NEW_UI - Whether to enable the new UI
* @env {number} MAX_API_RETRIES - Maximum API retry attempts
* @env {string} SENTRY_DSN - Sentry error tracking DSN
*/
Environment Variables and Test Configuration
Special handling for test environments:
// jest.config.js
module.exports = {
globals: {
'process.env': {
NODE_ENV: 'test',
API_URL: 'http://localhost:3000/mock-api',
TEST_USER: 'jest@example.com'
}
}
};
Environment Variable Debugging Tips
Debugging environment variable loading:
// Print all environment variables
console.log('Loaded environment variables:', {
...process.env,
// Filter sensitive information
API_KEY: process.env.API_KEY ? '***' : undefined
});
// Check variable sources
console.log('NODE_ENV from:', process.env.NODE_ENV);
Environment Variables and Docker Integration
Dockerfile example:
FROM node:16
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
COPY . .
RUN npm install && npm run build
CMD ["node", "server.js"]
Build command:
docker build --build-arg NODE_ENV=development -t my-app:dev .
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:开发环境与生产环境配置分离
下一篇:社区生态与插件体系