webpack
Version:
Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
94 lines (75 loc) • 2.48 kB
JavaScript
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Alexander Akait @alexander-akait
*/
;
const DuplicateModulesWarning = require("../errors/DuplicateModulesWarning");
const { compareStrings } = require("../util/comparators");
const getModuleSize = require("./getModuleSize");
/** @import { PerformanceOptions } from "../../declarations/WebpackOptions" */
/** @import Compiler from "../Compiler" */
/**
* @import {
* DuplicateModuleDetails
* } from "../errors/DuplicateModulesWarning"
*/
const PLUGIN_NAME = "DuplicateModulesPlugin";
// Enough to name the offenders without printing the module graph.
const MAX_REPORTED_MODULES = 5;
class DuplicateModulesPlugin {
/**
* Creates an instance of DuplicateModulesPlugin.
* @param {PerformanceOptions} options the plugin options
*/
constructor(options) {
/** @type {PerformanceOptions["hints"]} */
this.hints = options.hints;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
const hints = this.hints;
if (!hints) return;
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.afterSeal.tap(PLUGIN_NAME, () => {
const { chunkGraph, requestShortener } = compilation;
/** @type {DuplicateModuleDetails[]} */
const duplicated = [];
let wasted = 0;
for (const module of compilation.modules) {
const chunks = chunkGraph.getNumberOfModuleChunks(module);
if (chunks < 2) continue;
// The first copy is the one that had to be emitted; the rest are
// what a shared chunk would save.
const extra = getModuleSize(module) * (chunks - 1);
wasted += extra;
duplicated.push({
name: module.readableIdentifier(requestShortener),
chunks,
wasted: extra
});
}
if (duplicated.length === 0) return;
// Ties break by name: which modules finish first is not stable.
duplicated.sort(
(a, b) => b.wasted - a.wasted || compareStrings(a.name, b.name)
);
const warning = new DuplicateModulesWarning(
duplicated.slice(0, MAX_REPORTED_MODULES),
wasted
);
if (hints === "error") {
compilation.errors.push(warning);
} else if (hints === "stats") {
compilation.hints.push(warning);
} else {
compilation.warnings.push(warning);
}
});
});
}
}
module.exports = DuplicateModulesPlugin;