2017-05-03 15:35:00 +02:00
/ *
MIT License http : //www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @ sokra
* /
"use strict" ;
class AggressiveMergingPlugin {
constructor ( options ) {
if ( options !== undefined && typeof options !== "object" || Array . isArray ( options ) ) {
throw new Error ( "Argument should be an options object. To use defaults, pass in nothing.\nFor more info on options, see https://webpack.js.org/plugins/" ) ;
}
this . options = options || { } ;
}
apply ( compiler ) {
const options = this . options ;
const minSizeReduce = options . minSizeReduce || 1.5 ;
function getParentsWeight ( chunk ) {
return chunk . parents . map ( ( p ) => {
return p . isInitial ( ) ? options . entryChunkMultiplicator || 10 : 1 ;
} ) . reduce ( ( a , b ) => {
return a + b ;
} , 0 ) ;
}
2017-08-14 05:01:11 +02:00
compiler . plugin ( "this-compilation" , ( compilation ) => {
2017-05-03 15:35:00 +02:00
compilation . plugin ( "optimize-chunks-advanced" , ( chunks ) => {
let combinations = [ ] ;
chunks . forEach ( ( a , idx ) => {
if ( a . isInitial ( ) ) return ;
for ( let i = 0 ; i < idx ; i ++ ) {
const b = chunks [ i ] ;
if ( b . isInitial ( ) ) continue ;
2017-08-14 05:01:11 +02:00
combinations . push ( {
a ,
b ,
improvement : undefined
} ) ;
2017-05-03 15:35:00 +02:00
}
} ) ;
combinations . forEach ( ( pair ) => {
2017-08-14 05:01:11 +02:00
const a = pair . b . size ( {
2017-05-03 15:35:00 +02:00
chunkOverhead : 0
} ) ;
2017-08-14 05:01:11 +02:00
const b = pair . a . size ( {
2017-05-03 15:35:00 +02:00
chunkOverhead : 0
} ) ;
2017-08-14 05:01:11 +02:00
const ab = pair . b . integratedSize ( pair . a , {
2017-05-03 15:35:00 +02:00
chunkOverhead : 0
} ) ;
let newSize ;
if ( ab === false ) {
2017-08-14 05:01:11 +02:00
pair . improvement = false ;
return ;
2017-05-03 15:35:00 +02:00
} else if ( options . moveToParents ) {
const aOnly = ab - b ;
const bOnly = ab - a ;
const common = a + b - ab ;
2017-08-14 05:01:11 +02:00
newSize = common + getParentsWeight ( pair . b ) * aOnly + getParentsWeight ( pair . a ) * bOnly ;
2017-05-03 15:35:00 +02:00
} else {
newSize = ab ;
}
2017-08-14 05:01:11 +02:00
pair . improvement = ( a + b ) / newSize ;
2017-05-03 15:35:00 +02:00
} ) ;
combinations = combinations . filter ( ( pair ) => {
2017-08-14 05:01:11 +02:00
return pair . improvement !== false ;
2017-05-03 15:35:00 +02:00
} ) ;
combinations . sort ( ( a , b ) => {
2017-08-14 05:01:11 +02:00
return b . improvement - a . improvement ;
2017-05-03 15:35:00 +02:00
} ) ;
const pair = combinations [ 0 ] ;
if ( ! pair ) return ;
2017-08-14 05:01:11 +02:00
if ( pair . improvement < minSizeReduce ) return ;
2017-05-03 15:35:00 +02:00
if ( options . moveToParents ) {
2017-08-14 05:01:11 +02:00
const commonModules = pair . b . modules . filter ( ( m ) => {
return pair . a . modules . indexOf ( m ) >= 0 ;
2017-05-03 15:35:00 +02:00
} ) ;
2017-08-14 05:01:11 +02:00
const aOnlyModules = pair . b . modules . filter ( ( m ) => {
2017-05-03 15:35:00 +02:00
return commonModules . indexOf ( m ) < 0 ;
} ) ;
2017-08-14 05:01:11 +02:00
const bOnlyModules = pair . a . modules . filter ( ( m ) => {
2017-05-03 15:35:00 +02:00
return commonModules . indexOf ( m ) < 0 ;
} ) ;
aOnlyModules . forEach ( ( m ) => {
2017-08-14 05:01:11 +02:00
pair . b . removeModule ( m ) ;
m . removeChunk ( pair . b ) ;
pair . b . parents . forEach ( ( c ) => {
2017-05-03 15:35:00 +02:00
c . addModule ( m ) ;
m . addChunk ( c ) ;
} ) ;
} ) ;
bOnlyModules . forEach ( ( m ) => {
2017-08-14 05:01:11 +02:00
pair . a . removeModule ( m ) ;
m . removeChunk ( pair . a ) ;
pair . a . parents . forEach ( ( c ) => {
2017-05-03 15:35:00 +02:00
c . addModule ( m ) ;
m . addChunk ( c ) ;
} ) ;
} ) ;
}
2017-08-14 05:01:11 +02:00
if ( pair . b . integrate ( pair . a , "aggressive-merge" ) ) {
chunks . splice ( chunks . indexOf ( pair . a ) , 1 ) ;
2017-05-03 15:35:00 +02:00
return true ;
}
} ) ;
} ) ;
}
}
module . exports = AggressiveMergingPlugin ;