| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Alexander Akait @alexander-akait
- */
- "use strict";
- const InlinedAssetsWarning = require("../errors/InlinedAssetsWarning");
- const { compareStrings } = require("../util/comparators");
- const getModuleSize = require("./getModuleSize");
- /** @import { AssetModuleBuildInfo } from "../asset/AssetModule" */
- /** @import { PerformanceOptions } from "../../declarations/WebpackOptions" */
- /** @import Compiler from "../Compiler" */
- /** @import { InlinedAssetDetails } from "../errors/InlinedAssetsWarning" */
- const PLUGIN_NAME = "InlinedAssetsPlugin";
- // Enough to name the offenders without listing every icon.
- const MAX_REPORTED_ASSETS = 5;
- // What the asset modules default `dataUrlCondition.maxSize` is: below it,
- // inlining saves a request for less than it costs in bytes.
- const DEFAULT_MAX_SIZE = 8096;
- class InlinedAssetsPlugin {
- /**
- * Creates an instance of InlinedAssetsPlugin.
- * @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) => {
- // `afterSeal` is past the hash, which folds every message into it — a
- // hint reported earlier would change the build's identity.
- compilation.hooks.afterSeal.tap(PLUGIN_NAME, () => {
- /** @type {InlinedAssetDetails[]} */
- const assets = [];
- let total = 0;
- for (const module of compilation.modules) {
- // The parser records whether it inlined, so this asks rather than
- // deciding from the module's type what it must have done.
- const buildInfo =
- /** @type {AssetModuleBuildInfo} */
- (module.buildInfo);
- if (!buildInfo.dataUrl) continue;
- // Module sizes are estimates and come back fractional.
- const size = Math.round(getModuleSize(module));
- if (size <= DEFAULT_MAX_SIZE) continue;
- total += size;
- assets.push({
- name: module.readableIdentifier(compilation.requestShortener),
- size
- });
- }
- if (assets.length === 0) return;
- // Largest first; ties break by name, module order is not stable.
- assets.sort(
- (a, b) => b.size - a.size || compareStrings(a.name, b.name)
- );
- const warning = new InlinedAssetsWarning(
- assets.slice(0, MAX_REPORTED_ASSETS),
- total
- );
- if (hints === "error") {
- compilation.errors.push(warning);
- } else if (hints === "stats") {
- compilation.hints.push(warning);
- } else {
- compilation.warnings.push(warning);
- }
- });
- });
- }
- }
- module.exports = InlinedAssetsPlugin;
|