Механизм переменных окружения в Webpack используется для управления поведением сборки без изменения исходного кода конфигурации. Основная идея заключается в разделении конфигурации на среду выполнения и параметры, передаваемые извне: разработка, тестирование, продакшен-сборка, staging-окружения.
В основе работы лежат три ключевых уровня:
process.env)webpack.config.jsWebpack выполняется в Node.js, поэтому доступ к окружению
осуществляется через process.env.
console.log(process.env.NODE_ENV);
console.log(process.env.API_URL);
Однако прямое использование process.env в клиентском
коде невозможно без дополнительной обработки, поскольку браузер не имеет
доступа к переменным окружения Node.js.
Наиболее распространённая переменная — NODE_ENV.
Типовые значения:
development — режим разработкиproduction — продакшен-сборкаtest — тестовое окружениеWebpack использует mode, который по сути
синхронизируется с NODE_ENV:
module.exports = {
mode: 'production'
};
или через переменную окружения:
NODE_ENV=production webpack
Webpack поддерживает передачу параметров через аргумент
--env.
Пример вызова:
webpack --env mode=production --env apiUrl=https://api.example.com
Конфигурация:
module.exports = (env) => {
return {
mode: env.mode,
output: {
filename: 'bundle.js'
}
};
};
Структура env формируется автоматически:
env = {
mode: 'production',
apiUrl: 'https://api.example.com'
}
Webpack поддерживает экспорт функции вместо статического объекта. Это основной способ работы с переменными окружения.
module.exports = (env, argv) => {
const isProd = argv.mode === 'production';
return {
mode: isProd ? 'production' : 'development',
devtool: isProd ? false : 'source-map'
};
};
Параметры:
env — пользовательские переменные через
--envargv — аргументы CLI Webpack (mode,
watch, и др.)Переменные окружения Node.js не доступны в браузере. Для их передачи
используется DefinePlugin.
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.API_URL': JSON.stringify(process.env.API_URL)
})
]
};
После сборки:
console.log(process.env.API_URL);
превратится в:
console.log("https://api.example.com");
DefinePlugin выполняет подстановку на этапе сборки:
process.env без DefinePlugin:
Для управления локальными переменными часто используется пакет
dotenv.
Установка:
npm install dotenv
Файл .env:
API_URL=https://api.local
DEBUG=true
Подключение в webpack:
require('dotenv').config();
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.API_URL': JSON.stringify(process.env.API_URL),
'process.env.DEBUG': JSON.stringify(process.env.DEBUG)
})
]
};
Часто используется разбиение конфигурации:
webpack.common.js
webpack.dev.js
webpack.prod.js
Базовая конфигурация:
module.exports = {
entry: './src/index.js'
};
Development:
module.exports = {
mode: 'development',
devtool: 'source-map'
};
Production:
module.exports = {
mode: 'production',
optimization: {
minimize: true
}
};
Слияние через webpack-merge:
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'production'
});
CLI:
webpack --env apiUrl=https://api.example.com --env debug=true
Конфигурация:
module.exports = (env) => {
return {
plugins: [
new webpack.DefinePlugin({
'process.env.API_URL': JSON.stringify(env.apiUrl),
'process.env.DEBUG': JSON.stringify(env.debug)
})
]
};
};
Переменные из CLI и .env всегда строковые.
Пример:
--env debug=false
В конфигурации:
const isDebug = env.debug === 'true';
Без явного преобразования значения остаются строками, что приводит к ошибкам логики.
Расширенный вариант конфигурации:
module.exports = (env = {}, argv = {}) => {
const isProd = argv.mode === 'production';
return {
mode: isProd ? 'production' : 'development',
plugins: [
new webpack.DefinePlugin({
'process.env.API_URL': JSON.stringify(
env.apiUrl || 'http://localhost:3000'
)
})
]
};
};
Такой подход позволяет:
При одновременном использовании нескольких источников действует приоритет:
--envprocess.env.env файлЭто важно при отладке неожиданных значений в сборке.
Все переменные, переданные через DefinePlugin,
становятся частью клиентского бандла.
Следовательно:
Часто используется структура:
.env
.env.development
.env.production
Загрузка вручную:
const envFile = `.env.${process.env.NODE_ENV}`;
require('dotenv').config({ path: envFile });
В Windows и Unix синтаксис установки переменных различается. Решение
— cross-env.
Установка:
npm install cross-env
Использование:
cross-env NODE_ENV=production webpack
Пример управления функциональностью:
module.exports = (env) => ({
plugins: [
new webpack.DefinePlugin({
__FEATURE_X__: JSON.stringify(env.featureX === 'true')
})
]
});
Использование в коде:
if (__FEATURE_X__) {
console.log('Feature enabled');
}
Такой подход применяется для feature flags на этапе сборки.
Для предотвращения ошибок используется расширение типов:
declare namespace NodeJS {
interface ProcessEnv {
NODE_ENV: 'development' | 'production';
API_URL: string;
}
}
Это позволяет получать автодополнение и контроль значений на уровне компиляции.
Переменные окружения часто используются для управления оптимизациями:
const isProd = process.env.NODE_ENV === 'production';
module.exports = {
optimization: {
minimize: isProd,
splitChunks: isProd
}
};
Так формируется различное поведение сборки без изменения кода логики приложения.