UNPKG

webpack

Version:

Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.

156 lines (143 loc) 4.43 kB
/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Queue = require("./util/Queue"); const addToSet = (a, b) => { let changed = false; for (const item of b) { if (!a.has(item)) { a.add(item); changed = true; } } return changed; }; class FlagDependencyExportsPlugin { apply(compiler) { compiler.hooks.compilation.tap( "FlagDependencyExportsPlugin", compilation => { compilation.hooks.finishModules.tap( "FlagDependencyExportsPlugin", modules => { const dependencies = new Map(); const queue = new Queue(); let module; let moduleWithExports; let moduleProvidedExports; let providedExportsAreTemporary; const processDependenciesBlock = depBlock => { for (const dep of depBlock.dependencies) { if (processDependency(dep)) return true; } for (const variable of depBlock.variables) { for (const dep of variable.dependencies) { if (processDependency(dep)) return true; } } for (const block of depBlock.blocks) { if (processDependenciesBlock(block)) return true; } return false; }; const processDependency = dep => { const exportDesc = dep.getExports && dep.getExports(); if (!exportDesc) return; moduleWithExports = true; const exports = exportDesc.exports; // break early if it's only in the worst state if (module.buildMeta.providedExports === true) { return true; } // break if it should move to the worst state if (exports === true) { module.buildMeta.providedExports = true; notifyDependencies(); return true; } // merge in new exports if (Array.isArray(exports)) { if (addToSet(moduleProvidedExports, exports)) { notifyDependencies(); } } // store dependencies const exportDeps = exportDesc.dependencies; if (exportDeps) { providedExportsAreTemporary = true; for (const exportDependency of exportDeps) { // add dependency for this module const set = dependencies.get(exportDependency); if (set === undefined) { dependencies.set(exportDependency, new Set([module])); } else { set.add(module); } } } return false; }; const notifyDependencies = () => { const deps = dependencies.get(module); if (deps !== undefined) { for (const dep of deps) { queue.enqueue(dep); } } }; // Start with all modules without provided exports for (const module of modules) { if (module.buildInfo.temporaryProvidedExports) { // Clear exports when they are temporary // and recreate them module.buildMeta.providedExports = null; queue.enqueue(module); } else if (!module.buildMeta.providedExports) { queue.enqueue(module); } } while (queue.length > 0) { module = queue.dequeue(); if (module.buildMeta.providedExports !== true) { moduleWithExports = module.buildMeta && module.buildMeta.exportsType; moduleProvidedExports = Array.isArray( module.buildMeta.providedExports ) ? new Set(module.buildMeta.providedExports) : new Set(); providedExportsAreTemporary = false; processDependenciesBlock(module); module.buildInfo.temporaryProvidedExports = providedExportsAreTemporary; if (!moduleWithExports) { module.buildMeta.providedExports = true; notifyDependencies(); } else if (module.buildMeta.providedExports !== true) { module.buildMeta.providedExports = Array.from( moduleProvidedExports ); } } } } ); const providedExportsCache = new WeakMap(); compilation.hooks.rebuildModule.tap( "FlagDependencyExportsPlugin", module => { providedExportsCache.set(module, module.buildMeta.providedExports); } ); compilation.hooks.finishRebuildingModule.tap( "FlagDependencyExportsPlugin", module => { module.buildMeta.providedExports = providedExportsCache.get(module); } ); } ); } } module.exports = FlagDependencyExportsPlugin;