Зачем вообще делить конфигурацию Webpack?
Если вы когда-либо настраивали Webpack для проекта с нуля, то знаете, как быстро один файл `webpack.config.js` превращается в нечто чудовищное: десятки плагинов, условий, ветвлений на `process.env.NODE_ENV` и прочего хаоса. Особенно это заметно, когда проект растёт, и появляются разные требования для сборки: разработка, продакшен, тестирование, storybook и прочие окружения. Здесь и приходит на помощь webpack-merge — утилита, которая позволяет писать чистую, модульную и масштабируемую конфигурацию Webpack.
Что такое webpack-merge и как он работает
`webpack-merge` — это утилита, которая помогает объединять несколько конфигураций Webpack в одну. Под капотом она использует глубокое слияние объектов и массивов, что позволяет гибко комбинировать общие и специфические настройки окружения. Самое главное — это избавляет вас от повторения кода и делает конфигурацию прозрачной.
Вот упрощённый пример:
```js
// webpack.common.js
module.exports = {
entry: './src/index.js',
module: {
rules: [/*...*/],
},
};
```
```js
// webpack.dev.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
});
```
```js
// webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'production',
optimization: {
minimize: true,
},
});
```
Нестандартные подходы к разделению конфигураций
Стандартная практика — делить конфигурации на общую (common), для разработки (dev) и продакшена (prod). Но в реальной жизни этого часто недостаточно. Вот несколько нестандартных, но полезных сценариев использования и кастомизации `webpack-merge конфигурации`:
1. Разделение по типу сборки (SPA, SSR, Widget)

У вас может быть один проект, который собирается как одностраничное приложение, серверный рендер и встраиваемый виджет. Вместо того чтобы городить условную логику в одном файле, создайте отдельные конфигурации для каждого типа сборки и объединяйте их с помощью `webpack-merge`.
```js
// webpack.spa.js
const common = require('./webpack.common');
module.exports = merge(common, { /* SPA-specific config */ });
// webpack.ssr.js
module.exports = merge(common, { target: 'node', output: { libraryTarget: 'commonjs2' } });
```
2. Использование функций для динамики
Конфигурации не обязательно должны быть простыми объектами. Это могут быть функции, принимающие параметры и возвращающие конфигурацию. Это особенно удобно, если вы хотите передавать окружение или флаги сборки.
```js
// webpack.config.js
module.exports = (env) => {
const config = require(`./webpack.${env.type}.js`);
return merge(require('./webpack.common'), config);
};
```
Теперь можно запускать сборку так:
```bash
webpack --env type=spa
```
Практические советы по настройке webpack-merge

Когда речь заходит о том, как использовать webpack-merge, важно понимать, что не все настройки объединяются одинаково. Например, массивы по умолчанию просто заменяются, а не дополняются. Но `webpack-merge` поддерживает специальные стратегии объединения.
```js
const { mergeWithCustomize, customizeArray } = require('webpack-merge');
const mergedConfig = mergeWithCustomize({
customizeArray: customizeArray({
'module.rules': 'prepend', // или 'append'
}),
})(commonConfig, prodConfig);
```
Это позволяет, например, дописывать новые правила в `module.rules`, не теряя старые, что часто бывает критично при добавлении нового лоадера.
Типичная структура проекта с разделением конфигурации
Вот как может выглядеть структура вашего проекта при использовании `webpack-merge`:
```
/config
webpack.common.js
webpack.dev.js
webpack.prod.js
webpack.storybook.js
webpack.ssr.js
webpack.config.js
```
Такой подход делает проект прозрачным и легко поддерживаемым. Вы всегда знаете, где искать конфигурации и легко можете подключить новую сборку, просто скопировав и адаптировав существующую.
Полезные паттерны и тонкости
1. Не смешивайте плагины разных окружений. Например, `HotModuleReplacementPlugin` не нужен в продакшене. Оставляйте его в `webpack.dev.js`.
2. Избегайте дублирования. Если какой-то лоадер используется в двух окружениях, выносите его в `webpack.common.js`.
3. Используйте переменные окружения через cross-env. Это позволит вам точно управлять конфигурацией из npm-скриптов.
4. Добавьте логирование конфигурации. Иногда удобно печатать финальную конфигурацию в консоль при сборке (`console.log(JSON.stringify(config, null, 2))`).
5. Следите за размером бандла. Используйте `webpack-bundle-analyzer` как отдельную конфигурацию, подключаемую через `merge`.
Заключение
Использование `webpack-merge` — это не просто удобная практика, а необходимость для современных проектов. Разделение конфигурации с webpack-merge позволяет не только поддерживать порядок, но и ускоряет разработку, уменьшает количество ошибок и делает переход между окружениями максимально плавным. С его помощью вы можете строить сложные пайплайны сборки, не запутываясь в десятках условий. А благодаря расширенным возможностям кастомизации и стратегий слияния, настройка webpack-merge может быть максимально тонкой и точной — вплоть до слияния конкретных массивов или объектов по ключам.
В итоге, если вы ещё не применяете `webpack-merge` в своем проекте, самое время попробовать. Вы удивитесь, насколько это упрощает жизнь, особенно когда проект начинает расти.



