webpack/lib/FlagDependencyUsagePlugin.js

122 lines
3.3 KiB
JavaScript
Raw Normal View History

/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
2018-07-30 23:08:51 +08:00
"use strict";
const { STAGE_DEFAULT } = require("./OptimizationStages");
2019-01-23 19:12:44 +08:00
const Queue = require("./util/Queue");
2018-07-28 03:12:09 +08:00
/** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
/** @typedef {import("./Dependency")} Dependency */
2018-07-30 23:08:51 +08:00
/** @typedef {import("./Module")} Module */
class FlagDependencyUsagePlugin {
2018-07-28 03:12:09 +08:00
/**
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
2018-02-25 09:00:20 +08:00
compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", compilation => {
const moduleGraph = compilation.moduleGraph;
compilation.hooks.optimizeDependencies.tap(
2018-12-09 19:54:17 +08:00
{
name: "FlagDependencyUsagePlugin",
stage: STAGE_DEFAULT
2018-12-09 19:54:17 +08:00
},
2018-02-25 09:00:20 +08:00
modules => {
2018-07-20 22:24:35 +08:00
/**
*
* @param {Module} module module to process
* @param {boolean | string[]} usedExports list of used exports
2018-07-20 22:24:35 +08:00
* @returns {void}
*/
2018-02-25 09:00:20 +08:00
const processModule = (module, usedExports) => {
2019-01-23 19:12:44 +08:00
const exportsInfo = moduleGraph.getExportsInfo(module);
let changed = false;
if (usedExports === true) {
2019-01-23 19:12:44 +08:00
changed = exportsInfo.setUsedInUnknownWay();
} else if (usedExports) {
for (const exportName of usedExports) {
2019-01-28 17:40:32 +08:00
if (
exportName === "default" &&
module.buildMeta.exportsType === "named"
) {
if (exportsInfo.setUsedAsNamedExportType()) {
changed = true;
}
} else {
const exportInfo = exportsInfo.getExportInfo(exportName);
if (exportInfo.used !== true) {
exportInfo.used = true;
changed = true;
}
}
}
} else {
2019-01-23 19:12:44 +08:00
// for a module without side effects we stop tracking usage here when no export is used
// This module won't be evaluated in this case
if (module.factoryMeta.sideEffectFree) return;
changed = exportsInfo.setUsedForSideEffectsOnly();
}
2019-01-23 19:12:44 +08:00
if (changed) {
queue.enqueue(module);
2018-02-25 09:00:20 +08:00
}
};
/**
* @param {DependenciesBlock} depBlock the dependencies block
* @returns {void}
*/
2019-01-23 19:12:44 +08:00
const processDependenciesBlock = depBlock => {
2018-02-25 09:00:20 +08:00
for (const dep of depBlock.dependencies) {
2019-01-23 19:12:44 +08:00
processDependency(dep);
2018-01-22 20:52:43 +08:00
}
2018-02-25 09:00:20 +08:00
for (const block of depBlock.blocks) {
2019-01-23 19:12:44 +08:00
queue.enqueue(block);
2018-02-25 09:00:20 +08:00
}
};
2016-12-05 06:47:19 +08:00
/**
* @param {Dependency} dep the dependency
* @returns {void}
*/
2019-01-23 19:12:44 +08:00
const processDependency = dep => {
const reference = compilation.getDependencyReference(dep);
2018-02-25 09:00:20 +08:00
if (!reference) return;
const referenceModule = reference.module;
2018-02-25 09:00:20 +08:00
const importedNames = reference.importedNames;
2019-01-23 19:12:44 +08:00
processModule(referenceModule, importedNames);
2018-02-25 09:00:20 +08:00
};
2018-02-25 09:00:20 +08:00
for (const module of modules) {
2019-01-23 19:12:44 +08:00
moduleGraph.getExportsInfo(module).setHasUseInfo();
2018-02-25 09:00:20 +08:00
}
2019-01-23 19:12:44 +08:00
/** @type {Queue<DependenciesBlock>} */
const queue = new Queue();
for (const deps of compilation.entryDependencies.values()) {
for (const dep of deps) {
const module = moduleGraph.getModule(dep);
if (module) {
processModule(module, true);
}
2018-02-25 09:00:20 +08:00
}
2017-11-08 18:32:05 +08:00
}
2018-02-25 09:00:20 +08:00
while (queue.length) {
2019-01-23 19:12:44 +08:00
const depBlock = queue.dequeue();
processDependenciesBlock(depBlock);
2018-02-25 09:00:20 +08:00
}
2017-11-08 18:32:05 +08:00
}
2018-02-25 09:00:20 +08:00
);
});
}
}
2018-07-28 03:12:09 +08:00
module.exports = FlagDependencyUsagePlugin;