@ -36,6 +36,7 @@ DedupePlugin.prototype.apply = function(compiler) {
compilation . plugin ( "after-optimize-chunks" , function ( chunks ) {
var entryChunks = chunks . filter ( function ( c ) { return c . entry ; } ) ;
entryChunks . forEach ( function ( chunk ) { // for each entry chunk
var hasDeduplicatedModules = false ;
( function x ( dups , roots , visited , chunk ) {
var currentDups = [ ] ;
var currentRoots = [ ] ;
@ -51,6 +52,7 @@ DedupePlugin.prototype.apply = function(compiler) {
module . rootDuplicates [ chunkIndex ] . push ( module ) ;
module . rootDuplicates [ chunkIndex ] . commonModules =
mergeCommonModules ( module . rootDuplicates [ chunkIndex ] . commonModules , module . getAllModuleDependencies ( ) ) ;
hasDeduplicatedModules = true ;
} else {
idx = dups . indexOf ( module . duplicates ) ;
if ( idx < 0 ) {
@ -65,6 +67,7 @@ DedupePlugin.prototype.apply = function(compiler) {
module . rootDuplicates [ chunkIndex ] = roots [ idx ] ;
module . rootDuplicates [ chunkIndex ] . commonModules =
mergeCommonModules ( module . rootDuplicates [ chunkIndex ] . commonModules , module . getAllModuleDependencies ( ) ) ;
hasDeduplicatedModules = true ;
}
}
}
@ -83,9 +86,12 @@ DedupePlugin.prototype.apply = function(compiler) {
chunk . addModule ( template ) ;
template . addChunk ( chunk ) ;
compilation . modules . push ( template ) ;
hasDeduplicatedModules = true ;
}
} ) ;
} ( [ ] , [ ] , [ ] , chunk ) ) ;
if ( hasDeduplicatedModules )
chunk . _DedupePlugin _hasDeduplicatedModules = true ;
} ) ;
} ) ;
function mergeCommonModules ( commonModules , newModules ) {
@ -96,17 +102,25 @@ DedupePlugin.prototype.apply = function(compiler) {
} ) ;
compiler . moduleTemplate = new DedupModuleTemplateDecorator ( compiler . moduleTemplate ) ;
compiler . mainTemplate = Object . create ( compiler . mainTemplate ) ;
var oldRenderAddModule = compiler . mainTemplate . renderAddModule ;
compiler . mainTemplate . renderAddModule = function ( hash , chunk , varModuleId , varModule ) {
if ( ! chunk . _DedupePlugin _hasDeduplicatedModules ) {
return oldRenderAddModule . call ( this , hash , chunk , varModuleId , varModule ) ;
}
return [
"var _m = " + varModule + ";" ,
"" ,
"// Check if module is deduplicated" ,
"switch(typeof _m) {" ,
"case \"number\":" ,
this . indent ( [
"// Module is a copy of another module" ,
"modules[" + varModuleId + "] = modules[_m];" ,
"break;"
] ) ,
"case \"object\":" ,
this . indent ( [
"// Module can be created from a template" ,
"modules[" + varModuleId + "] = (function(_m) {" ,
this . indent ( [
"var args = _m.slice(1), fn = modules[_m[0]];" ,
@ -120,25 +134,34 @@ DedupePlugin.prototype.apply = function(compiler) {
"break;"
] ) ,
"default:" ,
this . indent ( "modules[" + varModuleId + "] = _m;" ) ,
this . indent ( [
"// Normal module" ,
"modules[" + varModuleId + "] = _m;"
] ) ,
"}"
]
} ;
var oldRenderModules = compiler . mainTemplate . renderModules ;
compiler . mainTemplate . renderModules = function renderModules ( hash , chunk , moduleTemplate , dependencyTemplates ) {
if ( ! chunk . _DedupePlugin _hasDeduplicatedModules ) {
return oldRenderModules . call ( this , hash , chunk , moduleTemplate , dependencyTemplates ) ;
}
var source = new ConcatSource ( ) ;
source . add ( "(function(modules) {\n" ) ;
source . add ( this . indent ( [
"// Check all modules for deduplicated modules" ,
"for(var i in modules) {" ,
this . indent ( [
"switch(typeof modules[i]) {" ,
"case \"number\":" ,
this . indent ( [
"// Module is a copy of another module" ,
"modules[i] = modules[modules[i]];" ,
"break;"
] ) ,
"case \"object\":" ,
this . indent ( [
"// Module can be created from a template" ,
"modules[i] = (function(_m) {" ,
this . indent ( [
"var args = _m.slice(1), fn = modules[_m[0]];" ,
@ -177,6 +200,10 @@ DedupModuleTemplateDecorator.prototype.render = function(module, dependencyTempl
request : module . request ,
templateModules : rootDuplicates . template . templateModules
} ) ;
rootDuplicates . template . reasons . sort ( function ( a , b ) {
if ( a . request == b . request ) return 0 ;
return a . request < b . request ? - 1 : 1 ;
} ) ;
var array = [ rootDuplicates . template . id ] . concat ( module . getTemplateArguments ( rootDuplicates . template . templateModules ) . map ( function ( module ) {
if ( typeof module . id !== "number" )
return "(function webpackMissingModule() { throw new Error(" + JSON . stringify ( "Cannot find module" ) + "); }())"