diff --git a/lib/Compilation.js b/lib/Compilation.js index b182380b9a1..5f64119a8bc 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -92,6 +92,7 @@ const compareLocations = require("./compareLocations"); * @typedef {Object} AvailableModulesChunkGroupMapping * @property {ChunkGroup} chunkGroup * @property {Set} availableModules + * @property {boolean} needCopy */ /** @@ -1491,7 +1492,7 @@ class Compilation extends Tapable { // eachother and Blocks with Chunks. It stops traversing when all modules // for a chunk are already available. So it doesn't connect unneeded chunks. - /** @type {Map} */ + /** @type {Map} */ const chunkDependencies = new Map(); const allCreatedChunkGroups = new Set(); @@ -1664,7 +1665,8 @@ class Compilation extends Tapable { if (!deps) chunkDependencies.set(chunkGroup, (deps = [])); deps.push({ block: b, - chunkGroup: c + chunkGroup: c, + couldBeFiltered: true }); // 3. We enqueue the DependenciesBlock for traversal @@ -1778,12 +1780,14 @@ class Compilation extends Tapable { // PART TWO /** @type {Set} */ let availableModules; + /** @type {Set} */ let newAvailableModules; /** @type {Queue} */ const queue2 = new Queue( inputChunkGroups.map(chunkGroup => ({ chunkGroup, - availableModules: new Set() + availableModules: new Set(), + needCopy: true })) ); @@ -1811,8 +1815,12 @@ class Compilation extends Tapable { */ const filterFn = dep => { const depChunkGroup = dep.chunkGroup; + if (!dep.couldBeFiltered) return true; if (blocksWithNestedBlocks.has(dep.block)) return true; - if (areModulesAvailable(depChunkGroup, newAvailableModules)) return false; // break all modules are already available + if (areModulesAvailable(depChunkGroup, newAvailableModules)) { + return false; // break all modules are already available + } + dep.couldBeFiltered = false; return true; }; @@ -1831,7 +1839,10 @@ class Compilation extends Tapable { // the list didn't shrink. let minAvailableModules = minAvailableModulesMap.get(chunkGroup); if (minAvailableModules === undefined) { - minAvailableModulesMap.set(chunkGroup, new Set(availableModules)); + minAvailableModulesMap.set( + chunkGroup, + queueItem.needCopy ? new Set(availableModules) : availableModules + ); } else { let deletedModules = false; for (const m of minAvailableModules) { @@ -1857,33 +1868,36 @@ class Compilation extends Tapable { } } - // 4. Filter edges with available modules - const filteredDeps = deps.filter(filterFn); - - // 5. Foreach remaining edge + // 4. Foreach remaining edge const nextChunkGroups = new Set(); - for (let i = 0; i < filteredDeps.length; i++) { - const dep = filteredDeps[i]; + for (let i = 0; i < deps.length; i++) { + const dep = deps[i]; + + // Filter inline, rather than creating a new array from `.filter()` + if (!filterFn(dep)) { + continue; + } const depChunkGroup = dep.chunkGroup; const depBlock = dep.block; - // 6. Connect block with chunk + // 5. Connect block with chunk GraphHelpers.connectDependenciesBlockAndChunkGroup( depBlock, depChunkGroup ); - // 7. Connect chunk with parent + // 6. Connect chunk with parent GraphHelpers.connectChunkGroupParentAndChild(chunkGroup, depChunkGroup); nextChunkGroups.add(depChunkGroup); } - // 8. Enqueue further traversal + // 7. Enqueue further traversal for (const nextChunkGroup of nextChunkGroups) { queue2.enqueue({ chunkGroup: nextChunkGroup, - availableModules: newAvailableModules + availableModules: newAvailableModules, + needCopy: nextChunkGroup.size !== 1 }); } }