What is webpack-merge?
The webpack-merge package provides a utility to merge multiple webpack configurations. It is useful for composing different webpack configurations for development, production, or any other purpose. It simplifies the process of combining configurations by smartly merging loaders, plugins, and other specific structures within the webpack configuration objects.
What are webpack-merge's main functionalities?
Merging basic configurations
This feature allows for the merging of two basic webpack configurations into one. It is useful for separating common configuration from environment-specific configurations.
const { merge } = require('webpack-merge');
const commonConfig = { entry: './src/app.js' };
const productionConfig = { mode: 'production' };
const mergedConfig = merge(commonConfig, productionConfig);
Merging with rules
This demonstrates merging configurations that include module rules. webpack-merge smartly combines the loaders, allowing for a nuanced configuration that can differ between development and production environments.
const { merge } = require('webpack-merge');
const commonConfig = { module: { rules: [ { test: /\.css$/, use: ['style-loader'] } ] } };
const productionConfig = { module: { rules: [ { test: /\.css$/, use: ['css-loader'] } ] } };
const mergedConfig = merge(commonConfig, productionConfig);
Customizing merge behavior
This feature allows for customizing the merge behavior, such as prepending or appending elements in arrays instead of the default merging strategy. It's particularly useful for fine-tuning the order of plugins or loaders.
const { mergeWithCustomize, customizeArray } = require('webpack-merge');
const commonConfig = { plugins: ['CommonPlugin'] };
const productionConfig = { plugins: ['ProductionPlugin'] };
const mergedConfig = mergeWithCustomize({ customizeArray: customizeArray({ 'plugins': 'prepend' }) })(commonConfig, productionConfig);
Other packages similar to webpack-merge
deepmerge
deepmerge is a library that can deeply merge multiple objects into one. While it's not specific to webpack configurations, it can be used for a similar purpose. However, webpack-merge offers webpack-specific merging capabilities that deepmerge does not, such as smart merging of loaders and plugins.
lodash.merge
lodash.merge is a method from the Lodash library that provides a deep merge of objects. Similar to deepmerge, it can be used to merge webpack configurations but lacks the webpack-specific intelligence of webpack-merge, potentially requiring more manual configuration for complex webpack setups.
webpack-merge - Merge designed for Webpack
webpack-merge provides a merge
function that concatenates arrays and merges objects. This behavior is particularly useful in configuring webpack. There's also a webpack specific merge variant known as merge.smart
that's able to take webpack specifics into account (i.e., it can flatten loader definitions).
API
var output = merge(object1, object2, object3, ...);
var output = merge.smart(object1, object2, object3, ...);
Check out SurviveJS - Webpack and React to dig deeper into the topic.
Example
package.json
{
"scripts": {
"start": "webpack-dev-server",
"build": "webpack"
},
...
}
webpack.config.js
var path = require('path');
var merge = require('webpack-merge');
var TARGET = process.env.npm_lifecycle_event;
var common = {
entry: path.join(__dirname, 'app'),
...
module: {
loaders: [
{
test: /\.css$/,
loaders: ['style', 'css'],
},
],
},
};
if(TARGET === 'start') {
module.exports = merge(common, {
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel?stage=1',
include: path.join(ROOT_PATH, 'app'),
},
],
},
...
});
}
if(TARGET === 'build') {
module.exports = merge(common, {
...
});
}
...
Note that you can override existing arrays/objects like this:
var common = {
entry: [APP_PATH, STYLE_PATH]
...
};
if(TARGET === 'test') {
module.exports = merge(common, {
entry: [],
...
});
}
Smart Merging of Loaders
Webpack-merge tries to be smart about merging loaders when merge.smart
is used. Loaders with matching tests will be merged into a single loader value.
Loader string values loader: 'babel'
override each other.
merge.smart({
loaders: [{
test: /\.js$/,
loader: 'babel'
}]
}, {
loaders: [{
test: /\.js$/,
loader: 'coffee'
}]
});
{
loaders: [{
test: /\.js$/,
loader: 'coffee'
}]
}
Loader array values loaders: ['babel']
will be merged, without duplication.
merge.smart({
loaders: [{
test: /\.js$/,
loaders: ['babel']
}]
}, {
loaders: [{
test: /\.js$/,
loaders: ['coffee']
}]
});
{
loaders: [{
test: /\.js$/,
loaders: ['babel', 'coffee']
}]
}
Loader query strings loaders: ['babel?plugins[]=object-assign']
will be overridden
merge.smart({
loaders: [{
test: /\.js$/,
loaders: ['babel?plugins[]=object-assign']
}]
}, {
loaders: [{
test: /\.js$/,
loaders: ['babel', 'coffee']
}]
});
{
loaders: [{
test: /\.js$/,
loaders: ['babel', 'coffee']
}]
}
Loader arrays in source values will have loader strings merged into them.
merge.smart({
loaders: [{
test: /\.js$/,
loader: 'babel'
}]
}, {
loaders: [{
test: /\.js$/,
loaders: ['coffee']
}]
});
{
loaders: [{
test: /\.js$/,
loaders: ['babel', 'coffee']
}]
}
Loader strings in source values will always override.
merge.smart({
loaders: [{
test: /\.js$/,
loaders: ['babel']
}]
}, {
loaders: [{
test: /\.js$/,
loader: 'coffee'
}]
});
{
loaders: [{
test: /\.js$/,
loader: 'coffee'
}]
}
Contributors
- Fernando Montoya - Use separate lodash functions instead of the core package. Faster to install this way.
- Jonathan Felchlin - Smart merging for loaders.
- David Gómez - Performance and cosmetic improvements.
- siready - Extend
merge.smart
to support include/exclude
. - C.J. Winslow - Make
merge.smart
include/exclude
to work correctly with loader
. - Artem Zakharchenko - Fix
merge.smart
duplication so that if include
exists, it will merge. - Matt Shwery - If
exclude
is the same while using merge.smart
, merge loaders
. - Lucretiel - Added a more generic test to describe merge behavior better.
- Christian Hoffmeister - Fix
merge.smart
behavior so that it checks against full loader names instead of just the first letter. - Ken Powers - Changed Travis icon to use SVG (scales better).
License
webpack-merge is available under MIT. See LICENSE for more details.