Конфигурация Webpack не ограничивается статическим объектом. Хотя базовый вариант представляет собой обычный JavaScript-объект, система загрузки конфигурации поддерживает более гибкие формы экспорта: функцию и Promise. Эти варианты позволяют адаптировать сборку под окружение, параметры запуска, режим выполнения и даже асинхронные источники данных.
Наиболее простая и часто используемая форма — экспорт конфигурационного объекта напрямую:
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
}
};
Такой подход фиксирует конфигурацию на этапе загрузки файла. Webpack просто читает объект и использует его без дополнительной обработки. Это удобно для небольших проектов или стандартных сценариев, где не требуется адаптация под окружение.
Особенности статического объекта:
При увеличении сложности проекта статический объект начинает ограничивать архитектурные возможности, особенно при необходимости условной сборки.
Webpack поддерживает экспорт функции вместо объекта. Эта функция может возвращать конфигурацию на основе входных параметров.
Базовый формат:
module.exports = (env, argv) => {
return {
mode: argv.mode || 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
}
};
};
env — это объект, передаваемый через CLI при запуске
Webpack:
webpack --env production
или
webpack --env apiUrl=https://example.com
Пример обработки:
module.exports = (env) => {
return {
mode: env.production ? 'production' : 'development',
entry: './src/index.js'
};
};
env позволяет создавать конфигурации, зависящие от
внешних условий, не изменяя сам файл конфигурации.
argv содержит аргументы командной строки, переданные
Webpack CLI:
module.exports = (env, argv) => {
return {
mode: argv.mode,
devtool: argv.mode === 'development' ? 'source-map' : false,
entry: './src/index.js'
};
};
Наиболее часто используется поле argv.mode, которое
автоматически задаётся при запуске:
webpack --mode production
Экспорт функции позволяет формировать различные конфигурации в зависимости от логики приложения:
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
mode: isProduction ? 'production' : 'development',
entry: './src/index.js',
output: {
filename: isProduction ? 'bundle.min.js' : 'bundle.js',
path: __dirname + '/dist'
},
devtool: isProduction ? false : 'source-map'
};
};
Такой подход позволяет централизовать правила сборки и избегать дублирования конфигураций.
Функциональный экспорт часто используется для построения конфигураций по шаблону:
const createConfig = (env, argv) => {
const isProd = argv.mode === 'production';
return {
mode: isProd ? 'production' : 'development',
entry: './src/index.js',
output: {
filename: isProd ? 'app.min.js' : 'app.js',
path: __dirname + '/dist'
}
};
};
module.exports = createConfig;
Такой подход позволяет:
Webpack поддерживает асинхронный экспорт через Promise. Это используется в случаях, когда конфигурация зависит от внешних источников: файлов, API, переменных окружения, удалённых сервисов.
Простейший пример:
module.exports = new Promise((resolve) => {
setTimeout(() => {
resolve({
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
}
});
}, 1000);
});
Хотя искусственная задержка здесь демонстрационная, реальный смысл заключается в асинхронной подготовке данных.
Promise-экспорт часто применяется для загрузки JSON или других источников:
const fs = require('fs');
module.exports = new Promise((resolve, reject) => {
fs.readFile('./webpack.settings.json', 'utf-8', (err, data) => {
if (err) {
reject(err);
return;
}
const settings = JSON.parse(data);
resolve({
mode: settings.mode,
entry: settings.entry,
output: {
filename: settings.outputFile,
path: __dirname + '/dist'
}
});
});
});
Такой подход позволяет отделить конфигурацию от кода сборки и управлять параметрами через внешние файлы.
Асинхронная конфигурация может учитывать окружение:
module.exports = new Promise((resolve) => {
const env = process.env.NODE_ENV;
const config = {
mode: env === 'production' ? 'production' : 'development',
entry: './src/index.js',
output: {
filename: env === 'production' ? 'bundle.min.js' : 'bundle.js',
path: __dirname + '/dist'
}
};
resolve(config);
});
Здесь Promise не добавляет задержки, но сохраняет возможность расширения асинхронной логики в будущем.
Наиболее гибкая форма — комбинация функции и Promise:
module.exports = (env, argv) => {
return new Promise((resolve) => {
const isProd = argv.mode === 'production';
setTimeout(() => {
resolve({
mode: isProd ? 'production' : 'development',
entry: './src/index.js',
output: {
filename: isProd ? 'bundle.min.js' : 'bundle.js',
path: __dirname + '/dist'
}
});
}, 500);
});
};
Такой подход используется в сложных системах сборки, где конфигурация зависит от:
Webpack определяет конфигурацию по типу экспортируемого значения:
Функция может возвращать как объект, так и Promise, что делает её универсальным вариантом.
Статический объект применяется, когда конфигурация фиксирована и не зависит от внешних факторов.
Функция используется при наличии:
Promise применяется при:
Поддержка трёх форм экспорта превращает Webpack-конфигурацию в полноценный исполняемый модуль. Это позволяет рассматривать сборку как часть приложения, а не как статический набор параметров.
Функциональный и асинхронный экспорт делает возможными:
Webpack в таком подходе перестаёт быть просто инструментом бандлинга и становится системой выполнения конфигурационной логики на Node.js-уровне.