Skip to content

Commit b34663c

Browse files
committed
add more config options
fix bugs
1 parent 417044f commit b34663c

10 files changed

Lines changed: 156 additions & 51 deletions

File tree

lib/Chunk.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,14 @@ class Chunk {
259259
return false;
260260
}
261261

262+
removeEntrypoint(entrypoint) {
263+
if(!this._entrypoints.has(entrypoint)) {
264+
this._entrypoints.remove(entrypoint);
265+
return true;
266+
}
267+
return false;
268+
}
269+
262270
removeModule(module) {
263271
if(this._modules.delete(module)) {
264272
module.removeChunk(this);

lib/Entrypoint.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ class Entrypoint {
3535
}
3636
}
3737

38+
remove() {
39+
for(const chunk of this.chunks) {
40+
chunk.removeEntrypoint(this);
41+
}
42+
this.chunks.length = 0;
43+
}
44+
3845
getFiles() {
3946
const files = new Set();
4047

@@ -48,7 +55,7 @@ class Entrypoint {
4855
}
4956

5057
getRuntimeChunk() {
51-
return this.chunks[0];
58+
return this.chunks[this.chunks.length - 1];
5259
}
5360
}
5461

lib/Stats.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ class Stats {
412412
initial: chunk.isInitial(),
413413
entry: chunk.hasRuntime(),
414414
recorded: chunk.recorded,
415-
extraAsync: !!chunk.extraAsync,
415+
reason: chunk.chunkReason,
416416
size: chunk.modulesSize(),
417417
names: chunk.name ? [chunk.name] : [],
418418
files: chunk.files.slice(),
@@ -882,6 +882,9 @@ class Stats {
882882
if(chunk.recorded) {
883883
colors.green(" [recorded]");
884884
}
885+
if(chunk.reason) {
886+
colors.yellow(` ${chunk.reason}`);
887+
}
885888
newline();
886889
if(chunk.origins) {
887890
chunk.origins.forEach(origin => {

lib/WebpackOptionsApply.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,21 +299,32 @@ class WebpackOptionsApply extends OptionsApply {
299299
vendors: /[\\/]node_modules[\\/]/
300300
};
301301
}
302-
if(typeof options.optimization.initialVendorChunk === "string") {
302+
if(typeof nameOption === "string") {
303303
nameOption = {
304304
[nameOption]: /[\\/]node_modules[\\/]/
305305
};
306306
}
307307
if(nameOption && typeof nameOption === "object") {
308-
nameOption = module => {
308+
nameOption = ((nameOption) => ((module, compilation) => {
309309
if(!module.nameForCondition) return;
310310
const name = module.nameForCondition();
311311
for(const chunkName of Object.keys(nameOption)) {
312312
const regExp = nameOption[chunkName];
313-
if(regExp.test(name))
314-
return chunkName;
313+
if(typeof regExp === "string") {
314+
if(name.startsWith(regExp))
315+
return chunkName;
316+
} else if(typeof regExp === "function") {
317+
const result = regExp(name);
318+
if(typeof result === "string")
319+
return result;
320+
else if(result)
321+
return chunkName;
322+
} else {
323+
if(regExp.test(name))
324+
return chunkName;
325+
}
315326
}
316-
};
327+
}))(nameOption);
317328
}
318329
new AutomaticCommonsChunksPlugin({
319330
initialChunks: true,

lib/optimize/AutomaticCommonsChunksPlugin.js

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
*/
55
"use strict";
66

7+
const SortableSet = require("../util/SortableSet");
8+
9+
const sortByIdentifier = (a, b) => {
10+
if(a.identifier() > b.identifier()) return 1;
11+
if(a.identifier() < b.identifier()) return -1;
12+
return 0;
13+
};
14+
715
module.exports = class AutomaticCommonsChunksPlugin {
816
constructor(options) {
917
this.options = Object.assign({}, {
@@ -15,7 +23,7 @@ module.exports = class AutomaticCommonsChunksPlugin {
1523

1624
apply(compiler) {
1725
compiler.hooks.compilation.tap("AutomaticCommonsChunksPlugin", compilation => {
18-
compilation.hooks.optimizeChunks.tap("AutomaticCommonsChunksPlugin", chunks => {
26+
compilation.hooks.optimizeChunksAdvanced.tap("AutomaticCommonsChunksPlugin", chunks => {
1927
const indexMap = new Map();
2028
let index = 1;
2129
for(const chunk of chunks) {
@@ -38,28 +46,73 @@ module.exports = class AutomaticCommonsChunksPlugin {
3846
const key = chunkIndices.sort().join();
3947
let modules = chunksModulesMap.get(key);
4048
if(modules === undefined) {
41-
chunksModulesMap.set(key, modules = []);
49+
chunksModulesMap.set(key, modules = new SortableSet(undefined, sortByIdentifier));
4250
if(name) {
4351
chunksNameMap.set(key, name);
4452
}
4553
}
46-
modules.push(module);
54+
modules.add(module);
4755
}
48-
for(const [key, modules] of chunksModulesMap.entries()) {
49-
let chunkName = chunksNameMap.get(key);
56+
const entries = Array.from(chunksModulesMap.entries()).sort((a, b) => {
57+
const chunkNameA = chunksNameMap.get(a[0]);
58+
const chunkNameB = chunksNameMap.get(b[0]);
59+
if(chunkNameA && !chunkNameB) return -1;
60+
if(!chunkNameA && chunkNameB) return 1;
61+
if(chunkNameA && chunkNameB) {
62+
if(chunkNameA < chunkNameB) return -1;
63+
if(chunkNameA > chunkNameB) return 1;
64+
}
65+
const modulesA = a[1];
66+
const modulesB = b[1];
67+
const diff = modulesA.size - modulesB.size;
68+
if(diff) return diff;
69+
modulesA.sort();
70+
modulesB.sort();
71+
const aI = modulesA[Symbol.iterator]();
72+
const bI = modulesB[Symbol.iterator]();
73+
while(true) { // eslint-disable-line
74+
const aItem = aI.next();
75+
const bItem = bI.next();
76+
if(aItem.done) return 0;
77+
const aModuleIdentifier = aItem.value.identifier();
78+
const bModuleIdentifier = bItem.value.identifier();
79+
if(aModuleIdentifier > bModuleIdentifier) return -1;
80+
if(aModuleIdentifier < bModuleIdentifier) return 1;
81+
}
82+
});
83+
let changed = false;
84+
for(const [key, modules] of entries) {
85+
const chunkName = chunksNameMap.get(key);
5086
const newChunk = compilation.addChunk(chunkName);
51-
for(const chunk of modules[0].chunksIterable) {
87+
let splitted = false;
88+
const firstModule = modules.values().next().value;
89+
for(const chunk of firstModule.chunksIterable) {
90+
if(newChunk === chunk) continue;
91+
if(!indexMap.get(chunk)) continue;
92+
splitted = true;
5293
chunk.split(newChunk);
5394
for(const module of modules) {
5495
chunk.removeModule(module);
5596
module.rewriteChunkInReasons(chunk, [newChunk]);
5697
}
5798
}
58-
for(const module of modules) {
59-
newChunk.addModule(module);
60-
module.addChunk(newChunk);
99+
if(splitted) {
100+
if(chunkName) {
101+
const entrypoint = compilation.entrypoints[chunkName];
102+
if(entrypoint) {
103+
delete compilation.entrypoints[chunkName];
104+
entrypoint.remove();
105+
}
106+
}
107+
newChunk.chunkReason = chunkName ? "vendors chunk" : "commons chunk";
108+
for(const module of modules) {
109+
newChunk.addModule(module);
110+
module.addChunk(newChunk);
111+
}
112+
changed = true;
61113
}
62114
}
115+
if(changed) return true;
63116
});
64117
});
65118
}

lib/optimize/MergeDuplicateChunksPlugin.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class MergeDuplicateChunksPlugin {
4747
// when we found duplicates
4848
if(possibleDuplicates !== undefined && possibleDuplicates.size > 0) {
4949
for(const otherChunk of possibleDuplicates) {
50+
if(otherChunk.isInitial() !== chunk.isInitial()) continue;
5051
// merge them
5152
if(chunk.integrate(otherChunk, "duplicate"))
5253
chunks.splice(chunks.indexOf(otherChunk), 1);

schemas/WebpackOptions.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,17 @@
13401340
{
13411341
"type": "object",
13421342
"additionalProperties": {
1343-
"instanceof": "RegExp"
1343+
"oneOf": [
1344+
{
1345+
"instanceof": "RegExp"
1346+
},
1347+
{
1348+
"type": "string"
1349+
},
1350+
{
1351+
"instanceof": "Function"
1352+
}
1353+
]
13441354
}
13451355
},
13461356
{
Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,50 @@
11
Entrypoint main = main.js
2-
Entrypoint a = 2.js 3.js a.js
3-
Entrypoint b = 2.js 3.js 0.js b.js
4-
Entrypoint c = 2.js 0.js c.js
5-
chunk {0} 0.js 20 bytes {2} {3} {4} {7} {8} [initial] [rendered]
6-
[2] ./f.js 20 bytes {0} [built]
7-
chunk {1} 1.chunk.js 34 bytes {2} {3} {4} {8} [rendered]
2+
Entrypoint a = libs.js vendors.js a.js
3+
Entrypoint b = libs.js vendors.js b.js
4+
Entrypoint c = libs.js vendors.js c.js
5+
chunk {0} 0.chunk.js 20 bytes {2} {3} {4} {7} {8} {11} {12} [rendered] commons chunk
6+
[2] ./f.js 20 bytes {0} {9} {10} [built]
7+
chunk {1} 1.chunk.js 34 bytes {2} {3} {4} {8} {11} {12} [rendered]
88
> [] 6:0-13
9-
[8] ./g.js 34 bytes {1} [built]
10-
chunk {2} 2.js 40 bytes {7} [entry] [rendered]
11-
[0] ./d.js 20 bytes {2} [built]
12-
[1] ./node_modules/x.js 20 bytes {2} [built]
13-
chunk {3} 3.js 20 bytes {7} [initial] [rendered]
14-
[3] ./node_modules/y.js 20 bytes {3} [built]
9+
[9] ./g.js 34 bytes {1} [built]
10+
chunk {2} 2.chunk.js 40 bytes {7} [rendered] commons chunk
11+
[0] ./d.js 20 bytes {2} {8} {9} {10} [built]
12+
[1] ./node_modules/x.js 20 bytes {2} {11} [built]
13+
chunk {3} 3.chunk.js 20 bytes {7} [rendered] commons chunk
14+
[3] ./node_modules/y.js 20 bytes {3} {12} [built]
1515
chunk {4} 4.chunk.js 122 bytes {7} [rendered]
16-
> [7] ./index.js 1:0-13
17-
[5] ./a.js + 1 modules 122 bytes {4} {8} [built]
16+
> [8] ./index.js 1:0-13
17+
[7] ./a.js + 1 modules 122 bytes {4} {8} [built]
1818
| ./a.js 87 bytes [built]
1919
| ./e.js 20 bytes [built]
2020
chunk {5} 5.chunk.js 72 bytes {7} [rendered]
21-
> [7] ./index.js 2:0-13
22-
[4] ./b.js 72 bytes {5} {9} [built]
23-
chunk {6} 6.chunk.js 107 bytes {7} [rendered]
24-
> [7] ./index.js 3:0-13
25-
[6] ./c.js + 1 modules 107 bytes {6} {10} [built]
26-
| ./c.js 72 bytes [built]
27-
| ./node_modules/z.js 20 bytes [built]
21+
> [8] ./index.js 2:0-13
22+
[5] ./b.js 72 bytes {5} {9} [built]
23+
chunk {6} 6.chunk.js 92 bytes {7} [rendered]
24+
> [8] ./index.js 3:0-13
25+
[4] ./node_modules/z.js 20 bytes {6} {12} [built]
26+
[6] ./c.js 72 bytes {6} {10} [built]
2827
chunk {7} main.js (main) 45 bytes [entry] [rendered]
29-
> main [7] ./index.js
30-
[7] ./index.js 45 bytes {7} [built]
31-
chunk {8} a.js (a) 122 bytes [initial] [rendered]
28+
> main [8] ./index.js
29+
[8] ./index.js 45 bytes {7} [built]
30+
chunk {8} a.js (a) 142 bytes [entry] [rendered]
3231
> a []
33-
[5] ./a.js + 1 modules 122 bytes {4} {8} [built]
32+
[0] ./d.js 20 bytes {2} {8} {9} {10} [built]
33+
[7] ./a.js + 1 modules 122 bytes {4} {8} [built]
3434
| ./a.js 87 bytes [built]
3535
| ./e.js 20 bytes [built]
36-
chunk {9} b.js (b) 72 bytes [initial] [rendered]
37-
> b [4] ./b.js
38-
[4] ./b.js 72 bytes {5} {9} [built]
39-
chunk {10} c.js (c) 107 bytes [initial] [rendered]
40-
> c []
41-
[6] ./c.js + 1 modules 107 bytes {6} {10} [built]
42-
| ./c.js 72 bytes [built]
43-
| ./node_modules/z.js 20 bytes [built]
36+
chunk {9} b.js (b) 112 bytes [entry] [rendered]
37+
> b [5] ./b.js
38+
[0] ./d.js 20 bytes {2} {8} {9} {10} [built]
39+
[2] ./f.js 20 bytes {0} {9} {10} [built]
40+
[5] ./b.js 72 bytes {5} {9} [built]
41+
chunk {10} c.js (c) 112 bytes [entry] [rendered]
42+
> c [6] ./c.js
43+
[0] ./d.js 20 bytes {2} {8} {9} {10} [built]
44+
[2] ./f.js 20 bytes {0} {9} {10} [built]
45+
[6] ./c.js 72 bytes {6} {10} [built]
46+
chunk {11} libs.js (libs) 20 bytes [initial] [rendered] vendors chunk
47+
[1] ./node_modules/x.js 20 bytes {2} {11} [built]
48+
chunk {12} vendors.js (vendors) 40 bytes [initial] [rendered] vendors chunk
49+
[3] ./node_modules/y.js 20 bytes {3} {12} [built]
50+
[4] ./node_modules/z.js 20 bytes {6} {12} [built]

test/statsCases/async-commons-chunk-auto/node_modules/xyz.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/statsCases/async-commons-chunk-auto/webpack.config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const path = require("path");
12
module.exports = {
23
mode: "production",
34
entry: {
@@ -10,7 +11,10 @@ module.exports = {
1011
chunkFilename: "[name].chunk.js"
1112
},
1213
optimization: {
13-
initialVendorChunk: "libs"
14+
initialVendorsChunk: {
15+
"libs": /[\\/](xyz|x)/,
16+
vendors: path.resolve(__dirname, "node_modules")
17+
}
1418
},
1519
stats: {
1620
hash: false,

0 commit comments

Comments
 (0)