webpack 5.43.0 → 5.46.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.

@@ -855,10 +855,13 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
855
855
  logger: this.getLogger("webpack.FileSystemInfo")
856
856
  });
857
857
  if (compiler.fileTimestamps) {
858
- this.fileSystemInfo.addFileTimestamps(compiler.fileTimestamps);
858
+ this.fileSystemInfo.addFileTimestamps(compiler.fileTimestamps, true);
859
859
  }
860
860
  if (compiler.contextTimestamps) {
861
- this.fileSystemInfo.addContextTimestamps(compiler.contextTimestamps);
861
+ this.fileSystemInfo.addContextTimestamps(
862
+ compiler.contextTimestamps,
863
+ true
864
+ );
862
865
  }
863
866
  /** @type {Map<string, string | Set<string>>} */
864
867
  this.valueCacheVersions = new Map();
package/lib/Compiler.js CHANGED
@@ -222,13 +222,13 @@ class Compiler {
222
222
  /** @type {Set<string>} */
223
223
  this.immutablePaths = new Set();
224
224
 
225
- /** @type {Set<string>} */
225
+ /** @type {ReadonlySet<string>} */
226
226
  this.modifiedFiles = undefined;
227
- /** @type {Set<string>} */
227
+ /** @type {ReadonlySet<string>} */
228
228
  this.removedFiles = undefined;
229
- /** @type {Map<string, FileSystemInfoEntry | "ignore" | null>} */
229
+ /** @type {ReadonlyMap<string, FileSystemInfoEntry | "ignore" | null>} */
230
230
  this.fileTimestamps = undefined;
231
- /** @type {Map<string, FileSystemInfoEntry | "ignore" | null>} */
231
+ /** @type {ReadonlyMap<string, FileSystemInfoEntry | "ignore" | null>} */
232
232
  this.contextTimestamps = undefined;
233
233
  /** @type {number} */
234
234
  this.fsStartTime = undefined;
@@ -12,7 +12,7 @@ const { resolveByProperty, cachedSetProperty } = require("./util/cleverMerge");
12
12
  /** @typedef {import("../declarations/WebpackOptions").Externals} Externals */
13
13
  /** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
14
14
 
15
- const UNSPECIFIED_EXTERNAL_TYPE_REGEXP = /^[a-z0-9]+ /;
15
+ const UNSPECIFIED_EXTERNAL_TYPE_REGEXP = /^[a-z0-9-]+ /;
16
16
  const EMPTY_RESOLVE_OPTIONS = {};
17
17
 
18
18
  // TODO webpack 6 remove this
@@ -8,6 +8,7 @@
8
8
  const { create: createResolver } = require("enhanced-resolve");
9
9
  const asyncLib = require("neo-async");
10
10
  const AsyncQueue = require("./util/AsyncQueue");
11
+ const StackedCacheMap = require("./util/StackedCacheMap");
11
12
  const createHash = require("./util/createHash");
12
13
  const { join, dirname, relative } = require("./util/fs");
13
14
  const makeSerializable = require("./util/makeSerializable");
@@ -365,7 +366,7 @@ class Snapshot {
365
366
  }
366
367
 
367
368
  /**
368
- * @param {function(Snapshot): (Map<string, any> | Set<string>)[]} getMaps first
369
+ * @param {function(Snapshot): (ReadonlyMap<string, any> | ReadonlySet<string>)[]} getMaps first
369
370
  * @returns {Iterable<string>} iterable
370
371
  */
371
372
  _createIterable(getMaps) {
@@ -853,14 +854,14 @@ class FileSystemInfo {
853
854
  (s, v) => s.setManagedMissing(v),
854
855
  true
855
856
  );
856
- /** @type {Map<string, FileSystemInfoEntry | "ignore" | null>} */
857
- this._fileTimestamps = new Map();
857
+ /** @type {StackedCacheMap<string, FileSystemInfoEntry | "ignore" | null>} */
858
+ this._fileTimestamps = new StackedCacheMap();
858
859
  /** @type {Map<string, string>} */
859
860
  this._fileHashes = new Map();
860
861
  /** @type {Map<string, TimestampAndHash | string>} */
861
862
  this._fileTshs = new Map();
862
- /** @type {Map<string, FileSystemInfoEntry | "ignore" | null>} */
863
- this._contextTimestamps = new Map();
863
+ /** @type {StackedCacheMap<string, FileSystemInfoEntry | "ignore" | null>} */
864
+ this._contextTimestamps = new StackedCacheMap();
864
865
  /** @type {Map<string, string>} */
865
866
  this._contextHashes = new Map();
866
867
  /** @type {Map<string, TimestampAndHash | string>} */
@@ -1060,24 +1061,22 @@ class FileSystemInfo {
1060
1061
  }
1061
1062
 
1062
1063
  /**
1063
- * @param {Map<string, FileSystemInfoEntry | "ignore" | null>} map timestamps
1064
+ * @param {ReadonlyMap<string, FileSystemInfoEntry | "ignore" | null>} map timestamps
1065
+ * @param {boolean=} immutable if 'map' is immutable and FileSystemInfo can keep referencing it
1064
1066
  * @returns {void}
1065
1067
  */
1066
- addFileTimestamps(map) {
1067
- for (const [path, ts] of map) {
1068
- this._fileTimestamps.set(path, ts);
1069
- }
1068
+ addFileTimestamps(map, immutable) {
1069
+ this._fileTimestamps.addAll(map, immutable);
1070
1070
  this._cachedDeprecatedFileTimestamps = undefined;
1071
1071
  }
1072
1072
 
1073
1073
  /**
1074
- * @param {Map<string, FileSystemInfoEntry | "ignore" | null>} map timestamps
1074
+ * @param {ReadonlyMap<string, FileSystemInfoEntry | "ignore" | null>} map timestamps
1075
+ * @param {boolean=} immutable if 'map' is immutable and FileSystemInfo can keep referencing it
1075
1076
  * @returns {void}
1076
1077
  */
1077
- addContextTimestamps(map) {
1078
- for (const [path, ts] of map) {
1079
- this._contextTimestamps.set(path, ts);
1080
- }
1078
+ addContextTimestamps(map, immutable) {
1079
+ this._contextTimestamps.addAll(map, immutable);
1081
1080
  this._cachedDeprecatedContextTimestamps = undefined;
1082
1081
  }
1083
1082
 
@@ -313,12 +313,12 @@ module.exports = class MultiCompiler {
313
313
  /**
314
314
  * @template SetupResult
315
315
  * @param {function(Compiler, number, Callback<Stats>, function(): boolean, function(): void, function(): void): SetupResult} setup setup a single compiler
316
- * @param {function(Compiler, Callback<Stats>): void} run run/continue a single compiler
316
+ * @param {function(Compiler, SetupResult, Callback<Stats>): void} run run/continue a single compiler
317
317
  * @param {Callback<MultiStats>} callback callback when all compilers are done, result includes Stats of all changed compilers
318
318
  * @returns {SetupResult[]} result of setup
319
319
  */
320
320
  _runGraph(setup, run, callback) {
321
- /** @typedef {{ compiler: Compiler, result: Stats, state: "pending" | "blocked" | "queued" | "starting" | "running" | "running-outdated" | "done", children: Node[], parents: Node[] }} Node */
321
+ /** @typedef {{ compiler: Compiler, setupResult: SetupResult, result: Stats, state: "pending" | "blocked" | "queued" | "starting" | "running" | "running-outdated" | "done", children: Node[], parents: Node[] }} Node */
322
322
 
323
323
  // State transitions for nodes:
324
324
  // -> blocked (initial)
@@ -335,6 +335,7 @@ module.exports = class MultiCompiler {
335
335
  /** @type {Node[]} */
336
336
  const nodes = this.compilers.map(compiler => ({
337
337
  compiler,
338
+ setupResult: undefined,
338
339
  result: undefined,
339
340
  state: "blocked",
340
341
  children: [],
@@ -444,14 +445,14 @@ module.exports = class MultiCompiler {
444
445
  const setupResults = [];
445
446
  nodes.forEach((node, i) => {
446
447
  setupResults.push(
447
- setup(
448
+ (node.setupResult = setup(
448
449
  node.compiler,
449
450
  i,
450
451
  nodeDone.bind(null, node),
451
452
  () => node.state !== "starting" && node.state !== "running",
452
453
  () => nodeChange(node),
453
454
  () => nodeInvalid(node)
454
- )
455
+ ))
455
456
  );
456
457
  });
457
458
  let processing = true;
@@ -470,7 +471,7 @@ module.exports = class MultiCompiler {
470
471
  ) {
471
472
  running++;
472
473
  node.state = "starting";
473
- run(node.compiler, nodeDone.bind(null, node));
474
+ run(node.compiler, node.setupResult, nodeDone.bind(null, node));
474
475
  node.state = "running";
475
476
  }
476
477
  }
@@ -522,8 +523,9 @@ module.exports = class MultiCompiler {
522
523
  }
523
524
  return watching;
524
525
  },
525
- (compiler, initial, callback) => {
526
- if (!compiler.watching.running) compiler.watching.invalidate();
526
+ (compiler, watching, callback) => {
527
+ if (compiler.watching !== watching) return;
528
+ if (!watching.running) watching.invalidate();
527
529
  },
528
530
  handler
529
531
  );
@@ -546,7 +548,7 @@ module.exports = class MultiCompiler {
546
548
  if (this.validateDependencies(callback)) {
547
549
  this._runGraph(
548
550
  () => {},
549
- (compiler, callback) => compiler.run(callback),
551
+ (compiler, setupResult, callback) => compiler.run(callback),
550
552
  (err, stats) => {
551
553
  this.running = false;
552
554
 
@@ -350,18 +350,20 @@ class NormalModule extends Module {
350
350
  this.resource = m.resource;
351
351
  this.matchResource = m.matchResource;
352
352
  this.loaders = m.loaders;
353
- this._sourceTypes = m._sourceTypes;
354
- this._sourceSizes = m._sourceSizes;
355
353
  }
356
354
 
357
355
  /**
358
356
  * Assuming this module is in the cache. Remove internal references to allow freeing some memory.
359
357
  */
360
358
  cleanupForCache() {
361
- // Make sure to cache types and sizes before cleanup
362
- if (this._sourceTypes === undefined) this.getSourceTypes();
363
- for (const type of this._sourceTypes) {
364
- this.size(type);
359
+ // Make sure to cache types and sizes before cleanup when this module has been built
360
+ // They are accessed by the stats and we don't want them to crash after cleanup
361
+ // TODO reconsider this for webpack 6
362
+ if (this.buildInfo) {
363
+ if (this._sourceTypes === undefined) this.getSourceTypes();
364
+ for (const type of this._sourceTypes) {
365
+ this.size(type);
366
+ }
365
367
  }
366
368
  super.cleanupForCache();
367
369
  this.parser = undefined;
@@ -152,7 +152,7 @@ class SourceMapDevToolPlugin {
152
152
  const fallbackModuleFilenameTemplate = this.fallbackModuleFilenameTemplate;
153
153
  const requestShortener = compiler.requestShortener;
154
154
  const options = this.options;
155
- options.test = options.test || /\.(m?js|css)($|\?)/i;
155
+ options.test = options.test || /\.((c|m)?js|css)($|\?)/i;
156
156
 
157
157
  const matchObject = ModuleFilenameHelpers.matchObject.bind(
158
158
  undefined,
package/lib/Template.js CHANGED
@@ -379,6 +379,7 @@ class Template {
379
379
  source.add(Template.toNormalComment(module.identifier()) + "\n");
380
380
  if (!module.shouldIsolate()) {
381
381
  source.add(runtimeSource);
382
+ source.add("\n\n");
382
383
  } else if (renderContext.runtimeTemplate.supportsArrowFunction()) {
383
384
  source.add("(() => {\n");
384
385
  if (renderContext.useStrict) source.add('\t"use strict";\n');
package/lib/Watching.js CHANGED
@@ -10,6 +10,7 @@ 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("./FileSystemInfo").FileSystemInfoEntry} FileSystemInfoEntry */
13
14
 
14
15
  /**
15
16
  * @template T
@@ -67,6 +68,10 @@ class Watching {
67
68
  });
68
69
  }
69
70
 
71
+ /**
72
+ * @param {ReadonlySet<string>} changedFiles changed files
73
+ * @param {ReadonlySet<string>} removedFiles removed files
74
+ */
70
75
  _mergeWithCollected(changedFiles, removedFiles) {
71
76
  if (!changedFiles) return;
72
77
  if (!this._collectedChangedFiles) {
@@ -84,6 +89,13 @@ class Watching {
84
89
  }
85
90
  }
86
91
 
92
+ /**
93
+ * @param {ReadonlyMap<string, FileSystemInfoEntry | "ignore">=} fileTimeInfoEntries info for files
94
+ * @param {ReadonlyMap<string, FileSystemInfoEntry | "ignore">=} contextTimeInfoEntries info for directories
95
+ * @param {ReadonlySet<string>=} changedFiles changed files
96
+ * @param {ReadonlySet<string>=} removedFiles removed files
97
+ * @returns {void}
98
+ */
87
99
  _go(fileTimeInfoEntries, contextTimeInfoEntries, changedFiles, removedFiles) {
88
100
  this._initial = false;
89
101
  if (this.startTime === null) this.startTime = Date.now();
@@ -141,7 +141,9 @@ class AssetGenerator extends Generator {
141
141
  module.resourceResolveData &&
142
142
  module.resourceResolveData.mimetype !== undefined
143
143
  ) {
144
- mimeType = module.resourceResolveData.mimetype;
144
+ mimeType =
145
+ module.resourceResolveData.mimetype +
146
+ module.resourceResolveData.parameters;
145
147
  } else if (ext) {
146
148
  mimeType = mimeTypes.lookup(ext);
147
149
  }
@@ -156,22 +158,33 @@ class AssetGenerator extends Generator {
156
158
  }
157
159
 
158
160
  let encodedContent;
159
- switch (encoding) {
160
- case "base64": {
161
- encodedContent = originalSource.buffer().toString("base64");
162
- break;
163
- }
164
- case false: {
165
- const content = originalSource.source();
166
- if (typeof content === "string") {
167
- encodedContent = encodeURI(content);
168
- } else {
169
- encodedContent = encodeURI(content.toString("utf-8"));
161
+ if (
162
+ module.resourceResolveData &&
163
+ module.resourceResolveData.encoding === encoding
164
+ ) {
165
+ encodedContent = module.resourceResolveData.encodedContent;
166
+ } else {
167
+ switch (encoding) {
168
+ case "base64": {
169
+ encodedContent = originalSource.buffer().toString("base64");
170
+ break;
171
+ }
172
+ case false: {
173
+ const content = originalSource.source();
174
+
175
+ if (typeof content !== "string") {
176
+ encodedContent = content.toString("utf-8");
177
+ }
178
+
179
+ encodedContent = encodeURIComponent(encodedContent).replace(
180
+ /[!'()*]/g,
181
+ character => "%" + character.codePointAt(0).toString(16)
182
+ );
183
+ break;
170
184
  }
171
- break;
185
+ default:
186
+ throw new Error(`Unsupported encoding '${encoding}'`);
172
187
  }
173
- default:
174
- throw new Error(`Unsupported encoding '${encoding}'`);
175
188
  }
176
189
 
177
190
  encodedSource = `data:${mimeType}${
@@ -172,24 +172,29 @@ class AssetModulesPlugin {
172
172
  );
173
173
  if (modules) {
174
174
  for (const module of modules) {
175
- const codeGenResult = codeGenerationResults.get(
176
- module,
177
- chunk.runtime
178
- );
179
- result.push({
180
- render: () => codeGenResult.sources.get(type),
181
- filename:
182
- module.buildInfo.filename ||
183
- codeGenResult.data.get("filename"),
184
- info:
185
- module.buildInfo.assetInfo ||
186
- codeGenResult.data.get("assetInfo"),
187
- auxiliary: true,
188
- identifier: `assetModule${chunkGraph.getModuleId(module)}`,
189
- hash:
190
- module.buildInfo.fullContentHash ||
191
- codeGenResult.data.get("fullContentHash")
192
- });
175
+ try {
176
+ const codeGenResult = codeGenerationResults.get(
177
+ module,
178
+ chunk.runtime
179
+ );
180
+ result.push({
181
+ render: () => codeGenResult.sources.get(type),
182
+ filename:
183
+ module.buildInfo.filename ||
184
+ codeGenResult.data.get("filename"),
185
+ info:
186
+ module.buildInfo.assetInfo ||
187
+ codeGenResult.data.get("assetInfo"),
188
+ auxiliary: true,
189
+ identifier: `assetModule${chunkGraph.getModuleId(module)}`,
190
+ hash:
191
+ module.buildInfo.fullContentHash ||
192
+ codeGenResult.data.get("fullContentHash")
193
+ });
194
+ } catch (e) {
195
+ e.message += `\nduring rendering of asset ${module.identifier()}`;
196
+ throw e;
197
+ }
193
198
  }
194
199
  }
195
200
 
@@ -0,0 +1,29 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const RuntimeModule = require("../RuntimeModule");
8
+
9
+ class ExportWebpackRequireRuntimeModule extends RuntimeModule {
10
+ constructor() {
11
+ super("export webpack runtime", RuntimeModule.STAGE_ATTACH);
12
+ }
13
+
14
+ /**
15
+ * @returns {boolean} true, if the runtime module should get it's own scope
16
+ */
17
+ shouldIsolate() {
18
+ return false;
19
+ }
20
+
21
+ /**
22
+ * @returns {string} runtime code
23
+ */
24
+ generate() {
25
+ return "export default __webpack_require__;";
26
+ }
27
+ }
28
+
29
+ module.exports = ExportWebpackRequireRuntimeModule;
@@ -5,13 +5,18 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const { ConcatSource } = require("webpack-sources");
8
+ const { ConcatSource, RawSource } = require("webpack-sources");
9
9
  const { RuntimeGlobals } = require("..");
10
10
  const HotUpdateChunk = require("../HotUpdateChunk");
11
11
  const Template = require("../Template");
12
12
  const {
13
- getCompilationHooks
13
+ getCompilationHooks,
14
+ getChunkFilenameTemplate
14
15
  } = require("../javascript/JavascriptModulesPlugin");
16
+ const {
17
+ generateEntryStartup,
18
+ updateHashForEntryStartup
19
+ } = require("../javascript/StartupHelpers");
15
20
 
16
21
  /** @typedef {import("../Compiler")} Compiler */
17
22
 
@@ -30,8 +35,9 @@ class ModuleChunkFormatPlugin {
30
35
  (chunk, set) => {
31
36
  if (chunk.hasRuntime()) return;
32
37
  if (compilation.chunkGraph.getNumberOfEntryModules(chunk) > 0) {
33
- set.add(RuntimeGlobals.onChunksLoaded);
34
38
  set.add(RuntimeGlobals.require);
39
+ set.add(RuntimeGlobals.startupEntrypoint);
40
+ set.add(RuntimeGlobals.externalInstallChunk);
35
41
  }
36
42
  }
37
43
  );
@@ -39,7 +45,7 @@ class ModuleChunkFormatPlugin {
39
45
  hooks.renderChunk.tap(
40
46
  "ModuleChunkFormatPlugin",
41
47
  (modules, renderContext) => {
42
- const { chunk, chunkGraph } = renderContext;
48
+ const { chunk, chunkGraph, runtimeTemplate } = renderContext;
43
49
  const hotUpdateChunk =
44
50
  chunk instanceof HotUpdateChunk ? chunk : null;
45
51
  const source = new ConcatSource();
@@ -68,9 +74,84 @@ class ModuleChunkFormatPlugin {
68
74
  chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
69
75
  );
70
76
  if (entries.length > 0) {
71
- throw new Error(
72
- "Entry modules in chunk is not implemented for module chunk format yet"
77
+ const runtimeChunk = entries[0][1].getRuntimeChunk();
78
+ const currentOutputName = compilation
79
+ .getPath(
80
+ getChunkFilenameTemplate(chunk, compilation.outputOptions),
81
+ {
82
+ chunk,
83
+ contentHashType: "javascript"
84
+ }
85
+ )
86
+ .split("/");
87
+ const runtimeOutputName = compilation
88
+ .getPath(
89
+ getChunkFilenameTemplate(
90
+ runtimeChunk,
91
+ compilation.outputOptions
92
+ ),
93
+ {
94
+ chunk: runtimeChunk,
95
+ contentHashType: "javascript"
96
+ }
97
+ )
98
+ .split("/");
99
+
100
+ // remove filename, we only need the directory
101
+ const outputFilename = currentOutputName.pop();
102
+
103
+ // remove common parts
104
+ while (
105
+ currentOutputName.length > 0 &&
106
+ runtimeOutputName.length > 0 &&
107
+ currentOutputName[0] === runtimeOutputName[0]
108
+ ) {
109
+ currentOutputName.shift();
110
+ runtimeOutputName.shift();
111
+ }
112
+
113
+ // create final path
114
+ const runtimePath =
115
+ (currentOutputName.length > 0
116
+ ? "../".repeat(currentOutputName.length)
117
+ : "./") + runtimeOutputName.join("/");
118
+
119
+ const entrySource = new ConcatSource();
120
+ entrySource.add(source);
121
+ entrySource.add(";\n\n// load runtime\n");
122
+ entrySource.add(
123
+ `import __webpack_require__ from ${JSON.stringify(
124
+ runtimePath
125
+ )};\n`
126
+ );
127
+ entrySource.add(
128
+ `import * as __webpack_self_exports__ from ${JSON.stringify(
129
+ "./" + outputFilename
130
+ )};\n`
131
+ );
132
+ entrySource.add(
133
+ `${RuntimeGlobals.externalInstallChunk}(__webpack_self_exports__);\n`
134
+ );
135
+ const startupSource = new RawSource(
136
+ generateEntryStartup(
137
+ chunkGraph,
138
+ runtimeTemplate,
139
+ entries,
140
+ chunk,
141
+ false
142
+ )
143
+ );
144
+ entrySource.add(
145
+ hooks.renderStartup.call(
146
+ startupSource,
147
+ entries[entries.length - 1][0],
148
+ {
149
+ ...renderContext,
150
+ inlined: false
151
+ }
152
+ )
73
153
  );
154
+ return entrySource;
74
155
  }
75
156
  }
76
157
  return source;
@@ -82,11 +163,10 @@ class ModuleChunkFormatPlugin {
82
163
  if (chunk.hasRuntime()) return;
83
164
  hash.update("ModuleChunkFormatPlugin");
84
165
  hash.update("1");
85
- // TODO
86
- // const entries = Array.from(
87
- // chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
88
- // );
89
- // updateHashForEntryStartup(hash, chunkGraph, entries, chunk);
166
+ const entries = Array.from(
167
+ chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
168
+ );
169
+ updateHashForEntryStartup(hash, chunkGraph, entries, chunk);
90
170
  }
91
171
  );
92
172
  }
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const RuntimeGlobals = require("../RuntimeGlobals");
9
+ const ExportWebpackRequireRuntimeModule = require("./ExportWebpackRequireRuntimeModule");
9
10
  const ModuleChunkLoadingRuntimeModule = require("./ModuleChunkLoadingRuntimeModule");
10
11
 
11
12
  /** @typedef {import("../Compiler")} Compiler */
@@ -45,9 +46,21 @@ class ModuleChunkLoadingPlugin {
45
46
  compilation.hooks.runtimeRequirementInTree
46
47
  .for(RuntimeGlobals.baseURI)
47
48
  .tap("ModuleChunkLoadingPlugin", handler);
49
+ compilation.hooks.runtimeRequirementInTree
50
+ .for(RuntimeGlobals.externalInstallChunk)
51
+ .tap("ModuleChunkLoadingPlugin", handler);
48
52
  compilation.hooks.runtimeRequirementInTree
49
53
  .for(RuntimeGlobals.onChunksLoaded)
50
54
  .tap("ModuleChunkLoadingPlugin", handler);
55
+ compilation.hooks.runtimeRequirementInTree
56
+ .for(RuntimeGlobals.externalInstallChunk)
57
+ .tap("ModuleChunkLoadingPlugin", (chunk, set) => {
58
+ if (!isEnabledForChunk(chunk)) return;
59
+ compilation.addRuntimeModule(
60
+ chunk,
61
+ new ExportWebpackRequireRuntimeModule()
62
+ );
63
+ });
51
64
 
52
65
  compilation.hooks.runtimeRequirementInTree
53
66
  .for(RuntimeGlobals.ensureChunkHandlers)