Webpack предоставляет встроенный механизм работы с переменными
окружения через EnvironmentPlugin, который позволяет
передавать конфигурационные значения в сборку без необходимости жёстко
прописывать их в коде приложения. Этот плагин является тонкой обёрткой
над DefinePlugin и предназначен для упрощённого управления
окружением, особенно в проектах, где требуется разделение конфигураций
между development, staging и production.
EnvironmentPlugin подменяет значения переменных
окружения во время сборки, используя process.env. При этом
на этапе компиляции происходит статическая замена значений, что
позволяет полностью исключить runtime-зависимость от
process.env в браузерном коде.
Ключевой механизм:
process.envМинимальная конфигурация плагина включает перечисление переменных, которые должны быть доступны в приложении:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.EnvironmentPlugin([
'NODE_ENV',
'API_URL'
])
]
};
В этом случае Webpack ожидает, что process.env.NODE_ENV
и process.env.API_URL будут определены в окружении
сборки.
Если переменная отсутствует, её значение в коде станет
undefined.
Переменные берутся из реального окружения процесса Node.js, в котором запускается сборка.
Пример запуска:
NODE_ENV=production API_URL=https://api.example.com webpack
Внутри кода:
console.log(process.env.NODE_ENV);
console.log(process.env.API_URL);
После сборки код фактически преобразуется в:
console.log("production");
console.log("https://api.example.com");
EnvironmentPlugin поддерживает задание
fallback-значений, что делает конфигурацию более устойчивой к отсутствию
переменных.
new webpack.EnvironmentPlugin({
NODE_ENV: 'development',
API_URL: 'http://localhost:3000'
})
В этом варианте:
NODE_ENV не задан, используется
developmentAPI_URL отсутствует, применяется
http://localhost:3000Существует два режима работы:
Если передан массив переменных:
new webpack.EnvironmentPlugin(['API_URL'])
и переменная не определена, результатом будет undefined,
что может привести к ошибкам в логике приложения.
Если передан объект:
new webpack.EnvironmentPlugin({
API_URL: 'http://localhost'
})
то используется указанное значение по умолчанию.
EnvironmentPlugin по сути генерирует вызовы
DefinePlugin:
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.API_URL': JSON.stringify(process.env.API_URL)
});
Это означает, что подстановка происходит на уровне AST, а не во время выполнения.
После сборки в клиентском коде:
process.env не существует как объект среды
выполненияПример:
if (process.env.NODE_ENV === 'production') {
enableOptimizations();
}
После сборки:
if ("production" === "production") {
enableOptimizations();
}
При работе с TypeScript требуется дополнительное объявление типов,
иначе компилятор будет ругаться на отсутствие
process.env.
declare const process: {
env: {
NODE_ENV: string;
API_URL: string;
};
};
Это не влияет на Webpack, но обеспечивает корректную проверку типов на этапе компиляции TypeScript.
Чаще всего используется для управления режимами работы приложения:
if (process.env.NODE_ENV !== 'production') {
console.log('debug mode');
}
fetch(`${process.env.API_URL}/users`);
Позволяет переключать backend без изменения исходного кода.
if (process.env.ENABLE_BETA_FEATURES === 'true') {
enableBeta();
}
Переменные не могут изменяться во время выполнения приложения, так как подставляются на этапе сборки.
Любая конструкция:
process.env.SOME_VAR + suffix
превращается в константное выражение только частично, что может ограничивать оптимизации.
Все значения попадают в клиентский бандл:
могут быть извлечены из итогового JS-кода.
EnvironmentPlugin является надстройкой над
DefinePlugin, поэтому все особенности последнего
сохраняются:
const webpack = require('webpack');
module.exports = {
mode: 'production',
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'production',
API_URL: 'https://api.example.com',
ENABLE_LOGS: false
})
]
};
Использование в коде:
const apiUrl = process.env.API_URL;
if (process.env.ENABLE_LOGS === 'true') {
console.log('logs enabled');
}
Часто EnvironmentPlugin используется совместно с
dotenv:
require('dotenv').config();
module.exports = {
plugins: [
new webpack.EnvironmentPlugin(Object.keys(process.env))
]
};
dotenv загружает переменные из .env, а
EnvironmentPlugin внедряет их в сборку.
Webpack способен удалять мёртвый код благодаря подстановке значений:
if (process.env.NODE_ENV === 'development') {
debug();
}
После сборки production:
if ("production" === "development") {
debug();
}
Условие всегда ложно, и код может быть удалён Terser’ом.
Использование EnvironmentPlugin влияет на архитектуру
приложения:
В отличие от загрузки конфигурации через HTTP или JSON:
В серверных приложениях на Node.js:
process.env остаётся реальным объектом окруженияЭто создаёт необходимость различать server-side и client-side конфигурации.
Типичные проблемы:
undefinedПосле работы Webpack и Terser:
Это усиливает роль EnvironmentPlugin как инструмента
compile-time конфигурации.