webpack 5.5.1 → 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/bin/webpack.js +10 -3
- package/lib/Compilation.js +132 -17
- package/lib/Compiler.js +2 -2
- package/lib/ExportsInfo.js +1 -1
- package/lib/FlagDependencyUsagePlugin.js +4 -2
- package/lib/HotModuleReplacementPlugin.js +170 -36
- package/lib/NormalModule.js +13 -1
- package/lib/RuntimeTemplate.js +0 -3
- package/lib/SourceMapDevToolPlugin.js +2 -1
- package/lib/Template.js +0 -1
- package/lib/TemplatedPathPlugin.js +8 -0
- package/lib/Watching.js +0 -1
- package/lib/cache/ResolverCachePlugin.js +0 -1
- package/lib/config/defaults.js +1 -1
- package/lib/dependencies/AMDDefineDependency.js +3 -1
- package/lib/dependencies/AMDRequireArrayDependency.js +3 -1
- package/lib/dependencies/AMDRequireDependency.js +3 -1
- package/lib/dependencies/CachedConstDependency.js +3 -1
- package/lib/dependencies/CommonJsExportRequireDependency.js +3 -2
- package/lib/dependencies/CommonJsExportsDependency.js +3 -1
- package/lib/dependencies/CommonJsFullRequireDependency.js +3 -1
- package/lib/dependencies/CommonJsSelfReferenceDependency.js +3 -1
- package/lib/dependencies/ConstDependency.js +3 -1
- package/lib/dependencies/ExportsInfoDependency.js +3 -1
- package/lib/dependencies/HarmonyAcceptDependency.js +3 -1
- package/lib/dependencies/HarmonyAcceptImportDependency.js +3 -1
- package/lib/dependencies/HarmonyCompatibilityDependency.js +3 -1
- package/lib/dependencies/HarmonyExportExpressionDependency.js +3 -1
- package/lib/dependencies/HarmonyExportHeaderDependency.js +3 -1
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +11 -2
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +3 -1
- package/lib/dependencies/HarmonyImportDependency.js +50 -46
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +3 -1
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +11 -1
- package/lib/dependencies/ImportDependency.js +3 -2
- package/lib/dependencies/ImportEagerDependency.js +3 -1
- package/lib/dependencies/ImportWeakDependency.js +3 -1
- package/lib/dependencies/LocalModuleDependency.js +3 -1
- package/lib/dependencies/ModuleDecoratorDependency.js +3 -2
- package/lib/dependencies/NullDependency.js +3 -2
- package/lib/dependencies/PureExpressionDependency.js +3 -1
- package/lib/dependencies/RequireEnsureDependency.js +3 -1
- package/lib/dependencies/RequireHeaderDependency.js +3 -1
- package/lib/dependencies/RequireIncludeDependency.js +3 -2
- package/lib/dependencies/RequireResolveHeaderDependency.js +3 -1
- package/lib/dependencies/RuntimeRequirementsDependency.js +3 -1
- package/lib/dependencies/URLDependency.js +3 -1
- package/lib/dependencies/UnsupportedDependency.js +3 -1
- package/lib/dependencies/WorkerDependency.js +3 -2
- package/lib/hmr/HotModuleReplacement.runtime.js +1 -0
- package/lib/index.js +3 -0
- package/lib/javascript/JavascriptParser.js +29 -11
- package/lib/optimize/RealContentHashPlugin.js +127 -32
- package/lib/optimize/SideEffectsFlagPlugin.js +224 -204
- package/lib/optimize/SplitChunksPlugin.js +0 -1
- package/lib/runtime/GetMainFilenameRuntimeModule.js +4 -2
- package/lib/runtime/LoadScriptRuntimeModule.js +0 -1
- package/lib/serialization/FileMiddleware.js +4 -2
- package/lib/util/runtime.js +4 -0
- package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +0 -1
- package/lib/webpack.js +0 -2
- package/package.json +14 -14
- package/types.d.ts +179 -149
package/bin/webpack.js
CHANGED
@@ -82,10 +82,17 @@ if (!cli.installed) {
|
|
82
82
|
|
83
83
|
console.error(notify);
|
84
84
|
|
85
|
-
|
85
|
+
let packageManager;
|
86
|
+
|
87
|
+
if (fs.existsSync(path.resolve(process.cwd(), "yarn.lock"))) {
|
88
|
+
packageManager = "yarn";
|
89
|
+
} else if (fs.existsSync(path.resolve(process.cwd(), "pnpm-lock.yaml"))) {
|
90
|
+
packageManager = "pnpm";
|
91
|
+
} else {
|
92
|
+
packageManager = "npm";
|
93
|
+
}
|
86
94
|
|
87
|
-
const
|
88
|
-
const installOptions = [isYarn ? "add" : "install", "-D"];
|
95
|
+
const installOptions = [packageManager === "yarn" ? "add" : "install", "-D"];
|
89
96
|
|
90
97
|
console.error(
|
91
98
|
`We will use "${packageManager}" to install the CLI via "${packageManager} ${installOptions.join(
|
package/lib/Compilation.js
CHANGED
@@ -76,6 +76,8 @@ const { getRuntimeKey } = require("./util/runtime");
|
|
76
76
|
/** @typedef {import("webpack-sources").Source} Source */
|
77
77
|
/** @typedef {import("../declarations/WebpackOptions").EntryDescriptionNormalized} EntryDescription */
|
78
78
|
/** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
|
79
|
+
/** @typedef {import("../declarations/WebpackOptions").WebpackPluginFunction} WebpackPluginFunction */
|
80
|
+
/** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */
|
79
81
|
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
|
80
82
|
/** @typedef {import("./Cache")} Cache */
|
81
83
|
/** @typedef {import("./CacheFacade")} CacheFacade */
|
@@ -87,15 +89,11 @@ const { getRuntimeKey } = require("./util/runtime");
|
|
87
89
|
/** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */
|
88
90
|
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */
|
89
91
|
/** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */
|
90
|
-
/** @typedef {import("./Module")} Module */
|
91
92
|
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
|
92
93
|
/** @typedef {import("./ModuleFactory")} ModuleFactory */
|
93
94
|
/** @typedef {import("./RuntimeModule")} RuntimeModule */
|
94
95
|
/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */
|
95
96
|
/** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions */
|
96
|
-
/** @typedef {import("./WebpackError")} WebpackError */
|
97
|
-
/** @typedef {import("./stats/StatsFactory")} StatsFactory */
|
98
|
-
/** @typedef {import("./stats/StatsPrinter")} StatsPrinter */
|
99
97
|
/** @typedef {import("./util/Hash")} Hash */
|
100
98
|
/** @template T @typedef {import("./util/deprecation").FakeHook<T>} FakeHook<T> */
|
101
99
|
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
|
@@ -119,11 +117,6 @@ const { getRuntimeKey } = require("./util/runtime");
|
|
119
117
|
* @returns {any}
|
120
118
|
*/
|
121
119
|
|
122
|
-
/**
|
123
|
-
* @typedef {Object} Plugin
|
124
|
-
* @property {() => void} apply
|
125
|
-
*/
|
126
|
-
|
127
120
|
/** @typedef {new (...args: any[]) => Dependency} DepConstructor */
|
128
121
|
/** @typedef {Record<string, Source>} CompilationAssets */
|
129
122
|
|
@@ -296,10 +289,122 @@ class Compilation {
|
|
296
289
|
*/
|
297
290
|
constructor(compiler) {
|
298
291
|
const getNormalModuleLoader = () => deprecatedNormalModuleLoaderHook(this);
|
299
|
-
/** @
|
292
|
+
/** @typedef {{ additionalAssets?: true | Function }} ProcessAssetsAdditionalOptions */
|
293
|
+
/** @type {AsyncSeriesHook<[CompilationAssets], ProcessAssetsAdditionalOptions>} */
|
300
294
|
const processAssetsHook = new AsyncSeriesHook(["assets"]);
|
295
|
+
|
296
|
+
let savedAssets = new Set();
|
297
|
+
const popNewAssets = assets => {
|
298
|
+
let newAssets = undefined;
|
299
|
+
for (const file of Object.keys(assets)) {
|
300
|
+
if (savedAssets.has(file)) continue;
|
301
|
+
if (newAssets === undefined) {
|
302
|
+
newAssets = Object.create(null);
|
303
|
+
}
|
304
|
+
newAssets[file] = assets[file];
|
305
|
+
savedAssets.add(file);
|
306
|
+
}
|
307
|
+
return newAssets;
|
308
|
+
};
|
309
|
+
processAssetsHook.intercept({
|
310
|
+
name: "Compilation",
|
311
|
+
call: () => {
|
312
|
+
savedAssets.clear();
|
313
|
+
},
|
314
|
+
register: tap => {
|
315
|
+
const { type, name } = tap;
|
316
|
+
const { fn, additionalAssets, ...remainingTap } = tap;
|
317
|
+
const additionalAssetsFn =
|
318
|
+
additionalAssets === true ? fn : additionalAssets;
|
319
|
+
let processedAssets = undefined;
|
320
|
+
switch (type) {
|
321
|
+
case "sync":
|
322
|
+
if (additionalAssetsFn) {
|
323
|
+
this.hooks.processAdditionalAssets.tap(name, assets => {
|
324
|
+
if (processedAssets === this.assets) additionalAssetsFn(assets);
|
325
|
+
});
|
326
|
+
}
|
327
|
+
return {
|
328
|
+
...remainingTap,
|
329
|
+
type: "async",
|
330
|
+
fn: (assets, callback) => {
|
331
|
+
try {
|
332
|
+
fn(assets);
|
333
|
+
} catch (e) {
|
334
|
+
return callback(e);
|
335
|
+
}
|
336
|
+
processedAssets = this.assets;
|
337
|
+
const newAssets = popNewAssets(assets);
|
338
|
+
if (newAssets !== undefined) {
|
339
|
+
this.hooks.processAdditionalAssets.callAsync(
|
340
|
+
newAssets,
|
341
|
+
callback
|
342
|
+
);
|
343
|
+
return;
|
344
|
+
}
|
345
|
+
callback();
|
346
|
+
}
|
347
|
+
};
|
348
|
+
case "async":
|
349
|
+
if (additionalAssetsFn) {
|
350
|
+
this.hooks.processAdditionalAssets.tapAsync(
|
351
|
+
name,
|
352
|
+
(assets, callback) => {
|
353
|
+
if (processedAssets === this.assets)
|
354
|
+
return additionalAssetsFn(assets, callback);
|
355
|
+
callback();
|
356
|
+
}
|
357
|
+
);
|
358
|
+
}
|
359
|
+
return {
|
360
|
+
...remainingTap,
|
361
|
+
fn: (assets, callback) => {
|
362
|
+
fn(assets, err => {
|
363
|
+
if (err) return callback(err);
|
364
|
+
processedAssets = this.assets;
|
365
|
+
const newAssets = popNewAssets(assets);
|
366
|
+
if (newAssets !== undefined) {
|
367
|
+
this.hooks.processAdditionalAssets.callAsync(
|
368
|
+
newAssets,
|
369
|
+
callback
|
370
|
+
);
|
371
|
+
return;
|
372
|
+
}
|
373
|
+
callback();
|
374
|
+
});
|
375
|
+
}
|
376
|
+
};
|
377
|
+
case "promise":
|
378
|
+
if (additionalAssetsFn) {
|
379
|
+
this.hooks.processAdditionalAssets.tapPromise(name, assets => {
|
380
|
+
if (processedAssets === this.assets)
|
381
|
+
return additionalAssetsFn(assets);
|
382
|
+
return Promise.resolve();
|
383
|
+
});
|
384
|
+
}
|
385
|
+
return {
|
386
|
+
...remainingTap,
|
387
|
+
fn: assets => {
|
388
|
+
const p = fn(assets);
|
389
|
+
if (!p || !p.then) return p;
|
390
|
+
return p.then(() => {
|
391
|
+
processedAssets = this.assets;
|
392
|
+
const newAssets = popNewAssets(assets);
|
393
|
+
if (newAssets !== undefined) {
|
394
|
+
return this.hooks.processAdditionalAssets.promise(
|
395
|
+
newAssets
|
396
|
+
);
|
397
|
+
}
|
398
|
+
});
|
399
|
+
}
|
400
|
+
};
|
401
|
+
}
|
402
|
+
}
|
403
|
+
});
|
404
|
+
|
301
405
|
/** @type {SyncHook<[CompilationAssets]>} */
|
302
406
|
const afterProcessAssetsHook = new SyncHook(["assets"]);
|
407
|
+
|
303
408
|
/**
|
304
409
|
* @template T
|
305
410
|
* @param {string} name name of the hook
|
@@ -551,6 +656,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
551
656
|
|
552
657
|
processAssets: processAssetsHook,
|
553
658
|
afterProcessAssets: afterProcessAssetsHook,
|
659
|
+
/** @type {AsyncSeriesHook<[CompilationAssets]>} */
|
660
|
+
processAdditionalAssets: new AsyncSeriesHook(["assets"]),
|
554
661
|
|
555
662
|
/** @type {SyncBailHook<[], boolean>} */
|
556
663
|
needAdditionalSeal: new SyncBailHook([]),
|
@@ -3325,7 +3432,7 @@ This prevents using hashes of each other and should be avoided.`
|
|
3325
3432
|
*
|
3326
3433
|
* @param {string} name name of the child compiler
|
3327
3434
|
* @param {OutputOptions} outputOptions // Need to convert config schema to types for this
|
3328
|
-
* @param {
|
3435
|
+
* @param {Array<WebpackPluginInstance | WebpackPluginFunction>} plugins webpack plugins that will be applied
|
3329
3436
|
* @returns {Compiler} creates a child Compiler instance
|
3330
3437
|
*/
|
3331
3438
|
createChildCompiler(name, outputOptions, plugins) {
|
@@ -3446,6 +3553,8 @@ Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE = 100;
|
|
3446
3553
|
|
3447
3554
|
/**
|
3448
3555
|
* Optimize the count of existing assets, e. g. by merging them.
|
3556
|
+
* Only assets of the same type should be merged.
|
3557
|
+
* For assets of different types see PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE.
|
3449
3558
|
*/
|
3450
3559
|
Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT = 200;
|
3451
3560
|
|
@@ -3460,16 +3569,22 @@ Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY = 300;
|
|
3460
3569
|
Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE = 400;
|
3461
3570
|
|
3462
3571
|
/**
|
3463
|
-
*
|
3464
|
-
* When creating new assets from this they should be fully optimized.
|
3465
|
-
* e. g. creating an assets manifest of Service Workers.
|
3572
|
+
* Add development tooling to assets, e. g. by extracting a SourceMap.
|
3466
3573
|
*/
|
3467
|
-
Compilation.
|
3574
|
+
Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING = 500;
|
3468
3575
|
|
3469
3576
|
/**
|
3470
|
-
*
|
3577
|
+
* Optimize the count of existing assets, e. g. by inlining assets of into other assets.
|
3578
|
+
* Only assets of different types should be inlined.
|
3579
|
+
* For assets of the same type see PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT.
|
3471
3580
|
*/
|
3472
|
-
Compilation.
|
3581
|
+
Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE = 700;
|
3582
|
+
|
3583
|
+
/**
|
3584
|
+
* Summarize the list of existing assets
|
3585
|
+
* e. g. creating an assets manifest of Service Workers.
|
3586
|
+
*/
|
3587
|
+
Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE = 1000;
|
3473
3588
|
|
3474
3589
|
/**
|
3475
3590
|
* Optimize the hashes of the assets, e. g. by generating real hashes of the asset content.
|
package/lib/Compiler.js
CHANGED
@@ -152,9 +152,9 @@ class Compiler {
|
|
152
152
|
beforeCompile: new AsyncSeriesHook(["params"]),
|
153
153
|
/** @type {SyncHook<[CompilationParams]>} */
|
154
154
|
compile: new SyncHook(["params"]),
|
155
|
-
/** @type {AsyncParallelHook<[Compilation]
|
155
|
+
/** @type {AsyncParallelHook<[Compilation]>} */
|
156
156
|
make: new AsyncParallelHook(["compilation"]),
|
157
|
-
/** @type {AsyncParallelHook<[Compilation]
|
157
|
+
/** @type {AsyncParallelHook<[Compilation]>} */
|
158
158
|
finishMake: new AsyncSeriesHook(["compilation"]),
|
159
159
|
/** @type {AsyncSeriesHook<[Compilation]>} */
|
160
160
|
afterCompile: new AsyncSeriesHook(["compilation"]),
|
package/lib/ExportsInfo.js
CHANGED
@@ -1085,7 +1085,7 @@ class ExportInfo {
|
|
1085
1085
|
|
1086
1086
|
/**
|
1087
1087
|
* get used name
|
1088
|
-
* @param {string
|
1088
|
+
* @param {string | undefined} fallbackName fallback name for used exports with no name
|
1089
1089
|
* @param {RuntimeSpec} runtime check usage for this runtime only
|
1090
1090
|
* @returns {string | false} used name
|
1091
1091
|
*/
|
@@ -16,7 +16,6 @@ const { getEntryRuntime, mergeRuntimeOwned } = require("./util/runtime");
|
|
16
16
|
/** @typedef {import("./ChunkGroup")} ChunkGroup */
|
17
17
|
/** @typedef {import("./Compiler")} Compiler */
|
18
18
|
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
|
19
|
-
/** @typedef {import("./Dependency")} Dependency */
|
20
19
|
/** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */
|
21
20
|
/** @typedef {import("./ExportsInfo")} ExportsInfo */
|
22
21
|
/** @typedef {import("./Module")} Module */
|
@@ -207,7 +206,10 @@ class FlagDependencyUsagePlugin {
|
|
207
206
|
referencedExports === EXPORTS_OBJECT_REFERENCED
|
208
207
|
) {
|
209
208
|
map.set(module, referencedExports);
|
210
|
-
} else if (
|
209
|
+
} else if (
|
210
|
+
oldReferencedExports !== undefined &&
|
211
|
+
referencedExports === NO_EXPORTS_REFERENCED
|
212
|
+
) {
|
211
213
|
continue;
|
212
214
|
} else {
|
213
215
|
let exportsMap;
|
@@ -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
|
|
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 {
|
@@ -42,7 +43,6 @@ const makeSerializable = require("./util/makeSerializable");
|
|
42
43
|
/** @typedef {import("webpack-sources").Source} Source */
|
43
44
|
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
|
44
45
|
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
45
|
-
/** @typedef {import("./Compilation")} Compilation */
|
46
46
|
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
|
47
47
|
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
|
48
48
|
/** @typedef {import("./Generator")} Generator */
|
@@ -249,6 +249,7 @@ class NormalModule extends Module {
|
|
249
249
|
this._lastSuccessfulBuildMeta = {};
|
250
250
|
this._forceBuild = true;
|
251
251
|
this._isEvaluatingSideEffects = false;
|
252
|
+
this._addedSideEffectsBailout = new WeakSet();
|
252
253
|
}
|
253
254
|
|
254
255
|
/**
|
@@ -878,6 +879,17 @@ class NormalModule extends Module {
|
|
878
879
|
for (const dep of this.dependencies) {
|
879
880
|
const state = dep.getModuleEvaluationSideEffectsState(moduleGraph);
|
880
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
|
+
}
|
881
893
|
this._isEvaluatingSideEffects = false;
|
882
894
|
return true;
|
883
895
|
} else if (state !== ModuleGraphConnection.CIRCULAR_CONNECTION) {
|
package/lib/RuntimeTemplate.js
CHANGED
@@ -17,7 +17,6 @@ const { forEachRuntime, subtractRuntime } = require("./util/runtime");
|
|
17
17
|
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
|
18
18
|
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
19
19
|
/** @typedef {import("./Dependency")} Dependency */
|
20
|
-
/** @typedef {import("./InitFragment")} InitFragment */
|
21
20
|
/** @typedef {import("./Module")} Module */
|
22
21
|
/** @typedef {import("./ModuleGraph")} ModuleGraph */
|
23
22
|
/** @typedef {import("./RequestShortener")} RequestShortener */
|
@@ -607,8 +606,6 @@ class RuntimeTemplate {
|
|
607
606
|
* @param {string} options.importVar name of the import variable
|
608
607
|
* @param {Module} options.originModule module in which the statement is emitted
|
609
608
|
* @param {boolean=} options.weak true, if this is a weak dependency
|
610
|
-
* @param {RuntimeSpec=} options.runtime runtime for which this code will be generated
|
611
|
-
* @param {RuntimeSpec | boolean=} options.runtimeCondition only execute the statement in some runtimes
|
612
609
|
* @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
|
613
610
|
* @returns {[string, string]} the import statement and the compat statement
|
614
611
|
*/
|
@@ -162,7 +162,8 @@ class SourceMapDevToolPlugin {
|
|
162
162
|
compilation.hooks.processAssets.tapAsync(
|
163
163
|
{
|
164
164
|
name: "SourceMapDevToolPlugin",
|
165
|
-
stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING
|
165
|
+
stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
|
166
|
+
additionalAssets: true
|
166
167
|
},
|
167
168
|
(assets, callback) => {
|
168
169
|
const chunkGraph = compilation.chunkGraph;
|
package/lib/Template.js
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
const { ConcatSource, PrefixSource } = require("webpack-sources");
|
9
9
|
|
10
|
-
/** @typedef {import("webpack-sources").ConcatSource} ConcatSource */
|
11
10
|
/** @typedef {import("webpack-sources").Source} Source */
|
12
11
|
/** @typedef {import("../declarations/WebpackOptions").Output} OutputOptions */
|
13
12
|
/** @typedef {import("./Chunk")} Chunk */
|
@@ -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/Watching.js
CHANGED
@@ -10,7 +10,6 @@ const Stats = require("./Stats");
|
|
10
10
|
/** @typedef {import("../declarations/WebpackOptions").WatchOptions} WatchOptions */
|
11
11
|
/** @typedef {import("./Compilation")} Compilation */
|
12
12
|
/** @typedef {import("./Compiler")} Compiler */
|
13
|
-
/** @typedef {import("./Stats")} Stats */
|
14
13
|
|
15
14
|
/**
|
16
15
|
* @template T
|
@@ -13,7 +13,6 @@ const makeSerializable = require("../util/makeSerializable");
|
|
13
13
|
/** @typedef {import("../Compiler")} Compiler */
|
14
14
|
/** @typedef {import("../FileSystemInfo")} FileSystemInfo */
|
15
15
|
/** @typedef {import("../FileSystemInfo").Snapshot} Snapshot */
|
16
|
-
/** @template T @typedef {import("../util/LazySet")<T>} LazySet<T> */
|
17
16
|
|
18
17
|
class CacheEntry {
|
19
18
|
constructor(result, snapshot) {
|