@@ -33,6 +33,7 @@ module.exports = function buildDeps(context, mainModule, options, callback) {
3333 modules : { } ,
3434 modulesById : { } ,
3535 chunks : { } ,
36+ chunkCount : 0 ,
3637 nextModuleId : 0 ,
3738 nextChunkId : 1 ,
3839 chunkModules : { } // used by checkObsolete
@@ -71,13 +72,17 @@ module.exports = function buildDeps(context, mainModule, options, callback) {
7172 // remove modules which are included in parent chunk
7273 removeParentsModules ( depTree , depTree . chunks [ chunkId ] ) ;
7374
74- // remove the chunk if it is empty
75- removeChunkIfEmpty ( depTree , depTree . chunks [ chunkId ] ) ;
76-
77- // remove duplicate chunks
75+ // remove duplicate and empty chunks
7876 checkObsolete ( depTree , depTree . chunks [ chunkId ] ) ;
7977 }
8078
79+ if ( options . maxChunks ) {
80+ while ( depTree . chunkCount > options . maxChunks ) {
81+ if ( ! removeOneChunk ( depTree , true ) )
82+ break ;
83+ }
84+ }
85+
8186 createRealChunkIds ( depTree , options ) ;
8287 options . events . emit ( "task-end" , "optimize" ) ;
8388
@@ -649,6 +654,7 @@ function addChunk(depTree, chunkStartpoint, options) {
649654 usages : 1
650655 } ;
651656 depTree . chunks [ chunk . id ] = chunk ;
657+ depTree . chunkCount ++ ;
652658 }
653659 if ( chunkStartpoint ) {
654660 chunkStartpoint . chunkId = chunk . id ;
@@ -712,39 +718,95 @@ function removeParentsModules(depTree, chunk) {
712718 }
713719}
714720
715- function removeChunkIfEmpty ( depTree , chunk ) {
716- var hasModules = false ;
717- for ( var moduleId in chunk . modules ) {
718- if ( chunk . modules [ moduleId ] === "include" ) {
719- hasModules = true ;
720- break ;
721- }
722- }
723- if ( ! hasModules ) {
724- chunk . contexts . forEach ( function ( c ) { c . chunkId = null ; } ) ;
725- chunk . empty = true ;
726- }
727- }
728-
729721function checkObsolete ( depTree , chunk ) {
730722 var modules = [ ] ;
731723 for ( var moduleId in chunk . modules ) {
732724 if ( chunk . modules [ moduleId ] === "include" ) {
733725 modules . push ( moduleId ) ;
734726 }
735727 }
736- if ( modules . length === 0 ) return ;
728+ if ( modules . length === 0 ) {
729+ chunk . contexts . forEach ( function ( c ) { c . chunkId = null ; } ) ;
730+ chunk . empty = true ;
731+ depTree . chunkCount -- ;
732+ return ;
733+ }
737734 modules . sort ( ) ;
738735 var moduleString = modules . join ( " " ) ;
739736 if ( depTree . chunkModules [ moduleString ] ) {
740737 chunk . equals = depTree . chunkModules [ moduleString ] ;
741738 chunk . contexts . forEach ( function ( c ) {
742739 c . chunkId = chunk . equals ;
743740 } ) ;
741+ depTree . chunkCount -- ;
744742 } else
745743 depTree . chunkModules [ moduleString ] = chunk . id ;
746744}
747745
746+ function moduleSize ( depTree , moduleId ) {
747+ return depTree . modulesById [ moduleId ] . source && depTree . modulesById [ moduleId ] . source . length || 0 ;
748+ }
749+
750+ function removeOneChunk ( depTree , force ) {
751+ var chunks = [ ] ;
752+ for ( var chunkId in depTree . chunks ) {
753+ var chunk = depTree . chunks [ chunkId ] ;
754+ if ( ! chunk . empty && ! chunk . equals && chunk . id != "main" ) {
755+ chunks . push ( chunk ) ;
756+ }
757+ }
758+ var best = null ;
759+ chunks . forEach ( function ( chunkA , idxA ) {
760+ chunks . forEach ( function ( chunkB , idxB ) {
761+ if ( idxB <= idxA ) return ;
762+ var sizeSum = 60 , sizeMerged = 30 ;
763+ for ( var moduleId in chunkA . modules ) {
764+ if ( chunkA . modules [ moduleId ] === "include" ) {
765+ var size = moduleSize ( depTree , moduleId ) ;
766+ sizeSum += size + 10 ;
767+ sizeMerged += size + 10 ;
768+ }
769+ }
770+ for ( var moduleId in chunkB . modules ) {
771+ if ( chunkB . modules [ moduleId ] === "include" ) {
772+ var size = moduleSize ( depTree , moduleId ) ;
773+ sizeSum += size + 10 ;
774+ if ( chunkA . modules [ moduleId ] !== "include" )
775+ sizeMerged += size + 10 ;
776+ }
777+ }
778+ var value = sizeSum * 2 - sizeMerged ;
779+ if ( best == null || best [ 0 ] < value )
780+ best = [ value , chunkA . id , chunkB . id ] ;
781+ } ) ;
782+ } ) ;
783+ console . dir ( best ) ;
784+ if ( ! best ) return false ;
785+ if ( force || best [ 0 ] > 0 ) {
786+ var chunk = depTree . chunks [ best [ 1 ] ] ;
787+ chunk . equals = best [ 2 ] ;
788+ chunk . contexts . forEach ( function ( c ) {
789+ c . chunkId = chunk . equals ;
790+ } ) ;
791+ chunks . forEach ( function ( chunk ) {
792+ if ( chunk . equals == best [ 1 ] ) {
793+ chunk . equals = best [ 2 ] ;
794+ chunk . contexts . forEach ( function ( c ) {
795+ c . chunkId = chunk . equals ;
796+ } ) ;
797+ }
798+ } ) ;
799+ var otherChunk = depTree . chunks [ best [ 2 ] ] ;
800+ for ( var moduleId in chunk . modules ) {
801+ if ( chunk . modules [ moduleId ] === "include" ) {
802+ otherChunk . modules [ moduleId ] = "include" ;
803+ }
804+ }
805+ depTree . chunkCount -- ;
806+ return true ;
807+ }
808+ }
809+
748810// rename the chunk ids after a defined sheme
749811function createRealChunkIds ( depTree , options ) {
750812 var sortedChunks = [ ] ;
0 commit comments