webpack 5.8.0 → 5.9.0
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.
Potentially problematic release.
This version of webpack might be problematic. Click here for more details.
- package/lib/ConcurrentCompilationError.js +1 -3
- package/lib/ContextModuleFactory.js +1 -3
- package/lib/HarmonyLinkingError.js +1 -3
- package/lib/HotModuleReplacementPlugin.js +170 -36
- package/lib/ModuleDependencyWarning.js +1 -3
- package/lib/NoModeWarning.js +1 -3
- package/lib/NormalModule.js +13 -0
- package/lib/TemplatedPathPlugin.js +8 -0
- package/lib/config/defaults.js +1 -1
- package/lib/container/ContainerEntryModuleFactory.js +1 -3
- package/lib/container/FallbackModuleFactory.js +1 -3
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +8 -0
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +8 -0
- package/lib/optimize/SideEffectsFlagPlugin.js +224 -204
- package/lib/performance/AssetsOverSizeLimitWarning.js +1 -3
- package/lib/performance/EntrypointsOverSizeLimitWarning.js +1 -3
- package/lib/performance/NoAsyncChunksWarning.js +1 -3
- package/lib/runtime/GetMainFilenameRuntimeModule.js +4 -2
- package/lib/util/runtime.js +4 -0
- package/lib/wasm-sync/UnsupportedWebAssemblyFeatureError.js +1 -3
- package/lib/wasm-sync/WebAssemblyInInitialChunkError.js +1 -3
- package/package.json +1 -1
- package/types.d.ts +1 -0
@@ -26,9 +26,7 @@ const { join } = require("./util/fs");
|
|
26
26
|
|
27
27
|
const EMPTY_RESOLVE_OPTIONS = {};
|
28
28
|
|
29
|
-
module.exports = class ContextModuleFactory extends
|
30
|
-
ModuleFactory
|
31
|
-
) {
|
29
|
+
module.exports = class ContextModuleFactory extends ModuleFactory {
|
32
30
|
/**
|
33
31
|
* @param {ResolverFactory} resolverFactory resolverFactory
|
34
32
|
*/
|
@@ -6,9 +6,7 @@
|
|
6
6
|
|
7
7
|
const WebpackError = require("./WebpackError");
|
8
8
|
|
9
|
-
module.exports = class HarmonyLinkingError extends
|
10
|
-
WebpackError
|
11
|
-
) {
|
9
|
+
module.exports = class HarmonyLinkingError extends WebpackError {
|
12
10
|
/** @param {string} message Error message */
|
13
11
|
constructor(message) {
|
14
12
|
super(message);
|
@@ -12,6 +12,7 @@ const Compilation = require("./Compilation");
|
|
12
12
|
const HotUpdateChunk = require("./HotUpdateChunk");
|
13
13
|
const NormalModule = require("./NormalModule");
|
14
14
|
const RuntimeGlobals = require("./RuntimeGlobals");
|
15
|
+
const WebpackError = require("./WebpackError");
|
15
16
|
const ConstDependency = require("./dependencies/ConstDependency");
|
16
17
|
const ImportMetaHotAcceptDependency = require("./dependencies/ImportMetaHotAcceptDependency");
|
17
18
|
const ImportMetaHotDeclineDependency = require("./dependencies/ImportMetaHotDeclineDependency");
|
@@ -22,15 +23,22 @@ const JavascriptParser = require("./javascript/JavascriptParser");
|
|
22
23
|
const {
|
23
24
|
evaluateToIdentifier
|
24
25
|
} = require("./javascript/JavascriptParserHelpers");
|
25
|
-
const { find } = require("./util/SetHelpers");
|
26
|
+
const { find, isSubset } = require("./util/SetHelpers");
|
26
27
|
const TupleSet = require("./util/TupleSet");
|
27
28
|
const { compareModulesById } = require("./util/comparators");
|
28
|
-
const {
|
29
|
+
const {
|
30
|
+
getRuntimeKey,
|
31
|
+
keyToRuntime,
|
32
|
+
forEachRuntime,
|
33
|
+
mergeRuntimeOwned,
|
34
|
+
subtractRuntime
|
35
|
+
} = require("./util/runtime");
|
29
36
|
|
30
37
|
/** @typedef {import("./Chunk")} Chunk */
|
31
38
|
/** @typedef {import("./Compilation").AssetInfo} AssetInfo */
|
32
39
|
/** @typedef {import("./Compiler")} Compiler */
|
33
40
|
/** @typedef {import("./Module")} Module */
|
41
|
+
/** @typedef {import("./RuntimeModule")} RuntimeModule */
|
34
42
|
|
35
43
|
/**
|
36
44
|
* @typedef {Object} HMRJavascriptParserHooks
|
@@ -388,27 +396,58 @@ class HotModuleReplacementPlugin {
|
|
388
396
|
}
|
389
397
|
chunkModuleHashes[key] = hash;
|
390
398
|
}
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
399
|
+
|
400
|
+
/** @type {Map<string, { updatedChunkIds: Set<string|number>, removedChunkIds: Set<string|number>, removedModules: Set<Module>, filename: string, assetInfo: AssetInfo }>} */
|
401
|
+
const hotUpdateMainContentByRuntime = new Map();
|
402
|
+
let allOldRuntime;
|
403
|
+
for (const key of Object.keys(records.chunkRuntime)) {
|
404
|
+
const runtime = keyToRuntime(records.chunkRuntime[key]);
|
405
|
+
allOldRuntime = mergeRuntimeOwned(allOldRuntime, runtime);
|
406
|
+
}
|
407
|
+
forEachRuntime(allOldRuntime, runtime => {
|
408
|
+
const {
|
409
|
+
path: filename,
|
410
|
+
info: assetInfo
|
411
|
+
} = compilation.getPathWithInfo(
|
412
|
+
compilation.outputOptions.hotUpdateMainFilename,
|
413
|
+
{
|
414
|
+
hash: records.hash,
|
415
|
+
runtime
|
416
|
+
}
|
417
|
+
);
|
418
|
+
hotUpdateMainContentByRuntime.set(runtime, {
|
419
|
+
updatedChunkIds: new Set(),
|
420
|
+
removedChunkIds: new Set(),
|
421
|
+
removedModules: new Set(),
|
422
|
+
filename,
|
423
|
+
assetInfo
|
424
|
+
});
|
425
|
+
});
|
426
|
+
if (hotUpdateMainContentByRuntime.size === 0) return;
|
396
427
|
|
397
428
|
// Create a list of all active modules to verify which modules are removed completely
|
398
429
|
/** @type {Map<number|string, Module>} */
|
399
430
|
const allModules = new Map();
|
400
431
|
for (const module of compilation.modules) {
|
401
|
-
|
432
|
+
const id = chunkGraph.getModuleId(module);
|
433
|
+
allModules.set(id, module);
|
402
434
|
}
|
403
435
|
|
404
436
|
// List of completely removed modules
|
405
|
-
|
437
|
+
/** @type {Set<string | number>} */
|
438
|
+
const completelyRemovedModules = new Set();
|
406
439
|
|
407
440
|
for (const key of Object.keys(records.chunkHashs)) {
|
408
|
-
|
441
|
+
const oldRuntime = keyToRuntime(records.chunkRuntime[key]);
|
442
|
+
/** @type {Module[]} */
|
443
|
+
const remainingModules = [];
|
444
|
+
// Check which modules are removed
|
409
445
|
for (const id of records.chunkModuleIds[key]) {
|
410
|
-
|
411
|
-
|
446
|
+
const module = allModules.get(id);
|
447
|
+
if (module === undefined) {
|
448
|
+
completelyRemovedModules.add(id);
|
449
|
+
} else {
|
450
|
+
remainingModules.push(module);
|
412
451
|
}
|
413
452
|
}
|
414
453
|
|
@@ -417,6 +456,7 @@ class HotModuleReplacementPlugin {
|
|
417
456
|
let newRuntimeModules;
|
418
457
|
let newFullHashModules;
|
419
458
|
let newRuntime;
|
459
|
+
let removedFromRuntime;
|
420
460
|
const currentChunk = find(
|
421
461
|
compilation.chunks,
|
422
462
|
chunk => `${chunk.id}` === key
|
@@ -438,18 +478,61 @@ class HotModuleReplacementPlugin {
|
|
438
478
|
Array.from(fullHashModules).filter(module =>
|
439
479
|
updatedModules.has(module, currentChunk)
|
440
480
|
);
|
481
|
+
removedFromRuntime = subtractRuntime(oldRuntime, newRuntime);
|
441
482
|
} else {
|
483
|
+
// chunk has completely removed
|
442
484
|
chunkId = `${+key}` === key ? +key : key;
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
485
|
+
removedFromRuntime = oldRuntime;
|
486
|
+
newRuntime = oldRuntime;
|
487
|
+
}
|
488
|
+
if (removedFromRuntime) {
|
489
|
+
// chunk was removed from some runtimes
|
490
|
+
forEachRuntime(removedFromRuntime, runtime => {
|
491
|
+
hotUpdateMainContentByRuntime
|
492
|
+
.get(runtime)
|
493
|
+
.removedChunkIds.add(chunkId);
|
494
|
+
});
|
495
|
+
// dispose modules from the chunk in these runtimes
|
496
|
+
// where they are no longer in this runtime
|
497
|
+
for (const module of remainingModules) {
|
449
498
|
const moduleKey = `${key}|${module.identifier()}`;
|
450
|
-
|
451
|
-
|
452
|
-
|
499
|
+
const oldHash = records.chunkModuleHashes[moduleKey];
|
500
|
+
const runtimes = chunkGraph.getModuleRuntimes(module);
|
501
|
+
if (oldRuntime === newRuntime && runtimes.has(newRuntime)) {
|
502
|
+
// Module is still in the same runtime combination
|
503
|
+
const hash = chunkGraph.getModuleHash(module, newRuntime);
|
504
|
+
if (hash !== oldHash) {
|
505
|
+
if (module.type === "runtime") {
|
506
|
+
newRuntimeModules = newRuntimeModules || [];
|
507
|
+
newRuntimeModules.push(
|
508
|
+
/** @type {RuntimeModule} */ (module)
|
509
|
+
);
|
510
|
+
} else {
|
511
|
+
newModules = newModules || [];
|
512
|
+
newModules.push(module);
|
513
|
+
}
|
514
|
+
}
|
515
|
+
} else {
|
516
|
+
// module is no longer in this runtime combination
|
517
|
+
// We (incorrectly) assume that it's not in an overlapping runtime combination
|
518
|
+
// and dispose it from the main runtimes the chunk was removed from
|
519
|
+
forEachRuntime(removedFromRuntime, runtime => {
|
520
|
+
// If the module is still used in this runtime, do not dispose it
|
521
|
+
// This could create a bad runtime state where the module is still loaded,
|
522
|
+
// but no chunk which contains it. This means we don't receive further HMR updates
|
523
|
+
// to this module and that's bad.
|
524
|
+
// TODO force load one of the chunks which contains the module
|
525
|
+
for (const moduleRuntime of runtimes) {
|
526
|
+
if (typeof moduleRuntime === "string") {
|
527
|
+
if (moduleRuntime === runtime) return;
|
528
|
+
} else if (moduleRuntime !== undefined) {
|
529
|
+
if (moduleRuntime.has(runtime)) return;
|
530
|
+
}
|
531
|
+
}
|
532
|
+
hotUpdateMainContentByRuntime
|
533
|
+
.get(runtime)
|
534
|
+
.removedModules.add(module);
|
535
|
+
});
|
453
536
|
}
|
454
537
|
}
|
455
538
|
}
|
@@ -516,24 +599,75 @@ class HotModuleReplacementPlugin {
|
|
516
599
|
compilation.hooks.chunkAsset.call(currentChunk, filename);
|
517
600
|
}
|
518
601
|
}
|
519
|
-
|
602
|
+
forEachRuntime(newRuntime, runtime => {
|
603
|
+
hotUpdateMainContentByRuntime
|
604
|
+
.get(runtime)
|
605
|
+
.updatedChunkIds.add(chunkId);
|
606
|
+
});
|
520
607
|
}
|
521
608
|
}
|
522
|
-
|
523
|
-
|
524
|
-
const {
|
525
|
-
path: filename,
|
526
|
-
info: assetInfo
|
527
|
-
} = compilation.getPathWithInfo(
|
528
|
-
compilation.outputOptions.hotUpdateMainFilename,
|
529
|
-
{
|
530
|
-
hash: records.hash
|
531
|
-
}
|
609
|
+
const completelyRemovedModulesArray = Array.from(
|
610
|
+
completelyRemovedModules
|
532
611
|
);
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
612
|
+
const hotUpdateMainContentByFilename = new Map();
|
613
|
+
for (const {
|
614
|
+
removedChunkIds,
|
615
|
+
removedModules,
|
616
|
+
updatedChunkIds,
|
617
|
+
filename,
|
618
|
+
assetInfo
|
619
|
+
} of hotUpdateMainContentByRuntime.values()) {
|
620
|
+
const old = hotUpdateMainContentByFilename.get(filename);
|
621
|
+
if (
|
622
|
+
old &&
|
623
|
+
(!isSubset(old.removedChunkIds, removedChunkIds) ||
|
624
|
+
!isSubset(old.removedModules, removedModules) ||
|
625
|
+
!isSubset(old.updatedChunkIds, updatedChunkIds))
|
626
|
+
) {
|
627
|
+
compilation.warnings.push(
|
628
|
+
new WebpackError(`HotModuleReplacementPlugin
|
629
|
+
The configured output.hotUpdateMainFilename doesn't lead to unique filenames per runtime and HMR update differs between runtimes.
|
630
|
+
This might lead to incorrect runtime behavior of the applied update.
|
631
|
+
To fix this, make sure to include [runtime] in the output.hotUpdateMainFilename option, or use the default config.`)
|
632
|
+
);
|
633
|
+
for (const chunkId of removedChunkIds)
|
634
|
+
old.removedChunkIds.add(chunkId);
|
635
|
+
for (const chunkId of removedModules)
|
636
|
+
old.removedModules.add(chunkId);
|
637
|
+
for (const chunkId of updatedChunkIds)
|
638
|
+
old.updatedChunkIds.add(chunkId);
|
639
|
+
continue;
|
640
|
+
}
|
641
|
+
hotUpdateMainContentByFilename.set(filename, {
|
642
|
+
removedChunkIds,
|
643
|
+
removedModules,
|
644
|
+
updatedChunkIds,
|
645
|
+
assetInfo
|
646
|
+
});
|
647
|
+
}
|
648
|
+
for (const [
|
649
|
+
filename,
|
650
|
+
{ removedChunkIds, removedModules, updatedChunkIds, assetInfo }
|
651
|
+
] of hotUpdateMainContentByFilename) {
|
652
|
+
const hotUpdateMainJson = {
|
653
|
+
c: Array.from(updatedChunkIds),
|
654
|
+
r: Array.from(removedChunkIds),
|
655
|
+
m:
|
656
|
+
removedModules.size === 0
|
657
|
+
? completelyRemovedModulesArray
|
658
|
+
: completelyRemovedModulesArray.concat(
|
659
|
+
Array.from(removedModules, m =>
|
660
|
+
chunkGraph.getModuleId(m)
|
661
|
+
)
|
662
|
+
)
|
663
|
+
};
|
664
|
+
|
665
|
+
const source = new RawSource(JSON.stringify(hotUpdateMainJson));
|
666
|
+
compilation.emitAsset(filename, source, {
|
667
|
+
hotModuleReplacement: true,
|
668
|
+
...assetInfo
|
669
|
+
});
|
670
|
+
}
|
537
671
|
}
|
538
672
|
);
|
539
673
|
|
@@ -10,9 +10,7 @@ const WebpackError = require("./WebpackError");
|
|
10
10
|
/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
|
11
11
|
/** @typedef {import("./Module")} Module */
|
12
12
|
|
13
|
-
module.exports = class ModuleDependencyWarning extends
|
14
|
-
WebpackError
|
15
|
-
) {
|
13
|
+
module.exports = class ModuleDependencyWarning extends WebpackError {
|
16
14
|
/**
|
17
15
|
* @param {Module} module module tied to dependency
|
18
16
|
* @param {Error} err error thrown
|
package/lib/NoModeWarning.js
CHANGED
package/lib/NormalModule.js
CHANGED
@@ -26,6 +26,7 @@ const ModuleWarning = require("./ModuleWarning");
|
|
26
26
|
const RuntimeGlobals = require("./RuntimeGlobals");
|
27
27
|
const UnhandledSchemeError = require("./UnhandledSchemeError");
|
28
28
|
const WebpackError = require("./WebpackError");
|
29
|
+
const formatLocation = require("./formatLocation");
|
29
30
|
const LazySet = require("./util/LazySet");
|
30
31
|
const { getScheme } = require("./util/URLAbsoluteSpecifier");
|
31
32
|
const {
|
@@ -248,6 +249,7 @@ class NormalModule extends Module {
|
|
248
249
|
this._lastSuccessfulBuildMeta = {};
|
249
250
|
this._forceBuild = true;
|
250
251
|
this._isEvaluatingSideEffects = false;
|
252
|
+
this._addedSideEffectsBailout = new WeakSet();
|
251
253
|
}
|
252
254
|
|
253
255
|
/**
|
@@ -877,6 +879,17 @@ class NormalModule extends Module {
|
|
877
879
|
for (const dep of this.dependencies) {
|
878
880
|
const state = dep.getModuleEvaluationSideEffectsState(moduleGraph);
|
879
881
|
if (state === true) {
|
882
|
+
if (!this._addedSideEffectsBailout.has(moduleGraph)) {
|
883
|
+
this._addedSideEffectsBailout.add(moduleGraph);
|
884
|
+
moduleGraph
|
885
|
+
.getOptimizationBailout(this)
|
886
|
+
.push(
|
887
|
+
() =>
|
888
|
+
`Dependency (${
|
889
|
+
dep.type
|
890
|
+
}) with side effects at ${formatLocation(dep.loc)}`
|
891
|
+
);
|
892
|
+
}
|
880
893
|
this._isEvaluatingSideEffects = false;
|
881
894
|
return true;
|
882
895
|
} else if (state !== ModuleGraphConnection.CIRCULAR_CONNECTION) {
|
@@ -274,6 +274,14 @@ const replacePathVariables = (path, data, assetInfo) => {
|
|
274
274
|
if (data.url) {
|
275
275
|
replacements.set("url", replacer(data.url));
|
276
276
|
}
|
277
|
+
if (typeof data.runtime === "string") {
|
278
|
+
replacements.set(
|
279
|
+
"runtime",
|
280
|
+
replacer(() => prepareId(data.runtime))
|
281
|
+
);
|
282
|
+
} else {
|
283
|
+
replacements.set("runtime", replacer("_"));
|
284
|
+
}
|
277
285
|
|
278
286
|
if (typeof path === "function") {
|
279
287
|
path = path(data, assetInfo);
|
package/lib/config/defaults.js
CHANGED
@@ -642,7 +642,7 @@ const applyOutputDefaults = (
|
|
642
642
|
F(output, "pathinfo", () => development);
|
643
643
|
D(output, "sourceMapFilename", "[file].map[query]");
|
644
644
|
D(output, "hotUpdateChunkFilename", "[id].[fullhash].hot-update.js");
|
645
|
-
D(output, "hotUpdateMainFilename", "[fullhash].hot-update.json");
|
645
|
+
D(output, "hotUpdateMainFilename", "[runtime].[fullhash].hot-update.json");
|
646
646
|
D(output, "crossOriginLoading", false);
|
647
647
|
F(output, "scriptType", () => (output.module ? "module" : false));
|
648
648
|
D(
|
@@ -12,9 +12,7 @@ const ContainerEntryModule = require("./ContainerEntryModule");
|
|
12
12
|
/** @typedef {import("../ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
|
13
13
|
/** @typedef {import("./ContainerEntryDependency")} ContainerEntryDependency */
|
14
14
|
|
15
|
-
module.exports = class ContainerEntryModuleFactory extends
|
16
|
-
ModuleFactory
|
17
|
-
) {
|
15
|
+
module.exports = class ContainerEntryModuleFactory extends ModuleFactory {
|
18
16
|
/**
|
19
17
|
* @param {ModuleFactoryCreateData} data data object
|
20
18
|
* @param {function(Error=, ModuleFactoryResult=): void} callback callback
|
@@ -12,9 +12,7 @@ const FallbackModule = require("./FallbackModule");
|
|
12
12
|
/** @typedef {import("../ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
|
13
13
|
/** @typedef {import("./FallbackDependency")} FallbackDependency */
|
14
14
|
|
15
|
-
module.exports = class FallbackModuleFactory extends
|
16
|
-
ModuleFactory
|
17
|
-
) {
|
15
|
+
module.exports = class FallbackModuleFactory extends ModuleFactory {
|
18
16
|
/**
|
19
17
|
* @param {ModuleFactoryCreateData} data data object
|
20
18
|
* @param {function(Error=, ModuleFactoryResult=): void} callback callback
|
@@ -370,6 +370,14 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
|
370
370
|
};
|
371
371
|
}
|
372
372
|
|
373
|
+
/**
|
374
|
+
* @param {ModuleGraph} moduleGraph the module graph
|
375
|
+
* @returns {ConnectionState} how this dependency connects the module to referencing modules
|
376
|
+
*/
|
377
|
+
getModuleEvaluationSideEffectsState(moduleGraph) {
|
378
|
+
return false;
|
379
|
+
}
|
380
|
+
|
373
381
|
/**
|
374
382
|
* Returns list of exports referenced by this dependency
|
375
383
|
* @param {ModuleGraph} moduleGraph module graph
|
@@ -88,6 +88,14 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
|
|
88
88
|
this.checkUsedByExports(moduleGraph, runtime);
|
89
89
|
}
|
90
90
|
|
91
|
+
/**
|
92
|
+
* @param {ModuleGraph} moduleGraph the module graph
|
93
|
+
* @returns {ConnectionState} how this dependency connects the module to referencing modules
|
94
|
+
*/
|
95
|
+
getModuleEvaluationSideEffectsState(moduleGraph) {
|
96
|
+
return false;
|
97
|
+
}
|
98
|
+
|
91
99
|
checkUsedByExports(moduleGraph, runtime) {
|
92
100
|
if (this.usedByExports === false) return false;
|
93
101
|
if (this.usedByExports !== true && this.usedByExports !== undefined) {
|
@@ -9,6 +9,7 @@ const glob2regexp = require("glob-to-regexp");
|
|
9
9
|
const { STAGE_DEFAULT } = require("../OptimizationStages");
|
10
10
|
const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
|
11
11
|
const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
|
12
|
+
const formatLocation = require("../formatLocation");
|
12
13
|
|
13
14
|
/** @typedef {import("../Compiler")} Compiler */
|
14
15
|
/** @typedef {import("../Dependency")} Dependency */
|
@@ -67,223 +68,242 @@ class SideEffectsFlagPlugin {
|
|
67
68
|
cache = new Map();
|
68
69
|
globToRegexpCache.set(compiler.root, cache);
|
69
70
|
}
|
70
|
-
compiler.hooks.
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
71
|
+
compiler.hooks.compilation.tap(
|
72
|
+
"SideEffectsFlagPlugin",
|
73
|
+
(compilation, { normalModuleFactory }) => {
|
74
|
+
const moduleGraph = compilation.moduleGraph;
|
75
|
+
normalModuleFactory.hooks.module.tap(
|
76
|
+
"SideEffectsFlagPlugin",
|
77
|
+
(module, data) => {
|
78
|
+
const resolveData = data.resourceResolveData;
|
79
|
+
if (
|
80
|
+
resolveData &&
|
81
|
+
resolveData.descriptionFileData &&
|
82
|
+
resolveData.relativePath
|
83
|
+
) {
|
84
|
+
const sideEffects = resolveData.descriptionFileData.sideEffects;
|
85
|
+
const hasSideEffects = SideEffectsFlagPlugin.moduleHasSideEffects(
|
86
|
+
resolveData.relativePath,
|
87
|
+
sideEffects,
|
88
|
+
cache
|
89
|
+
);
|
90
|
+
if (!hasSideEffects) {
|
91
|
+
if (module.factoryMeta === undefined) {
|
92
|
+
module.factoryMeta = {};
|
93
|
+
}
|
94
|
+
module.factoryMeta.sideEffectFree = true;
|
95
|
+
}
|
87
96
|
}
|
88
|
-
module.factoryMeta.sideEffectFree = true;
|
89
|
-
}
|
90
|
-
}
|
91
97
|
|
92
|
-
|
93
|
-
});
|
94
|
-
nmf.hooks.module.tap("SideEffectsFlagPlugin", (module, data) => {
|
95
|
-
if (data.settings.sideEffects === false) {
|
96
|
-
if (module.factoryMeta === undefined) {
|
97
|
-
module.factoryMeta = {};
|
98
|
-
}
|
99
|
-
module.factoryMeta.sideEffectFree = true;
|
100
|
-
} else if (data.settings.sideEffects === true) {
|
101
|
-
if (module.factoryMeta !== undefined) {
|
102
|
-
module.factoryMeta.sideEffectFree = false;
|
98
|
+
return module;
|
103
99
|
}
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
});
|
117
|
-
parser.hooks.statement.tap(
|
118
|
-
{ name: "SideEffectsFlagPlugin", stage: -100 },
|
119
|
-
statement => {
|
120
|
-
if (hasSideEffects) return;
|
121
|
-
if (parser.scope.topLevelScope !== true) return;
|
122
|
-
switch (statement.type) {
|
123
|
-
case "ExpressionStatement":
|
124
|
-
if (
|
125
|
-
!parser.isPure(statement.expression, statement.range[0])
|
126
|
-
) {
|
127
|
-
hasSideEffects = true;
|
128
|
-
}
|
129
|
-
break;
|
130
|
-
case "IfStatement":
|
131
|
-
case "WhileStatement":
|
132
|
-
case "DoWhileStatement":
|
133
|
-
if (!parser.isPure(statement.test, statement.range[0])) {
|
134
|
-
hasSideEffects = true;
|
135
|
-
}
|
136
|
-
// statement hook will be called for child statements too
|
137
|
-
break;
|
138
|
-
case "ForStatement":
|
139
|
-
if (
|
140
|
-
!parser.isPure(statement.init, statement.range[0]) ||
|
141
|
-
!parser.isPure(
|
142
|
-
statement.test,
|
143
|
-
statement.init
|
144
|
-
? statement.init.range[1]
|
145
|
-
: statement.range[0]
|
146
|
-
) ||
|
147
|
-
!parser.isPure(
|
148
|
-
statement.update,
|
149
|
-
statement.test
|
150
|
-
? statement.test.range[1]
|
151
|
-
: statement.init
|
152
|
-
? statement.init.range[1]
|
153
|
-
: statement.range[0]
|
154
|
-
)
|
155
|
-
) {
|
156
|
-
hasSideEffects = true;
|
157
|
-
}
|
158
|
-
// statement hook will be called for child statements too
|
159
|
-
break;
|
160
|
-
case "SwitchStatement":
|
161
|
-
if (
|
162
|
-
!parser.isPure(statement.discriminant, statement.range[0])
|
163
|
-
) {
|
164
|
-
hasSideEffects = true;
|
165
|
-
}
|
166
|
-
// statement hook will be called for child statements too
|
167
|
-
break;
|
168
|
-
case "VariableDeclaration":
|
169
|
-
case "ClassDeclaration":
|
170
|
-
case "FunctionDeclaration":
|
171
|
-
if (!parser.isPure(statement, statement.range[0])) {
|
172
|
-
hasSideEffects = true;
|
173
|
-
}
|
174
|
-
break;
|
175
|
-
case "ExportDefaultDeclaration":
|
176
|
-
if (
|
177
|
-
!parser.isPure(statement.declaration, statement.range[0])
|
178
|
-
) {
|
179
|
-
hasSideEffects = true;
|
180
|
-
}
|
181
|
-
break;
|
182
|
-
case "ExportNamedDeclaration":
|
183
|
-
if (statement.source) {
|
184
|
-
hasSideEffects = true;
|
185
|
-
}
|
186
|
-
break;
|
187
|
-
case "LabeledStatement":
|
188
|
-
case "BlockStatement":
|
189
|
-
// statement hook will be called for child statements too
|
190
|
-
break;
|
191
|
-
case "EmptyStatement":
|
192
|
-
break;
|
193
|
-
case "ImportDeclaration":
|
194
|
-
// imports will be handled by the dependencies
|
195
|
-
break;
|
196
|
-
default:
|
197
|
-
hasSideEffects = true;
|
198
|
-
break;
|
100
|
+
);
|
101
|
+
normalModuleFactory.hooks.module.tap(
|
102
|
+
"SideEffectsFlagPlugin",
|
103
|
+
(module, data) => {
|
104
|
+
if (data.settings.sideEffects === false) {
|
105
|
+
if (module.factoryMeta === undefined) {
|
106
|
+
module.factoryMeta = {};
|
107
|
+
}
|
108
|
+
module.factoryMeta.sideEffectFree = true;
|
109
|
+
} else if (data.settings.sideEffects === true) {
|
110
|
+
if (module.factoryMeta !== undefined) {
|
111
|
+
module.factoryMeta.sideEffectFree = false;
|
199
112
|
}
|
200
113
|
}
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
114
|
+
return module;
|
115
|
+
}
|
116
|
+
);
|
117
|
+
if (this._analyseSource) {
|
118
|
+
/**
|
119
|
+
* @param {JavascriptParser} parser the parser
|
120
|
+
* @returns {void}
|
121
|
+
*/
|
122
|
+
const parserHandler = parser => {
|
123
|
+
let sideEffectsStatement;
|
124
|
+
parser.hooks.program.tap("SideEffectsFlagPlugin", () => {
|
125
|
+
sideEffectsStatement = undefined;
|
126
|
+
});
|
127
|
+
parser.hooks.statement.tap(
|
128
|
+
{ name: "SideEffectsFlagPlugin", stage: -100 },
|
129
|
+
statement => {
|
130
|
+
if (sideEffectsStatement) return;
|
131
|
+
if (parser.scope.topLevelScope !== true) return;
|
132
|
+
switch (statement.type) {
|
133
|
+
case "ExpressionStatement":
|
134
|
+
if (
|
135
|
+
!parser.isPure(statement.expression, statement.range[0])
|
136
|
+
) {
|
137
|
+
sideEffectsStatement = statement;
|
138
|
+
}
|
139
|
+
break;
|
140
|
+
case "IfStatement":
|
141
|
+
case "WhileStatement":
|
142
|
+
case "DoWhileStatement":
|
143
|
+
if (!parser.isPure(statement.test, statement.range[0])) {
|
144
|
+
sideEffectsStatement = statement;
|
145
|
+
}
|
146
|
+
// statement hook will be called for child statements too
|
147
|
+
break;
|
148
|
+
case "ForStatement":
|
149
|
+
if (
|
150
|
+
!parser.isPure(statement.init, statement.range[0]) ||
|
151
|
+
!parser.isPure(
|
152
|
+
statement.test,
|
153
|
+
statement.init
|
154
|
+
? statement.init.range[1]
|
155
|
+
: statement.range[0]
|
156
|
+
) ||
|
157
|
+
!parser.isPure(
|
158
|
+
statement.update,
|
159
|
+
statement.test
|
160
|
+
? statement.test.range[1]
|
161
|
+
: statement.init
|
162
|
+
? statement.init.range[1]
|
163
|
+
: statement.range[0]
|
164
|
+
)
|
165
|
+
) {
|
166
|
+
sideEffectsStatement = statement;
|
167
|
+
}
|
168
|
+
// statement hook will be called for child statements too
|
169
|
+
break;
|
170
|
+
case "SwitchStatement":
|
171
|
+
if (
|
172
|
+
!parser.isPure(statement.discriminant, statement.range[0])
|
173
|
+
) {
|
174
|
+
sideEffectsStatement = statement;
|
175
|
+
}
|
176
|
+
// statement hook will be called for child statements too
|
177
|
+
break;
|
178
|
+
case "VariableDeclaration":
|
179
|
+
case "ClassDeclaration":
|
180
|
+
case "FunctionDeclaration":
|
181
|
+
if (!parser.isPure(statement, statement.range[0])) {
|
182
|
+
sideEffectsStatement = statement;
|
183
|
+
}
|
184
|
+
break;
|
185
|
+
case "ExportNamedDeclaration":
|
186
|
+
case "ExportDefaultDeclaration":
|
187
|
+
if (
|
188
|
+
!parser.isPure(statement.declaration, statement.range[0])
|
189
|
+
) {
|
190
|
+
sideEffectsStatement = statement;
|
191
|
+
}
|
192
|
+
break;
|
193
|
+
case "LabeledStatement":
|
194
|
+
case "BlockStatement":
|
195
|
+
// statement hook will be called for child statements too
|
196
|
+
break;
|
197
|
+
case "EmptyStatement":
|
198
|
+
break;
|
199
|
+
case "ExportAllDeclaration":
|
200
|
+
case "ImportDeclaration":
|
201
|
+
// imports will be handled by the dependencies
|
202
|
+
break;
|
203
|
+
default:
|
204
|
+
sideEffectsStatement = statement;
|
205
|
+
break;
|
206
|
+
}
|
207
|
+
}
|
208
|
+
);
|
209
|
+
parser.hooks.finish.tap("SideEffectsFlagPlugin", () => {
|
210
|
+
if (sideEffectsStatement === undefined) {
|
211
|
+
parser.state.module.buildMeta.sideEffectFree = true;
|
212
|
+
} else {
|
213
|
+
const { loc, type } = sideEffectsStatement;
|
214
|
+
moduleGraph
|
215
|
+
.getOptimizationBailout(parser.state.module)
|
216
|
+
.push(
|
217
|
+
() =>
|
218
|
+
`Statement (${type}) with side effects in source code at ${formatLocation(
|
219
|
+
loc
|
220
|
+
)}`
|
221
|
+
);
|
222
|
+
}
|
223
|
+
});
|
224
|
+
};
|
225
|
+
for (const key of [
|
226
|
+
"javascript/auto",
|
227
|
+
"javascript/esm",
|
228
|
+
"javascript/dynamic"
|
229
|
+
]) {
|
230
|
+
normalModuleFactory.hooks.parser
|
231
|
+
.for(key)
|
232
|
+
.tap("SideEffectsFlagPlugin", parserHandler);
|
233
|
+
}
|
214
234
|
}
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
modules => {
|
225
|
-
const logger = compilation.getLogger("webpack.SideEffectsFlagPlugin");
|
235
|
+
compilation.hooks.optimizeDependencies.tap(
|
236
|
+
{
|
237
|
+
name: "SideEffectsFlagPlugin",
|
238
|
+
stage: STAGE_DEFAULT
|
239
|
+
},
|
240
|
+
modules => {
|
241
|
+
const logger = compilation.getLogger(
|
242
|
+
"webpack.SideEffectsFlagPlugin"
|
243
|
+
);
|
226
244
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
module
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
module
|
263
|
-
|
264
|
-
|
265
|
-
|
245
|
+
logger.time("update dependencies");
|
246
|
+
for (const module of modules) {
|
247
|
+
if (module.getSideEffectsConnectionState(moduleGraph) === false) {
|
248
|
+
const exportsInfo = moduleGraph.getExportsInfo(module);
|
249
|
+
for (const connection of moduleGraph.getIncomingConnections(
|
250
|
+
module
|
251
|
+
)) {
|
252
|
+
const dep = connection.dependency;
|
253
|
+
let isReexport;
|
254
|
+
if (
|
255
|
+
(isReexport =
|
256
|
+
dep instanceof
|
257
|
+
HarmonyExportImportedSpecifierDependency) ||
|
258
|
+
(dep instanceof HarmonyImportSpecifierDependency &&
|
259
|
+
!dep.namespaceObjectAsContext)
|
260
|
+
) {
|
261
|
+
// TODO improve for export *
|
262
|
+
if (isReexport && dep.name) {
|
263
|
+
const exportInfo = moduleGraph.getExportInfo(
|
264
|
+
connection.originModule,
|
265
|
+
dep.name
|
266
|
+
);
|
267
|
+
exportInfo.moveTarget(
|
268
|
+
moduleGraph,
|
269
|
+
({ module }) =>
|
270
|
+
module.getSideEffectsConnectionState(moduleGraph) ===
|
271
|
+
false
|
272
|
+
);
|
273
|
+
}
|
274
|
+
// TODO improve for nested imports
|
275
|
+
const ids = dep.getIds(moduleGraph);
|
276
|
+
if (ids.length > 0) {
|
277
|
+
const exportInfo = exportsInfo.getExportInfo(ids[0]);
|
278
|
+
const target = exportInfo.moveTarget(
|
279
|
+
moduleGraph,
|
280
|
+
({ module }) =>
|
281
|
+
module.getSideEffectsConnectionState(moduleGraph) ===
|
282
|
+
false
|
283
|
+
);
|
284
|
+
if (!target) continue;
|
266
285
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
286
|
+
moduleGraph.updateModule(dep, target.module);
|
287
|
+
moduleGraph.addExplanation(
|
288
|
+
dep,
|
289
|
+
"(skipped side-effect-free modules)"
|
290
|
+
);
|
291
|
+
dep.setIds(
|
292
|
+
moduleGraph,
|
293
|
+
target.export
|
294
|
+
? [...target.export, ...ids.slice(1)]
|
295
|
+
: ids.slice(1)
|
296
|
+
);
|
297
|
+
}
|
278
298
|
}
|
279
299
|
}
|
280
300
|
}
|
281
301
|
}
|
302
|
+
logger.timeEnd("update dependencies");
|
282
303
|
}
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
});
|
304
|
+
);
|
305
|
+
}
|
306
|
+
);
|
287
307
|
}
|
288
308
|
|
289
309
|
static moduleHasSideEffects(moduleName, flagValue, cache) {
|
@@ -10,9 +10,7 @@ const WebpackError = require("../WebpackError");
|
|
10
10
|
|
11
11
|
/** @typedef {import("./SizeLimitsPlugin").AssetDetails} AssetDetails */
|
12
12
|
|
13
|
-
module.exports = class AssetsOverSizeLimitWarning extends
|
14
|
-
WebpackError
|
15
|
-
) {
|
13
|
+
module.exports = class AssetsOverSizeLimitWarning extends WebpackError {
|
16
14
|
/**
|
17
15
|
* @param {AssetDetails[]} assetsOverSizeLimit the assets
|
18
16
|
* @param {number} assetLimit the size limit
|
@@ -10,9 +10,7 @@ const WebpackError = require("../WebpackError");
|
|
10
10
|
|
11
11
|
/** @typedef {import("./SizeLimitsPlugin").EntrypointDetails} EntrypointDetails */
|
12
12
|
|
13
|
-
module.exports = class EntrypointsOverSizeLimitWarning extends
|
14
|
-
WebpackError
|
15
|
-
) {
|
13
|
+
module.exports = class EntrypointsOverSizeLimitWarning extends WebpackError {
|
16
14
|
/**
|
17
15
|
* @param {EntrypointDetails[]} entrypoints the entrypoints
|
18
16
|
* @param {number} entrypointLimit the size limit
|
@@ -7,9 +7,7 @@
|
|
7
7
|
|
8
8
|
const WebpackError = require("../WebpackError");
|
9
9
|
|
10
|
-
module.exports = class NoAsyncChunksWarning extends
|
11
|
-
WebpackError
|
12
|
-
) {
|
10
|
+
module.exports = class NoAsyncChunksWarning extends WebpackError {
|
13
11
|
constructor() {
|
14
12
|
super(
|
15
13
|
"webpack performance recommendations: \n" +
|
@@ -26,12 +26,14 @@ class GetMainFilenameRuntimeModule extends RuntimeModule {
|
|
26
26
|
* @returns {string} runtime code
|
27
27
|
*/
|
28
28
|
generate() {
|
29
|
-
const { global, filename, compilation } = this;
|
29
|
+
const { global, filename, compilation, chunk } = this;
|
30
30
|
const { runtimeTemplate } = compilation;
|
31
31
|
const url = compilation.getPath(JSON.stringify(filename), {
|
32
32
|
hash: `" + ${RuntimeGlobals.getFullHash}() + "`,
|
33
33
|
hashWithLength: length =>
|
34
|
-
`" + ${RuntimeGlobals.getFullHash}().slice(0, ${length}) + "
|
34
|
+
`" + ${RuntimeGlobals.getFullHash}().slice(0, ${length}) + "`,
|
35
|
+
chunk,
|
36
|
+
runtime: chunk.runtime
|
35
37
|
});
|
36
38
|
return Template.asString([
|
37
39
|
`${global} = ${runtimeTemplate.returningFunction(url)};`
|
package/lib/util/runtime.js
CHANGED
@@ -6,9 +6,7 @@
|
|
6
6
|
|
7
7
|
const WebpackError = require("../WebpackError");
|
8
8
|
|
9
|
-
module.exports = class UnsupportedWebAssemblyFeatureError extends
|
10
|
-
WebpackError
|
11
|
-
) {
|
9
|
+
module.exports = class UnsupportedWebAssemblyFeatureError extends WebpackError {
|
12
10
|
/** @param {string} message Error message */
|
13
11
|
constructor(message) {
|
14
12
|
super(message);
|
@@ -79,9 +79,7 @@ const getInitialModuleChains = (
|
|
79
79
|
return Array.from(results);
|
80
80
|
};
|
81
81
|
|
82
|
-
module.exports = class WebAssemblyInInitialChunkError extends
|
83
|
-
WebpackError
|
84
|
-
) {
|
82
|
+
module.exports = class WebAssemblyInInitialChunkError extends WebpackError {
|
85
83
|
/**
|
86
84
|
* @param {Module} module WASM module
|
87
85
|
* @param {ModuleGraph} moduleGraph the module graph
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "webpack",
|
3
|
-
"version": "5.
|
3
|
+
"version": "5.9.0",
|
4
4
|
"author": "Tobias Koppers @sokra",
|
5
5
|
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
|
6
6
|
"license": "MIT",
|
package/types.d.ts
CHANGED
@@ -8060,6 +8060,7 @@ declare abstract class RuntimeSpecMap<T> {
|
|
8060
8060
|
}
|
8061
8061
|
declare abstract class RuntimeSpecSet {
|
8062
8062
|
add(runtime?: any): void;
|
8063
|
+
has(runtime?: any): boolean;
|
8063
8064
|
[Symbol.iterator](): IterableIterator<string | SortableSet<string>>;
|
8064
8065
|
readonly size: number;
|
8065
8066
|
}
|