webpack/lib/stats/DefaultStatsPresetPlugin.js

412 lines
12 KiB
JavaScript
Raw Normal View History

/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RequestShortener = require("../RequestShortener");
/** @typedef {import("../../declarations/WebpackOptions").StatsOptions} StatsOptions */
2025-04-07 21:09:05 +08:00
/** @typedef {import("../../declarations/WebpackOptions").StatsValue} StatsValue */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compilation").CreateStatsOptionsContext} CreateStatsOptionsContext */
2025-04-07 21:09:05 +08:00
/** @typedef {import("../Compilation").KnownNormalizedStatsOptions} KnownNormalizedStatsOptions */
/** @typedef {import("../Compilation").NormalizedStatsOptions} NormalizedStatsOptions */
/** @typedef {import("../Compiler")} Compiler */
2024-08-06 11:08:48 +08:00
/** @typedef {import("./DefaultStatsFactoryPlugin").StatsError} StatsError */
2024-08-06 11:08:48 +08:00
/**
2025-04-07 21:09:05 +08:00
* @param {Partial<NormalizedStatsOptions>} options options
2024-08-06 11:08:48 +08:00
* @param {StatsOptions} defaults default options
*/
const applyDefaults = (options, defaults) => {
2024-08-06 11:08:48 +08:00
for (const _k of Object.keys(defaults)) {
const key = /** @type {keyof StatsOptions} */ (_k);
if (typeof options[key] === "undefined") {
2025-04-07 21:09:05 +08:00
options[/** @type {keyof NormalizedStatsOptions} */ (key)] =
defaults[key];
}
}
};
2025-04-07 21:09:05 +08:00
/** @typedef {{ [Key in Exclude<StatsValue, boolean | object | "normal">]: StatsOptions }} NamedPresets */
2024-08-06 11:08:48 +08:00
/** @type {NamedPresets} */
const NAMED_PRESETS = {
verbose: {
hash: true,
builtAt: true,
relatedAssets: true,
entrypoints: true,
chunkGroups: true,
ids: true,
modules: false,
chunks: true,
2018-12-22 20:19:13 +08:00
chunkRelations: true,
chunkModules: true,
2020-09-02 00:08:09 +08:00
dependentModules: true,
chunkOrigins: true,
depth: true,
env: true,
reasons: true,
usedExports: true,
providedExports: true,
optimizationBailout: true,
errorDetails: true,
errorStack: true,
errorCause: true,
errorErrors: true,
publicPath: true,
2019-07-24 16:51:04 +08:00
logging: "verbose",
orphanModules: true,
runtimeModules: true,
exclude: false,
2022-02-27 18:55:47 +08:00
errorsSpace: Infinity,
warningsSpace: Infinity,
2020-09-02 00:08:09 +08:00
modulesSpace: Infinity,
chunkModulesSpace: Infinity,
assetsSpace: Infinity,
reasonsSpace: Infinity,
children: true
},
detailed: {
hash: true,
builtAt: true,
relatedAssets: true,
entrypoints: true,
chunkGroups: true,
ids: true,
chunks: true,
2018-12-22 20:19:13 +08:00
chunkRelations: true,
chunkModules: false,
chunkOrigins: true,
depth: true,
usedExports: true,
providedExports: true,
optimizationBailout: true,
errorDetails: true,
errorCause: true,
errorErrors: true,
publicPath: true,
2019-07-24 16:51:04 +08:00
logging: true,
runtimeModules: true,
exclude: false,
2022-02-27 18:55:47 +08:00
errorsSpace: 1000,
warningsSpace: 1000,
modulesSpace: 1000,
assetsSpace: 1000,
reasonsSpace: 1000
},
minimal: {
all: false,
version: true,
timings: true,
modules: true,
2022-02-27 18:55:47 +08:00
errorsSpace: 0,
warningsSpace: 0,
2020-09-02 00:08:09 +08:00
modulesSpace: 0,
assets: true,
assetsSpace: 0,
errors: true,
errorsCount: true,
2019-07-24 16:51:04 +08:00
warnings: true,
warningsCount: true,
2019-07-24 16:51:04 +08:00
logging: "warn"
},
"errors-only": {
all: false,
errors: true,
errorsCount: true,
2022-02-27 18:55:47 +08:00
errorsSpace: Infinity,
2019-07-24 16:51:04 +08:00
moduleTrace: true,
logging: "error"
},
2019-05-10 03:38:10 +08:00
"errors-warnings": {
all: false,
errors: true,
errorsCount: true,
2022-02-27 18:55:47 +08:00
errorsSpace: Infinity,
2019-07-24 16:51:04 +08:00
warnings: true,
warningsCount: true,
2022-02-27 18:55:47 +08:00
warningsSpace: Infinity,
2019-07-24 16:51:04 +08:00
logging: "warn"
2019-05-10 03:38:10 +08:00
},
summary: {
all: false,
version: true,
errorsCount: true,
warningsCount: true
},
none: {
all: false
}
};
2024-08-06 11:08:48 +08:00
/**
2025-07-18 20:28:16 +08:00
* @param {Partial<NormalizedStatsOptions>} all stats options
2024-08-06 11:08:48 +08:00
* @returns {boolean} true when enabled, otherwise false
*/
const NORMAL_ON = ({ all }) => all !== false;
2024-08-06 11:08:48 +08:00
/**
2025-07-18 20:28:16 +08:00
* @param {Partial<NormalizedStatsOptions>} all stats options
2024-08-06 11:08:48 +08:00
* @returns {boolean} true when enabled, otherwise false
*/
const NORMAL_OFF = ({ all }) => all === true;
2024-08-06 11:08:48 +08:00
/**
2025-07-18 20:28:16 +08:00
* @param {Partial<NormalizedStatsOptions>} all stats options
2024-08-06 11:08:48 +08:00
* @param {CreateStatsOptionsContext} forToString stats options context
* @returns {boolean} true when enabled, otherwise false
*/
2020-08-27 15:59:12 +08:00
const ON_FOR_TO_STRING = ({ all }, { forToString }) =>
forToString ? all !== false : all === true;
2024-08-06 11:08:48 +08:00
/**
2025-07-18 20:28:16 +08:00
* @param {Partial<NormalizedStatsOptions>} all stats options
2024-08-06 11:08:48 +08:00
* @param {CreateStatsOptionsContext} forToString stats options context
* @returns {boolean} true when enabled, otherwise false
*/
const OFF_FOR_TO_STRING = ({ all }, { forToString }) =>
forToString ? all === true : all !== false;
2024-08-06 11:08:48 +08:00
/**
2025-07-18 20:28:16 +08:00
* @param {Partial<NormalizedStatsOptions>} all stats options
2024-08-06 11:08:48 +08:00
* @param {CreateStatsOptionsContext} forToString stats options context
* @returns {boolean | "auto"} true when enabled, otherwise false
*/
const AUTO_FOR_TO_STRING = ({ all }, { forToString }) => {
if (all === false) return false;
if (all === true) return true;
if (forToString) return "auto";
return true;
};
2025-04-07 21:09:05 +08:00
/** @typedef {keyof NormalizedStatsOptions} DefaultsKeys */
/** @typedef {{ [Key in DefaultsKeys]: (options: Partial<NormalizedStatsOptions>, context: CreateStatsOptionsContext, compilation: Compilation) => NormalizedStatsOptions[Key] | RequestShortener }} Defaults */
2024-08-06 11:08:48 +08:00
2025-07-10 21:30:16 +08:00
/** @type {Defaults} */
const DEFAULTS = {
context: (options, context, compilation) => compilation.compiler.context,
requestShortener: (options, context, compilation) =>
compilation.compiler.context === options.context
? compilation.requestShortener
2024-08-06 11:08:48 +08:00
: new RequestShortener(
/** @type {string} */
(options.context),
compilation.compiler.root
),
performance: NORMAL_ON,
hash: OFF_FOR_TO_STRING,
env: NORMAL_OFF,
version: NORMAL_ON,
timings: NORMAL_ON,
builtAt: OFF_FOR_TO_STRING,
assets: NORMAL_ON,
entrypoints: AUTO_FOR_TO_STRING,
chunkGroups: OFF_FOR_TO_STRING,
chunkGroupAuxiliary: OFF_FOR_TO_STRING,
chunkGroupChildren: OFF_FOR_TO_STRING,
chunkGroupMaxAssets: (o, { forToString }) => (forToString ? 5 : Infinity),
chunks: OFF_FOR_TO_STRING,
2018-12-22 20:19:13 +08:00
chunkRelations: OFF_FOR_TO_STRING,
2020-09-02 20:09:29 +08:00
chunkModules: ({ all, modules }) => {
if (all === false) return false;
if (all === true) return true;
if (modules) return false;
return true;
},
2020-09-02 00:08:09 +08:00
dependentModules: OFF_FOR_TO_STRING,
chunkOrigins: OFF_FOR_TO_STRING,
ids: OFF_FOR_TO_STRING,
2020-09-02 00:08:09 +08:00
modules: ({ all, chunks, chunkModules }, { forToString }) => {
if (all === false) return false;
if (all === true) return true;
2020-09-02 00:08:09 +08:00
if (forToString && chunks && chunkModules) return false;
return true;
},
nestedModules: OFF_FOR_TO_STRING,
2020-09-02 00:08:09 +08:00
groupModulesByType: ON_FOR_TO_STRING,
groupModulesByCacheStatus: ON_FOR_TO_STRING,
groupModulesByLayer: ON_FOR_TO_STRING,
2020-09-02 00:08:09 +08:00
groupModulesByAttributes: ON_FOR_TO_STRING,
groupModulesByPath: ON_FOR_TO_STRING,
groupModulesByExtension: ON_FOR_TO_STRING,
modulesSpace: (o, { forToString }) => (forToString ? 15 : Infinity),
chunkModulesSpace: (o, { forToString }) => (forToString ? 10 : Infinity),
nestedModulesSpace: (o, { forToString }) => (forToString ? 10 : Infinity),
relatedAssets: OFF_FOR_TO_STRING,
groupAssetsByEmitStatus: ON_FOR_TO_STRING,
2020-08-27 15:59:12 +08:00
groupAssetsByInfo: ON_FOR_TO_STRING,
groupAssetsByPath: ON_FOR_TO_STRING,
groupAssetsByExtension: ON_FOR_TO_STRING,
groupAssetsByChunk: ON_FOR_TO_STRING,
assetsSpace: (o, { forToString }) => (forToString ? 15 : Infinity),
orphanModules: OFF_FOR_TO_STRING,
runtimeModules: ({ all, runtime }, { forToString }) =>
runtime !== undefined
? runtime
: forToString
2024-01-14 09:41:34 +08:00
? all === true
: all !== false,
cachedModules: ({ all, cached }, { forToString }) =>
2020-09-02 00:08:09 +08:00
cached !== undefined ? cached : forToString ? all === true : all !== false,
moduleAssets: OFF_FOR_TO_STRING,
depth: OFF_FOR_TO_STRING,
2019-07-25 21:42:42 +08:00
cachedAssets: OFF_FOR_TO_STRING,
reasons: OFF_FOR_TO_STRING,
reasonsSpace: (o, { forToString }) => (forToString ? 15 : Infinity),
groupReasonsByOrigin: ON_FOR_TO_STRING,
usedExports: OFF_FOR_TO_STRING,
providedExports: OFF_FOR_TO_STRING,
optimizationBailout: OFF_FOR_TO_STRING,
children: OFF_FOR_TO_STRING,
source: NORMAL_OFF,
moduleTrace: NORMAL_ON,
errors: NORMAL_ON,
errorsCount: NORMAL_ON,
errorDetails: AUTO_FOR_TO_STRING,
errorStack: OFF_FOR_TO_STRING,
errorCause: AUTO_FOR_TO_STRING,
errorErrors: AUTO_FOR_TO_STRING,
warnings: NORMAL_ON,
warningsCount: NORMAL_ON,
publicPath: OFF_FOR_TO_STRING,
2019-07-24 16:51:04 +08:00
logging: ({ all }, { forToString }) =>
2020-03-29 06:10:15 +08:00
forToString && all !== false ? "info" : false,
2019-07-24 16:51:04 +08:00
loggingDebug: () => [],
loggingTrace: OFF_FOR_TO_STRING,
excludeModules: () => [],
excludeAssets: () => [],
modulesSort: () => "depth",
chunkModulesSort: () => "name",
nestedModulesSort: () => false,
chunksSort: () => false,
assetsSort: () => "!size",
outputPath: OFF_FOR_TO_STRING,
colors: () => false
};
2024-08-06 11:08:48 +08:00
/**
2025-04-07 21:09:05 +08:00
* @template {string} T
* @param {string | ({ test: (value: T) => boolean }) | ((value: T, ...args: EXPECTED_ANY[]) => boolean) | boolean} item item to normalize
* @returns {(value: T, ...args: EXPECTED_ANY[]) => boolean} normalize fn
2024-08-06 11:08:48 +08:00
*/
const normalizeFilter = (item) => {
if (typeof item === "string") {
const regExp = new RegExp(
2024-01-13 21:28:53 +08:00
`[\\\\/]${item.replace(/[-[\]{}()*+?.\\^$|]/g, "\\$&")}([\\\\/]|$|!|\\?)`
);
return (ident) => regExp.test(/** @type {T} */ (ident));
}
if (item && typeof item === "object" && typeof item.test === "function") {
return (ident) => item.test(ident);
}
if (typeof item === "boolean") {
return () => item;
}
2025-04-07 21:09:05 +08:00
return /** @type {(value: T, ...args: EXPECTED_ANY[]) => boolean} */ (item);
};
2025-04-07 21:09:05 +08:00
/** @typedef {keyof (KnownNormalizedStatsOptions | StatsOptions)} NormalizerKeys */
2025-07-10 21:30:16 +08:00
/** @typedef {{ [Key in NormalizerKeys]?: (value: StatsOptions[Key]) => KnownNormalizedStatsOptions[Key] }} Normalizers */
2025-04-07 21:09:05 +08:00
2025-07-10 21:30:16 +08:00
/** @type {Normalizers} */
const NORMALIZER = {
excludeModules: (value) => {
if (!Array.isArray(value)) {
2025-04-07 21:09:05 +08:00
value = value
? /** @type {KnownNormalizedStatsOptions["excludeModules"]} */ ([value])
: [];
}
2019-07-24 16:51:04 +08:00
return value.map(normalizeFilter);
},
excludeAssets: (value) => {
if (!Array.isArray(value)) {
value = value ? [value] : [];
}
2019-07-24 16:51:04 +08:00
return value.map(normalizeFilter);
},
warningsFilter: (value) => {
if (!Array.isArray(value)) {
value = value ? [value] : [];
}
2024-08-06 11:08:48 +08:00
/**
* @callback WarningFilterFn
* @param {StatsError} warning warning
* @param {string} warningString warning string
* @returns {boolean} result
*/
return value.map(
/**
* @param {StatsOptions["warningsFilter"]} filter a warning filter
* @returns {WarningFilterFn} result
*/
(filter) => {
2024-08-06 11:08:48 +08:00
if (typeof filter === "string") {
return (warning, warningString) => warningString.includes(filter);
}
if (filter instanceof RegExp) {
return (warning, warningString) => filter.test(warningString);
}
if (typeof filter === "function") {
return filter;
}
throw new Error(
`Can only filter warnings with Strings or RegExps. (Given: ${filter})`
);
}
2024-08-06 11:08:48 +08:00
);
2019-07-24 16:51:04 +08:00
},
logging: (value) => {
2019-07-24 16:51:04 +08:00
if (value === true) value = "log";
2025-04-07 21:09:05 +08:00
return /** @type {KnownNormalizedStatsOptions["logging"]} */ (value);
2019-07-24 16:51:04 +08:00
},
loggingDebug: (value) => {
2019-07-24 16:51:04 +08:00
if (!Array.isArray(value)) {
2025-04-07 21:09:05 +08:00
value = value
? /** @type {KnownNormalizedStatsOptions["loggingDebug"]} */ ([value])
: [];
2019-07-24 16:51:04 +08:00
}
return value.map(normalizeFilter);
}
};
2025-04-23 20:03:37 +08:00
const PLUGIN_NAME = "DefaultStatsPresetPlugin";
class DefaultStatsPresetPlugin {
/**
2020-04-23 16:48:36 +08:00
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
for (const key of Object.keys(NAMED_PRESETS)) {
2024-08-06 11:08:48 +08:00
const defaults = NAMED_PRESETS[/** @type {keyof NamedPresets} */ (key)];
compilation.hooks.statsPreset
.for(key)
2025-07-08 22:46:17 +08:00
.tap(PLUGIN_NAME, (options, _context) => {
applyDefaults(options, defaults);
});
}
2025-04-23 20:03:37 +08:00
compilation.hooks.statsNormalize.tap(PLUGIN_NAME, (options, context) => {
for (const key of Object.keys(DEFAULTS)) {
if (options[key] === undefined) {
2025-07-10 21:30:16 +08:00
options[key] = DEFAULTS[/** @type {DefaultsKeys} */ (key)](
options,
context,
compilation
);
}
2025-04-23 20:03:37 +08:00
}
for (const key of Object.keys(NORMALIZER)) {
options[key] =
2025-07-10 21:30:16 +08:00
/** @type {NonNullable<Normalizers[keyof Normalizers]>} */
2025-04-23 20:03:37 +08:00
(NORMALIZER[/** @type {NormalizerKeys} */ (key)])(options[key]);
}
2025-04-23 20:03:37 +08:00
});
});
}
}
module.exports = DefaultStatsPresetPlugin;