diff options
Diffstat (limited to 'node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js')
-rw-r--r-- | node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js | 192 |
1 files changed, 127 insertions, 65 deletions
diff --git a/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js b/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js index 43550819c..7fff59207 100644 --- a/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js +++ b/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js @@ -1,65 +1,127 @@ -/*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
-*/
-"use strict";
-
-function hasModule(chunk, module, checkedChunks) {
- if(chunk.containsModule(module)) return [chunk];
- if(chunk.parents.length === 0) return false;
- return allHaveModule(chunk.parents.filter((c) => {
- return !checkedChunks.has(c);
- }), module, checkedChunks);
-}
-
-function allHaveModule(someChunks, module, checkedChunks) {
- if(!checkedChunks) checkedChunks = new Set();
- var chunks = new Set();
- for(var i = 0; i < someChunks.length; i++) {
- checkedChunks.add(someChunks[i]);
- var subChunks = hasModule(someChunks[i], module, checkedChunks);
- if(!subChunks) return false;
-
- for(var index = 0; index < subChunks.length; index++) {
- var item = subChunks[index];
-
- chunks.add(item);
- }
- }
- return chunks;
-}
-
-class RemoveParentModulesPlugin {
- apply(compiler) {
- compiler.plugin("compilation", (compilation) => {
- compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], (chunks) => {
- for(var index = 0; index < chunks.length; index++) {
- var chunk = chunks[index];
- if(chunk.parents.length === 0) continue;
-
- // TODO consider Map when performance has improved https://gist.github.com/sokra/b36098368da7b8f6792fd7c85fca6311
- var cache = Object.create(null);
- var modules = chunk.getModules();
- for(var i = 0; i < modules.length; i++) {
- var module = modules[i];
-
- var dId = module.getChunkIdsIdent();
- var parentChunksWithModule;
- if(dId === null) {
- parentChunksWithModule = allHaveModule(chunk.parents, module);
- } else if(dId in cache) {
- parentChunksWithModule = cache[dId];
- } else {
- parentChunksWithModule = cache[dId] = allHaveModule(chunk.parents, module);
- }
- if(parentChunksWithModule) {
- module.rewriteChunkInReasons(chunk, Array.from(parentChunksWithModule));
- chunk.removeModule(module);
- }
- }
- }
- });
- });
- }
-}
-module.exports = RemoveParentModulesPlugin;
+/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Queue = require("../util/Queue"); +const { intersect } = require("../util/SetHelpers"); + +const getParentChunksWithModule = (currentChunk, module) => { + const chunks = []; + const stack = new Set(currentChunk.parentsIterable); + + for (const chunk of stack) { + if (chunk.containsModule(module)) { + chunks.push(chunk); + } else { + for (const parent of chunk.parentsIterable) { + stack.add(parent); + } + } + } + + return chunks; +}; + +class RemoveParentModulesPlugin { + apply(compiler) { + compiler.hooks.compilation.tap("RemoveParentModulesPlugin", compilation => { + const handler = (chunks, chunkGroups) => { + const queue = new Queue(); + const availableModulesMap = new WeakMap(); + + for (const chunkGroup of compilation.entrypoints.values()) { + // initialize available modules for chunks without parents + availableModulesMap.set(chunkGroup, new Set()); + for (const child of chunkGroup.childrenIterable) { + queue.enqueue(child); + } + } + + while (queue.length > 0) { + const chunkGroup = queue.dequeue(); + let availableModules = availableModulesMap.get(chunkGroup); + let changed = false; + for (const parent of chunkGroup.parentsIterable) { + const availableModulesInParent = availableModulesMap.get(parent); + if (availableModulesInParent !== undefined) { + // If we know the available modules in parent: process these + if (availableModules === undefined) { + // if we have not own info yet: create new entry + availableModules = new Set(availableModulesInParent); + for (const chunk of parent.chunks) { + for (const m of chunk.modulesIterable) { + availableModules.add(m); + } + } + availableModulesMap.set(chunkGroup, availableModules); + changed = true; + } else { + for (const m of availableModules) { + if ( + !parent.containsModule(m) && + !availableModulesInParent.has(m) + ) { + availableModules.delete(m); + changed = true; + } + } + } + } + } + if (changed) { + // if something changed: enqueue our children + for (const child of chunkGroup.childrenIterable) { + queue.enqueue(child); + } + } + } + + // now we have available modules for every chunk + for (const chunk of chunks) { + const availableModulesSets = Array.from( + chunk.groupsIterable, + chunkGroup => availableModulesMap.get(chunkGroup) + ); + if (availableModulesSets.some(s => s === undefined)) continue; // No info about this chunk group + const availableModules = + availableModulesSets.length === 1 + ? availableModulesSets[0] + : intersect(availableModulesSets); + const numberOfModules = chunk.getNumberOfModules(); + const toRemove = new Set(); + if (numberOfModules < availableModules.size) { + for (const m of chunk.modulesIterable) { + if (availableModules.has(m)) { + toRemove.add(m); + } + } + } else { + for (const m of availableModules) { + if (chunk.containsModule(m)) { + toRemove.add(m); + } + } + } + for (const module of toRemove) { + module.rewriteChunkInReasons( + chunk, + getParentChunksWithModule(chunk, module) + ); + chunk.removeModule(module); + } + } + }; + compilation.hooks.optimizeChunksBasic.tap( + "RemoveParentModulesPlugin", + handler + ); + compilation.hooks.optimizeExtractedChunksBasic.tap( + "RemoveParentModulesPlugin", + handler + ); + }); + } +} +module.exports = RemoveParentModulesPlugin; |