Skip to content

Commit 6bf1868

Browse files
authored
Merge pull request #9635 from webpack/bugfix/9634
fixes #9634
2 parents 54519bd + 83dd295 commit 6bf1868

10 files changed

Lines changed: 94 additions & 14 deletions

File tree

lib/buildChunkGraph.js

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ const GraphHelpers = require("./GraphHelpers");
2828

2929
/**
3030
* @typedef {Object} ChunkGroupInfo
31+
* @property {ChunkGroup} chunkGroup the chunk group
3132
* @property {Set<Module>} minAvailableModules current minimal set of modules available at this point
3233
* @property {boolean} minAvailableModulesOwned true, if minAvailableModules is owned and can be modified
3334
* @property {Set<Module>[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules
3435
* @property {QueueItem[]} skippedItems queue items that were skipped because module is already available in parent chunks (need to reconsider when minAvailableModules is shrinking)
3536
* @property {Set<Module>} resultingAvailableModules set of modules available including modules from this chunk group
37+
* @property {Set<ChunkGroup>} children set of children chunk groups, that will be revisited when availableModules shrink
3638
*/
3739

3840
/**
@@ -196,11 +198,13 @@ const visitModules = (
196198
});
197199
}
198200
chunkGroupInfoMap.set(chunkGroup, {
201+
chunkGroup,
199202
minAvailableModules: new Set(),
200203
minAvailableModulesOwned: true,
201204
availableModulesToBeMerged: [],
202205
skippedItems: [],
203-
resultingAvailableModules: undefined
206+
resultingAvailableModules: undefined,
207+
children: undefined
204208
});
205209
return queue;
206210
};
@@ -418,7 +422,7 @@ const visitModules = (
418422
}
419423
logger.timeEnd("visiting");
420424

421-
if (queueConnect.size > 0) {
425+
while (queueConnect.size > 0) {
422426
logger.time("calculating available modules");
423427

424428
// Figure out new parents for chunk groups
@@ -435,17 +439,26 @@ const visitModules = (
435439
}
436440
}
437441
info.resultingAvailableModules = resultingAvailableModules;
442+
if (info.children === undefined) {
443+
info.children = targets;
444+
} else {
445+
for (const target of targets) {
446+
info.children.add(target);
447+
}
448+
}
438449

439450
// 2. Update chunk group info
440451
for (const target of targets) {
441452
let chunkGroupInfo = chunkGroupInfoMap.get(target);
442453
if (chunkGroupInfo === undefined) {
443454
chunkGroupInfo = {
455+
chunkGroup: target,
444456
minAvailableModules: undefined,
445457
minAvailableModulesOwned: undefined,
446458
availableModulesToBeMerged: [],
447459
skippedItems: [],
448-
resultingAvailableModules: undefined
460+
resultingAvailableModules: undefined,
461+
children: undefined
449462
};
450463
chunkGroupInfoMap.set(target, chunkGroupInfo);
451464
}
@@ -463,7 +476,7 @@ const visitModules = (
463476
// Execute the merge
464477
for (const info of outdatedChunkGroupInfo) {
465478
const availableModulesToBeMerged = info.availableModulesToBeMerged;
466-
let minAvailableModules = info.minAvailableModules;
479+
let cachedMinAvailableModules = info.minAvailableModules;
467480

468481
// 1. Get minimal available modules
469482
// It doesn't make sense to traverse a chunk again with more available modules.
@@ -474,29 +487,31 @@ const visitModules = (
474487
}
475488
let changed = false;
476489
for (const availableModules of availableModulesToBeMerged) {
477-
if (minAvailableModules === undefined) {
478-
minAvailableModules = availableModules;
479-
info.minAvailableModules = minAvailableModules;
490+
if (cachedMinAvailableModules === undefined) {
491+
cachedMinAvailableModules = availableModules;
492+
info.minAvailableModules = cachedMinAvailableModules;
480493
info.minAvailableModulesOwned = false;
481494
changed = true;
482495
} else {
483496
if (info.minAvailableModulesOwned) {
484497
// We own it and can modify it
485-
for (const m of minAvailableModules) {
498+
for (const m of cachedMinAvailableModules) {
486499
if (!availableModules.has(m)) {
487-
minAvailableModules.delete(m);
500+
cachedMinAvailableModules.delete(m);
488501
changed = true;
489502
}
490503
}
491504
} else {
492-
for (const m of minAvailableModules) {
505+
for (const m of cachedMinAvailableModules) {
493506
if (!availableModules.has(m)) {
494-
// minAvailableModules need to be modified
507+
// cachedMinAvailableModules need to be modified
495508
// but we don't own it
496-
// construct a new Set as intersection of minAvailableModules and availableModules
509+
// construct a new Set as intersection of cachedMinAvailableModules and availableModules
497510
/** @type {Set<Module>} */
498511
const newSet = new Set();
499-
const iterator = minAvailableModules[Symbol.iterator]();
512+
const iterator = cachedMinAvailableModules[
513+
Symbol.iterator
514+
]();
500515
/** @type {IteratorResult<Module>} */
501516
let it;
502517
while (!(it = iterator.next()).done) {
@@ -510,9 +525,16 @@ const visitModules = (
510525
newSet.add(module);
511526
}
512527
}
513-
minAvailableModules = newSet;
528+
cachedMinAvailableModules = newSet;
514529
info.minAvailableModulesOwned = true;
515530
info.minAvailableModules = newSet;
531+
532+
// Update the cache from the first queue
533+
// if the chunkGroup is currently cached
534+
if (chunkGroup === info.chunkGroup) {
535+
minAvailableModules = cachedMinAvailableModules;
536+
}
537+
516538
changed = true;
517539
break;
518540
}
@@ -528,6 +550,19 @@ const visitModules = (
528550
queue.push(queueItem);
529551
}
530552
info.skippedItems.length = 0;
553+
554+
// 3. Reconsider children chunk groups
555+
if (info.children !== undefined) {
556+
const chunkGroup = info.chunkGroup;
557+
for (const c of info.children) {
558+
let connectList = queueConnect.get(chunkGroup);
559+
if (connectList === undefined) {
560+
connectList = new Set();
561+
queueConnect.set(chunkGroup, connectList);
562+
}
563+
connectList.add(c);
564+
}
565+
}
531566
}
532567
outdatedChunkGroupInfo.clear();
533568
logger.timeEnd("merging available modules");
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default import(/* webpackChunkName: "shared" */ "./shared");
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default import(/* webpackChunkName: "async-b" */ "./async-b");
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import leaf from "./leaf";
2+
3+
it("should include the leaf module", () => {
4+
expect(leaf).toBe("ok");
5+
});
6+
7+
it("should load the leaf module from a", () => {
8+
return import(/* webpackChunkName: "shared" */ "./shared").then(shared => {
9+
return shared.default.then(module => {
10+
expect(module.default).toBe("ok");
11+
});
12+
});
13+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
it("should load the leaf module from b", () => {
2+
return import(/* webpackChunkName: "async-b2" */ "./async-b2").then(asy => {
3+
return asy.default.then(asy => {
4+
return asy.default.then(shared => {
5+
return shared.default.then(module => {
6+
expect(module.default).toBe("ok");
7+
});
8+
});
9+
});
10+
});
11+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default "ok";
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import leaf from "./leaf";
2+
3+
export default leaf;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default import(/* webpackChunkName: "module" */ "./module");
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
findBundle: function(i, options) {
3+
return ["a.js", "b.js"];
4+
}
5+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
entry: {
3+
b: "./entry-b",
4+
a: "./entry-a"
5+
},
6+
output: {
7+
filename: "[name].js"
8+
}
9+
};

0 commit comments

Comments
 (0)