Webpack.merge插件
webpack-merge插件可以用来merge两个webpack的配置。它的底层引用了lodash中的merge,但针对webpack的特点,专门对loaders,preLoaders,postLoaders专门做了处理。
一般情况下,对于以下两个module
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var module: { loaders: [ { test: /\.css$/, loaders: ['style', 'css'], }, ] } var moduleExtend = { loaders: [ { test: /\.jsx?$/, loader: 'babel?stage=1', include: path.join(ROOT_PATH, 'app'), }, ] }
|
进行merge(module, moduleExtend)后会得到如下结果:
1 2 3 4 5 6 7 8 9
| moduleMerged = { loaders: [ { test: /\.jsx?$/, loader: 'babel?stage=1', include: path.join(ROOT_PATH, 'app'), }, ] }
|
因为loaders是数组,所以结果中的css的loader信息丢失了。所以为了保证merge之后,loaders,preLoaders,postLoaders中的内容不会丢失,webpack-merge中对于loaders,preLoaders,postLoaders进行了特殊处理,采用concat对数组内容进行合并
1 2 3 4
| if (isLoader(key)) { return b.concat(a); } return a.concat(b);
|
如此,merge的结果为
1 2 3 4 5 6 7 8 9 10 11
| loaders: [ { test: /\.css$/, loaders: ['style', 'css'], }, { test: /\.jsx?$/, loader: 'babel?stage=1', include: path.join(ROOT_PATH, 'app'), } ]
|
但是如果遇到两个test值相同的loader时,仅仅用concat的话,会产生两条结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| merge({ loaders: [{ test: /\.js$/, loader: 'babel' }] }, { loaders: [{ test: /\.js$/, loader: 'coffee' }] }); { loaders: [{ test: /\.js$/, loader: 'coffee' }, { test: /\.js$/, loader: 'babel' }] }
|
这时对于js文件会先用babel-loader处理,然后再用coffee-loader处理。但是更多的,我们希望merge的结果是,后一个可以覆盖掉前一个。此外,在loaders中,除了可以写loader:’coffee’,还会有loaders:[‘xx’]的形式,如果一律采用concat的形式,显然过于粗暴了。所以,webpack-merge提供了更为聪明的的merge.smart函数,可以将test值相同的loader(preLoaders,postLoaders)进行合并。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| merge.smart({ loaders: [{ test: /\.js$/, loader: 'babel' }] }, { loaders: [{ test: /\.js$/, loader: 'coffee' }] }); { loaders: [{ test: /\.js$/, loader: 'coffee' }] }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| merge.smart({ loaders: [{ test: /\.js$/, loaders: ['babel'] }] }, { loaders: [{ test: /\.js$/, loaders: ['coffee'] }] }); { loaders: [{ test: /\.js$/, loaders: ['coffee', 'babel'] }] }
|
注意:对于loaders中带参数的形式,如babel?plugins[]=object-assign,在smart merge时会认为和babel、babel?…为同一类,后一个会对前一个产生覆盖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| merge.smart({ loaders: [{ test: /\.js$/, loaders: ['babel?plugins[]=object-assign'] }] }, { loaders: [{ test: /\.js$/, loaders: ['babel', 'coffee'] }] }); { loaders: [{ test: /\.js$/, loaders: ['babel', 'coffee'] }] }
|
- 如果后一个loaders,前一个为loader,则merge时会将loader转化为loaders,然后进行merge
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| merge.smart({ loaders: [{ test: /\.js$/, loader: 'babel' }] }, { loaders: [{ test: /\.js$/, loaders: ['coffee'] }] }); { loaders: [{ test: /\.js$/, loaders: ['coffee', 'babel'] }] }
|
- 如果后一个为loader,前一个为loaders,则merge的结果为loader
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| merge.smart({ loaders: [{ test: /\.js$/, loaders: ['babel'] }] }, { loaders: [{ test: /\.js$/, loader: 'coffee' }] }); { loaders: [{ test: /\.js$/, loader: 'coffee' }] }
|
注意:include和exclude的配置同时也会影响loader是否会被合并。如果两个loaders有不同的include或者exclude值(后一个loaders不包含include或exclude除外),那么loaders最终不会进行合并,而是像merge中进行了concat。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| merge.smart({ loaders: [{ test: /\.js$/, include: '/dir1', loader: 'babel' }] }, { loaders: [{ test: /\.js$/, include: '/dir2', loader: 'coffee' }] }); { loaders: [{ test: /\.js$/, include: '/dir2', loader: 'coffee' }, { test: /\.js$/, include: '/dir1', loader: 'babel' }] }
|