@@ -33,35 +33,48 @@ module.exports = class AutomaticCommonsChunksPlugin {
33
33
apply ( compiler ) {
34
34
compiler . hooks . compilation . tap ( "AutomaticCommonsChunksPlugin" , compilation => {
35
35
compilation . hooks . optimizeChunksAdvanced . tap ( "AutomaticCommonsChunksPlugin" , chunks => {
36
+ // Give each selected chunk an index (to create strings from chunks)
36
37
const indexMap = new Map ( ) ;
37
38
let index = 1 ;
38
39
for ( const chunk of chunks ) {
39
40
if ( chunk . isInitial ( ) === this . options . initialChunks )
40
41
indexMap . set ( chunk , index ++ ) ;
41
42
}
43
+ // Map a list of chunks to a list of modules
44
+ // For the key the chunk "index" is used, the value is a SortableSet of modules
42
45
const chunksModulesMap = new Map ( ) ;
46
+ // Map a list of chunks to a name (not every list of chunks is mapped, only when "name" option is used)
43
47
const chunksNameMap = new Map ( ) ;
48
+ // Walk through all modules
44
49
for ( const module of compilation . modules ) {
50
+ // Get indices of chunks in which this module occurs
45
51
const chunkIndices = Array . from ( module . chunksIterable , chunk => indexMap . get ( chunk ) ) . filter ( Boolean ) ;
52
+ // Get name from "name" option
46
53
let name = this . options . name ;
47
54
if ( typeof name === "function" )
48
55
name = name ( module ) ;
49
56
if ( name ) {
50
- chunkIndices . push ( name ) ;
57
+ chunkIndices . push ( `[ ${ name } ]` ) ;
51
58
} else if ( this . options . onlyNamed ) {
59
+ // May skip unnamed chunks if "onlyNamed" is used
52
60
continue ;
53
61
}
62
+ // skip for modules which are only in one chunk or don't get a name
54
63
if ( chunkIndices . length <= 1 ) continue ;
64
+ // Create key for maps
55
65
const key = chunkIndices . sort ( ) . join ( ) ;
66
+ // Add module to maps
56
67
let modules = chunksModulesMap . get ( key ) ;
57
68
if ( modules === undefined ) {
58
69
chunksModulesMap . set ( key , modules = new SortableSet ( undefined , sortByIdentifier ) ) ;
59
70
if ( name ) {
71
+ // Note name when used
60
72
chunksNameMap . set ( key , name ) ;
61
73
}
62
74
}
63
75
modules . add ( module ) ;
64
76
}
77
+ // Get size of module lists and sort them by name and size
65
78
const entries = Array . from ( chunksModulesMap . entries ( ) , pair => {
66
79
const modules = pair [ 1 ] ;
67
80
const size = Array . from ( modules , m => m . size ( ) ) . reduce ( ( a , b ) => a + b , 0 ) ;
@@ -71,9 +84,8 @@ module.exports = class AutomaticCommonsChunksPlugin {
71
84
size
72
85
} ;
73
86
} ) . sort ( ( a , b ) => {
87
+ // Sort
74
88
// 1. by chunk name
75
- // 2. by total modules size
76
- // 3. by module identifiers
77
89
const chunkNameA = chunksNameMap . get ( a . key ) ;
78
90
const chunkNameB = chunksNameMap . get ( b . key ) ;
79
91
if ( chunkNameA && ! chunkNameB ) return - 1 ;
@@ -82,10 +94,12 @@ module.exports = class AutomaticCommonsChunksPlugin {
82
94
if ( chunkNameA < chunkNameB ) return - 1 ;
83
95
if ( chunkNameA > chunkNameB ) return 1 ;
84
96
}
97
+ // 2. by total modules size
85
98
const diffSize = b . size - a . size ;
86
99
if ( diffSize ) return diffSize ;
87
100
const modulesA = a . modules ;
88
101
const modulesB = b . modules ;
102
+ // 3. by module identifiers
89
103
const diff = modulesA . size - modulesB . size ;
90
104
if ( diff ) return diff ;
91
105
modulesA . sort ( ) ;
@@ -102,44 +116,55 @@ module.exports = class AutomaticCommonsChunksPlugin {
102
116
if ( aModuleIdentifier < bModuleIdentifier ) return 1 ;
103
117
}
104
118
} ) ;
119
+
105
120
let changed = false ;
106
- for ( const { key, modules, size } of entries ) {
107
- const chunkName = chunksNameMap . get ( key ) ;
108
- if ( ! chunkName && size < this . options . minSize ) continue ;
109
- const newChunk = compilation . addChunk ( chunkName ) ;
110
- let splitted = false ;
111
- const firstModule = modules . values ( ) . next ( ) . value ;
121
+ // Walk though all entries
122
+ for ( const item of entries ) {
123
+ const chunkName = chunksNameMap . get ( item . key ) ;
124
+ // Skip if size is smaller than minimum size
125
+ if ( ! chunkName && item . size < this . options . minSize ) continue ;
126
+ // Variable for the new chunk (lazy created)
127
+ let newChunk ;
128
+ // Walk through all chunks
129
+ // All modules have the same chunks so we can use the first module
130
+ const firstModule = item . modules . values ( ) . next ( ) . value ;
112
131
for ( const chunk of firstModule . chunksIterable ) {
113
- // skip itself when already a chunk of the module
114
- if ( newChunk === chunk ) continue ;
132
+ // skip if we address ourself
133
+ if ( chunk . name === chunkName ) continue ;
115
134
// only use selected chunks
116
135
if ( ! indexMap . get ( chunk ) ) continue ;
117
136
// respect max requests when not a named chunk
118
137
if ( ! chunkName && getRequests ( chunk ) >= this . options . maxRequests ) continue ;
119
- splitted = true ;
138
+ if ( newChunk === undefined ) {
139
+ // Create the new chunk
140
+ newChunk = compilation . addChunk ( chunkName ) ;
141
+ }
142
+ // Add graph connections for splitted chunk
120
143
chunk . split ( newChunk ) ;
121
- for ( const module of modules ) {
144
+ // Remove all selected modules from the chunk
145
+ for ( const module of item . modules ) {
122
146
chunk . removeModule ( module ) ;
123
147
module . rewriteChunkInReasons ( chunk , [ newChunk ] ) ;
124
148
}
125
149
}
126
- if ( splitted ) {
150
+ // If we successfully creates a new chunk
151
+ if ( newChunk ) {
152
+ // If the choosen name is already an entry point we remove the entry point
127
153
if ( chunkName ) {
128
154
const entrypoint = compilation . entrypoints [ chunkName ] ;
129
155
if ( entrypoint ) {
130
156
delete compilation . entrypoints [ chunkName ] ;
131
157
entrypoint . remove ( ) ;
132
158
}
133
159
}
160
+ // Add a note to the chunk
134
161
newChunk . chunkReason = chunkName ? "vendors chunk" : "commons chunk" ;
135
- for ( const module of modules ) {
162
+ // Add all modules to the new chunk
163
+ for ( const module of item . modules ) {
136
164
newChunk . addModule ( module ) ;
137
165
module . addChunk ( newChunk ) ;
138
166
}
139
167
changed = true ;
140
- } else if ( ! chunkName ) {
141
- newChunk . remove ( "empty" ) ;
142
- chunks . splice ( chunks . indexOf ( newChunk ) , 1 ) ;
143
168
}
144
169
}
145
170
if ( changed ) return true ;
0 commit comments