webpack 5.108.4 → 5.109.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/webpack.js +12 -0
- package/lib/APIPlugin.js +48 -29
- package/lib/CacheFacade.js +8 -0
- package/lib/ChunkGraph.js +17 -15
- package/lib/ChunkGroup.js +1 -0
- package/lib/CompatibilityPlugin.js +62 -29
- package/lib/Compilation.js +58 -6
- package/lib/ConstPlugin.js +11 -11
- package/lib/ContextModule.js +239 -6
- package/lib/ContextModuleFactory.js +139 -14
- package/lib/DefinePlugin.js +433 -112
- package/lib/Entrypoint.js +1 -1
- package/lib/ExportsInfo.js +22 -5
- package/lib/ExportsInfoApiPlugin.js +2 -2
- package/lib/ExternalModule.js +107 -5
- package/lib/ExternalModuleFactoryPlugin.js +20 -1
- package/lib/FileSystemInfo.js +256 -100
- package/lib/FlagDependencyUsagePlugin.js +33 -12
- package/lib/HotModuleReplacementPlugin.js +18 -15
- package/lib/InitFragment.js +20 -32
- package/lib/Module.js +3 -0
- package/lib/ModuleFilenameHelpers.js +2 -2
- package/lib/ModuleTypeConstants.js +8 -1
- package/lib/MultiCompiler.js +13 -2
- package/lib/MultiWatching.js +1 -0
- package/lib/NodeStuffPlugin.js +51 -33
- package/lib/NormalModule.js +175 -401
- package/lib/NormalModuleFactory.js +76 -2
- package/lib/ProgressPlugin.js +211 -119
- package/lib/ProvidePlugin.js +2 -2
- package/lib/RuntimeGlobals.js +47 -0
- package/lib/RuntimePlugin.js +67 -107
- package/lib/RuntimeTemplate.js +304 -16
- package/lib/Template.js +23 -3
- package/lib/UseStrictPlugin.js +1 -1
- package/lib/WebpackIsIncludedPlugin.js +1 -1
- package/lib/WebpackOptionsApply.js +24 -19
- package/lib/asset/AssetGenerator.js +110 -28
- package/lib/asset/AssetModulesPlugin.js +92 -2
- package/lib/asset/WebManifestGenerator.js +164 -0
- package/lib/asset/WebManifestParser.js +130 -0
- package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
- package/lib/async-modules/isGeneratorLowered.js +26 -0
- package/lib/cache/PackFileCacheStrategy.js +9 -3
- package/lib/config/browserslistTargetHandler.js +40 -0
- package/lib/config/defaults.js +219 -29
- package/lib/config/normalization.js +26 -0
- package/lib/config/target.js +9 -1
- package/lib/container/HoistContainerReferencesPlugin.js +47 -55
- package/lib/css/CssGenerator.js +40 -31
- package/lib/css/CssLoadingRuntimeModule.js +5 -1
- package/lib/css/CssModulesPlugin.js +13 -0
- package/lib/css/CssParser.js +729 -313
- package/lib/css/syntax.js +1371 -861
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
- package/lib/dependencies/AMDPlugin.js +2 -2
- package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
- package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
- package/lib/dependencies/CommonJsExportRequireDependency.js +19 -0
- package/lib/dependencies/CommonJsExportsDependency.js +47 -2
- package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
- package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
- package/lib/dependencies/CommonJsPlugin.js +2 -2
- package/lib/dependencies/CommonJsRequireDependency.js +26 -1
- package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
- package/lib/dependencies/ContextDependencyHelpers.js +3 -3
- package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
- package/lib/dependencies/CssIcssExportDependency.js +162 -71
- package/lib/dependencies/CssUrlDependency.js +35 -4
- package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
- package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
- package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +2 -1
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +17 -9
- package/lib/dependencies/HarmonyImportDependency.js +13 -2
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +11 -11
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -7
- package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
- package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
- package/lib/dependencies/HtmlEntryDependency.js +797 -172
- package/lib/dependencies/HtmlSourceDependency.js +26 -0
- package/lib/dependencies/ImportDependency.js +43 -1
- package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
- package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
- package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
- package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
- package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
- package/lib/dependencies/ImportMetaPlugin.js +532 -180
- package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
- package/lib/dependencies/ImportParserPlugin.js +80 -17
- package/lib/dependencies/ImportPhase.js +10 -8
- package/lib/dependencies/LoaderPlugin.js +5 -1
- package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
- package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
- package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
- package/lib/dependencies/SystemPlugin.js +2 -4
- package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
- package/lib/dependencies/URLDependency.js +141 -21
- package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
- package/lib/dependencies/WorkerDependency.js +86 -18
- package/lib/dependencies/WorkletDependency.js +278 -0
- package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
- package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
- package/lib/errors/LoaderLoadingError.js +20 -0
- package/lib/errors/ModuleParseError.js +39 -22
- package/lib/errors/NodeStuffInWebError.js +1 -1
- package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
- package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
- package/lib/hmr/lazyCompilationBackend.js +51 -12
- package/lib/html/HtmlGenerator.js +907 -15
- package/lib/html/HtmlModule.js +2 -2
- package/lib/html/HtmlModulesPlugin.js +610 -166
- package/lib/html/HtmlParser.js +603 -247
- package/lib/html/favicon.svg +1 -0
- package/lib/html/syntax.js +3451 -2762
- package/lib/ids/IdHelpers.js +25 -11
- package/lib/index.js +6 -0
- package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
- package/lib/javascript/BasicEvaluatedExpression.js +366 -48
- package/lib/javascript/JavascriptGenerator.js +197 -49
- package/lib/javascript/JavascriptModulesPlugin.js +178 -24
- package/lib/javascript/JavascriptParser.js +704 -355
- package/lib/javascript/JavascriptParserHelpers.js +3 -6
- package/lib/javascript/syntax.js +5037 -0
- package/lib/library/ModuleLibraryPlugin.js +38 -1
- package/lib/loaders/LoaderRunner.js +714 -0
- package/lib/loaders/loadLoader.js +100 -0
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +29 -2
- package/lib/node/ReadFileCompileWasmPlugin.js +24 -2
- package/lib/optimize/AggressiveMergingPlugin.js +19 -15
- package/lib/optimize/ConcatenatedModule.js +139 -31
- package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
- package/lib/optimize/InnerGraphPlugin.js +50 -30
- package/lib/optimize/ModuleConcatenationPlugin.js +139 -24
- package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
- package/lib/optimize/SplitChunksPlugin.js +146 -44
- package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
- package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
- package/lib/prefetch/ResourceHintPlugin.js +687 -0
- package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
- package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
- package/lib/prefetch/parseResourceHintOptions.js +103 -0
- package/lib/rules/RuleSetCompiler.js +114 -0
- package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
- package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
- package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
- package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
- package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
- package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
- package/lib/schemes/HttpUriPlugin.js +40 -1
- package/lib/schemes/VirtualUrlPlugin.js +1 -2
- package/lib/serialization/BinaryMiddleware.js +270 -938
- package/lib/serialization/FileMiddleware.js +29 -3
- package/lib/stats/DefaultStatsFactoryPlugin.js +229 -194
- package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
- package/lib/stats/DefaultStatsPrinterPlugin.js +36 -168
- package/lib/stats/StatsFactory.js +46 -17
- package/lib/url/URLParserPlugin.js +66 -13
- package/lib/util/AsyncQueue.js +122 -72
- package/lib/util/SetHelpers.js +1 -1
- package/lib/util/StackedMap.js +122 -48
- package/lib/util/binarySearchBounds.js +2 -2
- package/lib/util/concatenate.js +40 -14
- package/lib/util/createHooksRegistry.js +13 -5
- package/lib/util/dataURL.js +2 -2
- package/lib/util/deterministicGrouping.js +7 -5
- package/lib/util/formatSize.js +6 -2
- package/lib/util/globUtils.js +710 -0
- package/lib/util/identifier.js +23 -6
- package/lib/util/implicitTypeLoaderFallback.js +62 -0
- package/lib/util/internalSerializables.js +88 -71
- package/lib/util/magicComment.js +121 -25
- package/lib/util/numberHash.js +2 -2
- package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
- package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
- package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
- package/lib/web/FetchCompileWasmPlugin.js +14 -0
- package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
- package/lib/webpack.js +65 -0
- package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
- package/module.d.ts +21 -0
- package/package.json +12 -11
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +759 -36
- package/schemas/plugins/HtmlParserOptions.check.js +1 -1
- package/schemas/plugins/ProgressPlugin.check.js +1 -1
- package/schemas/plugins/ProgressPlugin.json +17 -1
- package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
- package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
- package/schemas/plugins/container/ExternalsType.check.js +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
- package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssParserOptions.check.js +1 -1
- package/types.d.ts +1212 -99
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
|
-
const { getContext } = require("loader-runner");
|
|
9
8
|
const asyncLib = require("neo-async");
|
|
10
9
|
const {
|
|
11
10
|
AsyncSeriesBailHook,
|
|
@@ -21,6 +20,7 @@ const ModuleGraph = require("./ModuleGraph");
|
|
|
21
20
|
const { JAVASCRIPT_MODULE_TYPE_AUTO } = require("./ModuleTypeConstants");
|
|
22
21
|
const NormalModule = require("./NormalModule");
|
|
23
22
|
const { ImportPhaseUtils } = require("./dependencies/ImportPhase");
|
|
23
|
+
const { getContext } = require("./loaders/LoaderRunner");
|
|
24
24
|
const BasicEffectRulePlugin = require("./rules/BasicEffectRulePlugin");
|
|
25
25
|
const BasicMatcherRulePlugin = require("./rules/BasicMatcherRulePlugin");
|
|
26
26
|
const ObjectMatcherRulePlugin = require("./rules/ObjectMatcherRulePlugin");
|
|
@@ -118,6 +118,19 @@ const {
|
|
|
118
118
|
* @property {string | undefined} options options
|
|
119
119
|
*/
|
|
120
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Dependencies captured while resolving a loader.
|
|
123
|
+
* @typedef {object} ResolveDependencies
|
|
124
|
+
* @property {LazySet<string>} fileDependencies file dependencies of the resolve
|
|
125
|
+
* @property {LazySet<string>} contextDependencies context dependencies of the resolve
|
|
126
|
+
* @property {LazySet<string>} missingDependencies missing dependencies of the resolve
|
|
127
|
+
*/
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Memoized result of resolving a loader for a given (context, request).
|
|
131
|
+
* @typedef {ResolveDependencies & { loader: string, query: string | undefined, type: string | undefined }} LoaderResolveCacheEntry
|
|
132
|
+
*/
|
|
133
|
+
|
|
121
134
|
/** @typedef {import("./ModuleTypeConstants").JAVASCRIPT_MODULE_TYPE_AUTO} JAVASCRIPT_MODULE_TYPE_AUTO */
|
|
122
135
|
/** @typedef {import("./ModuleTypeConstants").JAVASCRIPT_MODULE_TYPE_DYNAMIC} JAVASCRIPT_MODULE_TYPE_DYNAMIC */
|
|
123
136
|
/** @typedef {import("./ModuleTypeConstants").JAVASCRIPT_MODULE_TYPE_ESM} JAVASCRIPT_MODULE_TYPE_ESM */
|
|
@@ -149,6 +162,25 @@ const EMPTY_ELEMENTS = [];
|
|
|
149
162
|
const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;
|
|
150
163
|
const LEADING_DOT_EXTENSION_REGEX = /^[^.]/;
|
|
151
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Replays the file/context/missing dependencies captured by a loader resolve
|
|
167
|
+
* into a resolve context, so memoized loaders still record everything needed
|
|
168
|
+
* for watch invalidation.
|
|
169
|
+
* @param {ResolveContext} resolveContext resolve context to add dependencies to
|
|
170
|
+
* @param {ResolveDependencies} source captured resolve dependencies
|
|
171
|
+
* @returns {void}
|
|
172
|
+
*/
|
|
173
|
+
const replayResolveDependencies = (resolveContext, source) => {
|
|
174
|
+
// On this path resolveContext always carries the three LazySet dependency
|
|
175
|
+
// sets built in the `resolve` hook, so they are safe to treat as LazySet.
|
|
176
|
+
/** @type {LazySet<string>} */
|
|
177
|
+
(resolveContext.fileDependencies).addAll(source.fileDependencies);
|
|
178
|
+
/** @type {LazySet<string>} */
|
|
179
|
+
(resolveContext.contextDependencies).addAll(source.contextDependencies);
|
|
180
|
+
/** @type {LazySet<string>} */
|
|
181
|
+
(resolveContext.missingDependencies).addAll(source.missingDependencies);
|
|
182
|
+
};
|
|
183
|
+
|
|
152
184
|
/**
|
|
153
185
|
* Returns ident.
|
|
154
186
|
* @param {LoaderItem} data data
|
|
@@ -457,6 +489,8 @@ class NormalModuleFactory extends ModuleFactory {
|
|
|
457
489
|
this.generatorCache = new Map();
|
|
458
490
|
/** @type {Set<Module>} */
|
|
459
491
|
this._restoredUnsafeCacheEntries = new Set();
|
|
492
|
+
/** @type {Map<string, LoaderResolveCacheEntry>} */
|
|
493
|
+
this._loaderResolveCache = new Map();
|
|
460
494
|
|
|
461
495
|
/** @type {(resource: string) => import("./util/identifier").ParsedResource} */
|
|
462
496
|
const cacheParseResource = parseResource.bindCache(
|
|
@@ -1336,14 +1370,44 @@ If changing the source code is not an option there is also a resolve options cal
|
|
|
1336
1370
|
* Handles the callback logic for this hook.
|
|
1337
1371
|
* @param {LoaderItem} item item
|
|
1338
1372
|
* @param {Callback<LoaderItem>} callback callback
|
|
1373
|
+
* @returns {void}
|
|
1339
1374
|
*/
|
|
1340
1375
|
(item, callback) => {
|
|
1376
|
+
// Loaders resolve identically for a given (context, request), so memoize
|
|
1377
|
+
// the result and the resolve's dependencies to skip repeated resolves.
|
|
1378
|
+
const cacheKey = `${context}\n${item.loader}`;
|
|
1379
|
+
const cached = this._loaderResolveCache.get(cacheKey);
|
|
1380
|
+
if (cached !== undefined) {
|
|
1381
|
+
replayResolveDependencies(resolveContext, cached);
|
|
1382
|
+
return callback(null, {
|
|
1383
|
+
loader: cached.loader,
|
|
1384
|
+
type: cached.type,
|
|
1385
|
+
options:
|
|
1386
|
+
item.options === undefined
|
|
1387
|
+
? cached.query
|
|
1388
|
+
? cached.query.slice(1)
|
|
1389
|
+
: undefined
|
|
1390
|
+
: item.options,
|
|
1391
|
+
ident: item.options === undefined ? undefined : item.ident
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
// Capture this resolve's dependencies in dedicated sets so a future hit
|
|
1395
|
+
// can replay them; also feed them back into the caller's resolveContext.
|
|
1396
|
+
const captureContext = {
|
|
1397
|
+
...resolveContext,
|
|
1398
|
+
fileDependencies: new LazySet(),
|
|
1399
|
+
contextDependencies: new LazySet(),
|
|
1400
|
+
missingDependencies: new LazySet()
|
|
1401
|
+
};
|
|
1341
1402
|
resolver.resolve(
|
|
1342
1403
|
contextInfo,
|
|
1343
1404
|
context,
|
|
1344
1405
|
item.loader,
|
|
1345
|
-
|
|
1406
|
+
captureContext,
|
|
1346
1407
|
(err, result, resolveRequest) => {
|
|
1408
|
+
// Merge the captured dependencies back so a failed or successful
|
|
1409
|
+
// resolve records them for watch invalidation just like before.
|
|
1410
|
+
replayResolveDependencies(resolveContext, captureContext);
|
|
1347
1411
|
if (
|
|
1348
1412
|
err &&
|
|
1349
1413
|
/^[^/]*$/.test(item.loader) &&
|
|
@@ -1385,6 +1449,16 @@ If changing the source code is not an option there is also a resolve options cal
|
|
|
1385
1449
|
/** @type {ResolveRequest} */
|
|
1386
1450
|
(resolveRequest).descriptionFileData.type
|
|
1387
1451
|
);
|
|
1452
|
+
|
|
1453
|
+
this._loaderResolveCache.set(cacheKey, {
|
|
1454
|
+
loader: parsedResult.path,
|
|
1455
|
+
query: parsedResult.query,
|
|
1456
|
+
type,
|
|
1457
|
+
fileDependencies: captureContext.fileDependencies,
|
|
1458
|
+
contextDependencies: captureContext.contextDependencies,
|
|
1459
|
+
missingDependencies: captureContext.missingDependencies
|
|
1460
|
+
});
|
|
1461
|
+
|
|
1388
1462
|
/** @type {LoaderItem} */
|
|
1389
1463
|
const resolved = {
|
|
1390
1464
|
loader: parsedResult.path,
|
package/lib/ProgressPlugin.js
CHANGED
|
@@ -29,27 +29,12 @@ const BULLET_ICON = "●";
|
|
|
29
29
|
*/
|
|
30
30
|
/** @typedef {import("../declarations/plugins/ProgressPlugin").ProgressPluginArgument} ProgressPluginArgument */
|
|
31
31
|
/** @typedef {import("../declarations/plugins/ProgressPlugin").ProgressPluginOptions} ProgressPluginOptions */
|
|
32
|
-
/** @typedef {import("./Compilation").FactorizeModuleOptions} FactorizeModuleOptions */
|
|
33
32
|
/** @typedef {import("./Dependency")} Dependency */
|
|
34
33
|
/** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */
|
|
35
34
|
/** @typedef {import("./Module")} Module */
|
|
36
|
-
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
|
|
37
35
|
/** @typedef {import("./logging/Logger").Logger} Logger */
|
|
38
36
|
/** @typedef {import("./cli").Colors} Colors */
|
|
39
37
|
|
|
40
|
-
/**
|
|
41
|
-
* Defines the async queue type used by this module.
|
|
42
|
-
* @template T, K, R
|
|
43
|
-
* @typedef {import("./util/AsyncQueue")<T, K, R>} AsyncQueue
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Defines the counts data type used by this module.
|
|
48
|
-
* @typedef {object} CountsData
|
|
49
|
-
* @property {number} modulesCount modules count
|
|
50
|
-
* @property {number} dependenciesCount dependencies count
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
38
|
/**
|
|
54
39
|
* Returns median.
|
|
55
40
|
* @param {number} a a
|
|
@@ -125,37 +110,110 @@ const reportProfile = (logger, lastStateInfo, percentage, msg, args) => {
|
|
|
125
110
|
}
|
|
126
111
|
};
|
|
127
112
|
|
|
113
|
+
/**
|
|
114
|
+
* @param {number} ms milliseconds
|
|
115
|
+
* @returns {string} human readable duration
|
|
116
|
+
*/
|
|
117
|
+
const formatTime = (ms) => {
|
|
118
|
+
if (ms < 1000) return `${Math.round(ms)}ms`;
|
|
119
|
+
const seconds = Math.floor(ms / 1000);
|
|
120
|
+
if (seconds < 60) return `${seconds}s`;
|
|
121
|
+
const minutes = Math.floor(seconds / 60);
|
|
122
|
+
if (minutes < 60) return `${minutes}m ${seconds % 60}s`;
|
|
123
|
+
const hours = Math.floor(minutes / 60);
|
|
124
|
+
return `${hours}h ${minutes % 60}m`;
|
|
125
|
+
};
|
|
126
|
+
|
|
128
127
|
/**
|
|
129
128
|
* @param {string} name progress bar name
|
|
130
129
|
* @param {string} color progress bar color
|
|
130
|
+
* @param {number} width progress bar width in characters
|
|
131
131
|
* @returns {(percentage: number) => string} bar renderer
|
|
132
132
|
*/
|
|
133
|
-
const createReportBar = (name, color) => {
|
|
133
|
+
const createReportBar = (name, color, width) => {
|
|
134
134
|
const c = getColors();
|
|
135
|
+
const colorFn = color in c ? c[/** @type {keyof Colors} */ (color)] : c.green;
|
|
136
|
+
// The bar only changes when the filled width does, so cache it between steps.
|
|
137
|
+
let lastFilled = -1;
|
|
138
|
+
let lastBar = "";
|
|
135
139
|
|
|
136
140
|
return (percentage) => {
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
const filled = Math.round(percentage * width);
|
|
142
|
+
if (filled === lastFilled) return lastBar;
|
|
143
|
+
lastFilled = filled;
|
|
144
|
+
const filledStr = BLOCK_CHAR.repeat(filled);
|
|
145
|
+
const emptyStr = BLOCK_CHAR.repeat(width - filled);
|
|
146
|
+
lastBar = `${[BULLET_ICON, name, filledStr].map(colorFn).join(" ")}${c.white(
|
|
147
|
+
emptyStr
|
|
148
|
+
)}`;
|
|
149
|
+
return lastBar;
|
|
144
150
|
};
|
|
145
151
|
};
|
|
146
152
|
|
|
147
|
-
/** @typedef {Required<Exclude<NonNullable<ProgressPluginOptions["progressBar"]>, boolean>>} ProgressBarOptions */
|
|
153
|
+
/** @typedef {Required<Exclude<NonNullable<ProgressPluginOptions["progressBar"]>, boolean | "auto">>} ProgressBarOptions */
|
|
154
|
+
|
|
155
|
+
/** @type {ProgressBarOptions} */
|
|
156
|
+
const DEFAULT_PROGRESS_BAR = {
|
|
157
|
+
name: "Build",
|
|
158
|
+
color: "green",
|
|
159
|
+
width: BAR_LENGTH
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/** @typedef {{ progressBar?: ProgressBarOptions | false, estimatedTime?: boolean, phaseTimings?: boolean }} DefaultHandlerOptions */
|
|
148
163
|
|
|
149
164
|
/**
|
|
150
165
|
* Creates a default handler.
|
|
151
166
|
* @param {boolean | null | undefined} profile need profile
|
|
152
167
|
* @param {Logger} logger logger
|
|
153
|
-
* @param {
|
|
168
|
+
* @param {DefaultHandlerOptions=} options display options
|
|
154
169
|
* @returns {HandlerFn} default handler
|
|
155
170
|
*/
|
|
156
|
-
const createDefaultHandler = (profile, logger,
|
|
171
|
+
const createDefaultHandler = (profile, logger, options = {}) => {
|
|
172
|
+
const {
|
|
173
|
+
progressBar = false,
|
|
174
|
+
estimatedTime = false,
|
|
175
|
+
phaseTimings = false
|
|
176
|
+
} = options;
|
|
177
|
+
const trackTime = estimatedTime || phaseTimings;
|
|
178
|
+
|
|
157
179
|
/** @type {{ value: string | undefined, time: number }[]} */
|
|
158
180
|
const lastStateInfo = [];
|
|
181
|
+
let buildStart = 0;
|
|
182
|
+
// Exponential moving average of the estimated total build time (0 = unset).
|
|
183
|
+
let smoothedTotal = 0;
|
|
184
|
+
/** @type {Map<string, number>} accumulated ms per phase (msg) */
|
|
185
|
+
const phaseTimes = new Map();
|
|
186
|
+
/** @type {string | undefined} */
|
|
187
|
+
let currentPhase;
|
|
188
|
+
let currentPhaseStart = 0;
|
|
189
|
+
let summaryReported = false;
|
|
190
|
+
/** @type {((percentage: number) => string) | undefined} */
|
|
191
|
+
let reportBar;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @param {number} now current timestamp
|
|
195
|
+
* @returns {void}
|
|
196
|
+
*/
|
|
197
|
+
const reportPhaseSummary = (now) => {
|
|
198
|
+
if (!phaseTimings || summaryReported || phaseTimes.size === 0) return;
|
|
199
|
+
summaryReported = true;
|
|
200
|
+
// Flush the phase still running at completion.
|
|
201
|
+
if (currentPhase !== undefined) {
|
|
202
|
+
phaseTimes.set(
|
|
203
|
+
currentPhase,
|
|
204
|
+
(phaseTimes.get(currentPhase) || 0) + (now - currentPhaseStart)
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const total = now - buildStart;
|
|
208
|
+
logger.info(`Build completed in ${formatTime(total)}`);
|
|
209
|
+
logger.info("Phase breakdown:");
|
|
210
|
+
for (const [phase, duration] of phaseTimes) {
|
|
211
|
+
if (duration > 0) {
|
|
212
|
+
const percent = total > 0 ? Math.round((duration / total) * 100) : 0;
|
|
213
|
+
logger.info(` ${phase}: ${formatTime(duration)} (${percent}%)`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
};
|
|
159
217
|
|
|
160
218
|
/** @type {HandlerFn} */
|
|
161
219
|
const defaultHandler = (percentage, msg, ...args) => {
|
|
@@ -163,34 +221,84 @@ const createDefaultHandler = (profile, logger, progressBar) => {
|
|
|
163
221
|
reportProfile(logger, lastStateInfo, percentage, msg, args);
|
|
164
222
|
}
|
|
165
223
|
|
|
224
|
+
const now = trackTime ? Date.now() : 0;
|
|
225
|
+
|
|
226
|
+
if (trackTime && percentage === 0) {
|
|
227
|
+
buildStart = now;
|
|
228
|
+
smoothedTotal = 0;
|
|
229
|
+
summaryReported = false;
|
|
230
|
+
phaseTimes.clear();
|
|
231
|
+
currentPhase = undefined;
|
|
232
|
+
currentPhaseStart = now;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Accumulate time under the previous phase whenever the top-level message changes.
|
|
236
|
+
if (phaseTimings && msg && msg !== currentPhase) {
|
|
237
|
+
if (currentPhase !== undefined) {
|
|
238
|
+
phaseTimes.set(
|
|
239
|
+
currentPhase,
|
|
240
|
+
(phaseTimes.get(currentPhase) || 0) + (now - currentPhaseStart)
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
currentPhase = msg;
|
|
244
|
+
currentPhaseStart = now;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** @type {string | undefined} */
|
|
248
|
+
let eta;
|
|
249
|
+
if (estimatedTime && percentage > 0.05 && percentage < 1) {
|
|
250
|
+
const elapsed = now - buildStart;
|
|
251
|
+
const rawTotal = elapsed / percentage;
|
|
252
|
+
smoothedTotal =
|
|
253
|
+
smoothedTotal > 0 ? smoothedTotal * 0.7 + rawTotal * 0.3 : rawTotal;
|
|
254
|
+
const remaining = smoothedTotal - elapsed;
|
|
255
|
+
if (remaining > 0) eta = `ETA: ${formatTime(remaining)}`;
|
|
256
|
+
}
|
|
257
|
+
|
|
166
258
|
if (progressBar) {
|
|
167
|
-
|
|
259
|
+
// Build the bar renderer once, then reuse it across every step.
|
|
260
|
+
if (reportBar === undefined) {
|
|
261
|
+
reportBar = createReportBar(
|
|
262
|
+
progressBar.name,
|
|
263
|
+
progressBar.color,
|
|
264
|
+
progressBar.width
|
|
265
|
+
);
|
|
266
|
+
}
|
|
168
267
|
const c = getColors();
|
|
169
268
|
/** @type {string} */
|
|
170
269
|
const currentBar = reportBar(percentage);
|
|
270
|
+
const suffix = eta ? ` ${eta}` : "";
|
|
171
271
|
|
|
172
272
|
if (percentage === 1) {
|
|
173
273
|
logger.status();
|
|
274
|
+
reportPhaseSummary(now);
|
|
174
275
|
} else if (msg) {
|
|
175
276
|
logger.status(
|
|
176
|
-
`${currentBar} (${Math.floor(percentage * 100)}%)`,
|
|
277
|
+
`${currentBar} (${Math.floor(percentage * 100)}%)${suffix}`,
|
|
177
278
|
`\n${[msg, ...args].map(c.gray).join(" ")}`
|
|
178
279
|
);
|
|
179
280
|
} else {
|
|
180
|
-
logger.status(
|
|
281
|
+
logger.status(
|
|
282
|
+
`${currentBar} (${Math.floor(percentage * 100)}%)${suffix}`
|
|
283
|
+
);
|
|
181
284
|
}
|
|
182
285
|
return;
|
|
183
286
|
}
|
|
184
287
|
|
|
185
|
-
|
|
186
|
-
|
|
288
|
+
if (eta) {
|
|
289
|
+
logger.status(`${Math.floor(percentage * 100)}%`, msg, ...args, eta);
|
|
290
|
+
} else {
|
|
291
|
+
logger.status(`${Math.floor(percentage * 100)}%`, msg, ...args);
|
|
292
|
+
}
|
|
293
|
+
if (percentage === 1 || (!msg && args.length === 0)) {
|
|
294
|
+
if (percentage === 1) reportPhaseSummary(now);
|
|
295
|
+
logger.status();
|
|
296
|
+
}
|
|
187
297
|
};
|
|
188
298
|
|
|
189
299
|
return defaultHandler;
|
|
190
300
|
};
|
|
191
301
|
|
|
192
|
-
const SKIPPED_QUEUE_CONTEXTS = ["import-module", "load-module"];
|
|
193
|
-
|
|
194
302
|
/**
|
|
195
303
|
* Defines the report progress callback.
|
|
196
304
|
* @callback ReportProgress
|
|
@@ -214,7 +322,34 @@ const DEFAULT_OPTIONS = {
|
|
|
214
322
|
activeModules: false,
|
|
215
323
|
entries: true,
|
|
216
324
|
percentBy: null,
|
|
217
|
-
progressBar: false
|
|
325
|
+
progressBar: false,
|
|
326
|
+
estimatedTime: false,
|
|
327
|
+
phaseTimings: false
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Whether progress can be rendered in place (interactive TTY). The bar is only
|
|
332
|
+
* useful here; in append-only output every update becomes a new line.
|
|
333
|
+
* @param {Compiler | MultiCompiler} compiler compiler
|
|
334
|
+
* @returns {boolean} true when output is an interactive terminal
|
|
335
|
+
*/
|
|
336
|
+
const isInteractive = (compiler) => {
|
|
337
|
+
const c =
|
|
338
|
+
compiler instanceof MultiCompiler ? compiler.compilers[0] : compiler;
|
|
339
|
+
const infrastructureLogging =
|
|
340
|
+
c && c.options && c.options.infrastructureLogging;
|
|
341
|
+
if (
|
|
342
|
+
infrastructureLogging &&
|
|
343
|
+
typeof infrastructureLogging.appendOnly === "boolean"
|
|
344
|
+
) {
|
|
345
|
+
return !infrastructureLogging.appendOnly;
|
|
346
|
+
}
|
|
347
|
+
const stream =
|
|
348
|
+
(infrastructureLogging && infrastructureLogging.stream) || process.stderr;
|
|
349
|
+
return (
|
|
350
|
+
Boolean(/** @type {NodeJS.WriteStream} */ (stream).isTTY) &&
|
|
351
|
+
process.env.TERM !== "dumb"
|
|
352
|
+
);
|
|
218
353
|
};
|
|
219
354
|
|
|
220
355
|
class ProgressPlugin {
|
|
@@ -260,11 +395,21 @@ class ProgressPlugin {
|
|
|
260
395
|
this.showActiveModules = merged.activeModules;
|
|
261
396
|
this.percentBy = merged.percentBy;
|
|
262
397
|
|
|
263
|
-
const progressBar = merged.progressBar
|
|
264
|
-
/** @type {ProgressBarOptions | false} */
|
|
265
|
-
this.progressBar =
|
|
266
|
-
|
|
267
|
-
|
|
398
|
+
const progressBar = merged.progressBar;
|
|
399
|
+
/** @type {ProgressBarOptions | false | "auto"} */
|
|
400
|
+
this.progressBar =
|
|
401
|
+
progressBar === "auto"
|
|
402
|
+
? "auto"
|
|
403
|
+
: progressBar
|
|
404
|
+
? {
|
|
405
|
+
...DEFAULT_PROGRESS_BAR,
|
|
406
|
+
...(progressBar === true ? {} : progressBar)
|
|
407
|
+
}
|
|
408
|
+
: false;
|
|
409
|
+
/** @type {boolean} */
|
|
410
|
+
this.estimatedTime = merged.estimatedTime;
|
|
411
|
+
/** @type {boolean} */
|
|
412
|
+
this.phaseTimings = merged.phaseTimings;
|
|
268
413
|
}
|
|
269
414
|
|
|
270
415
|
/**
|
|
@@ -273,12 +418,31 @@ class ProgressPlugin {
|
|
|
273
418
|
* @returns {void}
|
|
274
419
|
*/
|
|
275
420
|
apply(compiler) {
|
|
421
|
+
let progressBar = this.progressBar;
|
|
422
|
+
// webpack@6 (opt-in today via `experiments.futureDefaults`) turns an unset
|
|
423
|
+
// progressBar into the auto bar; an explicit `false` is still respected.
|
|
424
|
+
if (progressBar === false && this.options.progressBar === undefined) {
|
|
425
|
+
const c =
|
|
426
|
+
compiler instanceof MultiCompiler ? compiler.compilers[0] : compiler;
|
|
427
|
+
if (c && c.options && c.options.experiments.futureDefaults) {
|
|
428
|
+
progressBar = "auto";
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (progressBar === "auto") {
|
|
432
|
+
progressBar = isInteractive(compiler)
|
|
433
|
+
? { ...DEFAULT_PROGRESS_BAR }
|
|
434
|
+
: false;
|
|
435
|
+
}
|
|
276
436
|
const handler =
|
|
277
437
|
this.handler ||
|
|
278
438
|
createDefaultHandler(
|
|
279
439
|
this.profile,
|
|
280
440
|
compiler.getInfrastructureLogger("webpack.Progress"),
|
|
281
|
-
|
|
441
|
+
{
|
|
442
|
+
progressBar,
|
|
443
|
+
estimatedTime: this.estimatedTime,
|
|
444
|
+
phaseTimings: this.phaseTimings
|
|
445
|
+
}
|
|
282
446
|
);
|
|
283
447
|
if (compiler instanceof MultiCompiler) {
|
|
284
448
|
this._applyOnMultiCompiler(compiler, handler);
|
|
@@ -336,9 +500,7 @@ class ProgressPlugin {
|
|
|
336
500
|
let lastDependenciesCount = 0;
|
|
337
501
|
let lastEntriesCount = 0;
|
|
338
502
|
let modulesCount = 0;
|
|
339
|
-
let skippedModulesCount = 0;
|
|
340
503
|
let dependenciesCount = 0;
|
|
341
|
-
let skippedDependenciesCount = 0;
|
|
342
504
|
let entriesCount = 1;
|
|
343
505
|
let doneModules = 0;
|
|
344
506
|
let doneDependencies = 0;
|
|
@@ -422,16 +584,7 @@ class ProgressPlugin {
|
|
|
422
584
|
lastUpdate = Date.now();
|
|
423
585
|
};
|
|
424
586
|
|
|
425
|
-
|
|
426
|
-
* Processes the provided factorize queue.
|
|
427
|
-
* @template T
|
|
428
|
-
* @param {AsyncQueue<FactorizeModuleOptions, string, Module | ModuleFactoryResult>} factorizeQueue async queue
|
|
429
|
-
* @param {T} _item item
|
|
430
|
-
*/
|
|
431
|
-
const factorizeAdd = (factorizeQueue, _item) => {
|
|
432
|
-
if (SKIPPED_QUEUE_CONTEXTS.includes(factorizeQueue.getContext())) {
|
|
433
|
-
skippedDependenciesCount++;
|
|
434
|
-
}
|
|
587
|
+
const factorizeAdd = () => {
|
|
435
588
|
dependenciesCount++;
|
|
436
589
|
if (dependenciesCount < 50 || dependenciesCount % 100 === 0) {
|
|
437
590
|
updateThrottled();
|
|
@@ -445,16 +598,7 @@ class ProgressPlugin {
|
|
|
445
598
|
}
|
|
446
599
|
};
|
|
447
600
|
|
|
448
|
-
|
|
449
|
-
* Processes the provided add module queue.
|
|
450
|
-
* @template T
|
|
451
|
-
* @param {AsyncQueue<Module, string, Module>} addModuleQueue async queue
|
|
452
|
-
* @param {T} _item item
|
|
453
|
-
*/
|
|
454
|
-
const moduleAdd = (addModuleQueue, _item) => {
|
|
455
|
-
if (SKIPPED_QUEUE_CONTEXTS.includes(addModuleQueue.getContext())) {
|
|
456
|
-
skippedModulesCount++;
|
|
457
|
-
}
|
|
601
|
+
const moduleAdd = () => {
|
|
458
602
|
modulesCount++;
|
|
459
603
|
if (modulesCount < 50 || modulesCount % 100 === 0) updateThrottled();
|
|
460
604
|
};
|
|
@@ -516,72 +660,20 @@ class ProgressPlugin {
|
|
|
516
660
|
update();
|
|
517
661
|
};
|
|
518
662
|
|
|
519
|
-
const cache = compiler.getCache(PLUGIN_NAME).getItemCache("counts", null);
|
|
520
|
-
|
|
521
|
-
/** @type {Promise<CountsData> | undefined} */
|
|
522
|
-
let cacheGetPromise;
|
|
523
|
-
|
|
524
|
-
compiler.hooks.beforeCompile.tap(PLUGIN_NAME, () => {
|
|
525
|
-
if (!cacheGetPromise) {
|
|
526
|
-
cacheGetPromise = cache.getPromise().then(
|
|
527
|
-
(data) => {
|
|
528
|
-
if (data) {
|
|
529
|
-
lastModulesCount = lastModulesCount || data.modulesCount;
|
|
530
|
-
lastDependenciesCount =
|
|
531
|
-
lastDependenciesCount || data.dependenciesCount;
|
|
532
|
-
}
|
|
533
|
-
return data;
|
|
534
|
-
},
|
|
535
|
-
(_err) => {
|
|
536
|
-
// Ignore error
|
|
537
|
-
}
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
compiler.hooks.afterCompile.tapPromise(PLUGIN_NAME, (compilation) => {
|
|
543
|
-
if (compilation.compiler.isChild()) return Promise.resolve();
|
|
544
|
-
return /** @type {Promise<CountsData>} */ (cacheGetPromise).then(
|
|
545
|
-
async (oldData) => {
|
|
546
|
-
const realModulesCount = modulesCount - skippedModulesCount;
|
|
547
|
-
const realDependenciesCount =
|
|
548
|
-
dependenciesCount - skippedDependenciesCount;
|
|
549
|
-
|
|
550
|
-
if (
|
|
551
|
-
!oldData ||
|
|
552
|
-
oldData.modulesCount !== realModulesCount ||
|
|
553
|
-
oldData.dependenciesCount !== realDependenciesCount
|
|
554
|
-
) {
|
|
555
|
-
await cache.storePromise({
|
|
556
|
-
modulesCount: realModulesCount,
|
|
557
|
-
dependenciesCount: realDependenciesCount
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
);
|
|
562
|
-
});
|
|
563
|
-
|
|
564
663
|
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
|
565
664
|
if (compilation.compiler.isChild()) return;
|
|
665
|
+
// Carry the previous compilation's counts into the next as an estimate
|
|
666
|
+
// (helps watch rebuilds); not persisted, to avoid cache invalidation.
|
|
566
667
|
lastModulesCount = modulesCount;
|
|
567
668
|
lastEntriesCount = entriesCount;
|
|
568
669
|
lastDependenciesCount = dependenciesCount;
|
|
569
|
-
modulesCount =
|
|
570
|
-
skippedModulesCount =
|
|
571
|
-
dependenciesCount =
|
|
572
|
-
skippedDependenciesCount =
|
|
573
|
-
entriesCount =
|
|
574
|
-
0;
|
|
670
|
+
modulesCount = dependenciesCount = entriesCount = 0;
|
|
575
671
|
doneModules = doneDependencies = doneEntries = 0;
|
|
576
672
|
|
|
577
|
-
compilation.factorizeQueue.hooks.added.tap(PLUGIN_NAME,
|
|
578
|
-
factorizeAdd(compilation.factorizeQueue, item)
|
|
579
|
-
);
|
|
673
|
+
compilation.factorizeQueue.hooks.added.tap(PLUGIN_NAME, factorizeAdd);
|
|
580
674
|
compilation.factorizeQueue.hooks.result.tap(PLUGIN_NAME, factorizeDone);
|
|
581
675
|
|
|
582
|
-
compilation.addModuleQueue.hooks.added.tap(PLUGIN_NAME,
|
|
583
|
-
moduleAdd(compilation.addModuleQueue, item)
|
|
584
|
-
);
|
|
676
|
+
compilation.addModuleQueue.hooks.added.tap(PLUGIN_NAME, moduleAdd);
|
|
585
677
|
compilation.processDependenciesQueue.hooks.result.tap(
|
|
586
678
|
PLUGIN_NAME,
|
|
587
679
|
moduleDone
|
package/lib/ProvidePlugin.js
CHANGED
|
@@ -85,7 +85,7 @@ class ProvidePlugin {
|
|
|
85
85
|
request.slice(1),
|
|
86
86
|
/** @type {Range} */ (expr.range)
|
|
87
87
|
);
|
|
88
|
-
dep.loc =
|
|
88
|
+
dep.loc = parser.getLocation(expr);
|
|
89
89
|
parser.state.module.addDependency(dep);
|
|
90
90
|
return true;
|
|
91
91
|
});
|
|
@@ -100,7 +100,7 @@ class ProvidePlugin {
|
|
|
100
100
|
request.slice(1),
|
|
101
101
|
/** @type {Range} */ (expr.callee.range)
|
|
102
102
|
);
|
|
103
|
-
dep.loc =
|
|
103
|
+
dep.loc = parser.getLocation(expr.callee);
|
|
104
104
|
parser.state.module.addDependency(dep);
|
|
105
105
|
parser.walkExpressions(expr.arguments);
|
|
106
106
|
return true;
|