webpack 5.51.0 → 5.52.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.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

@@ -76,7 +76,9 @@ makeSerializable(
76
76
 
77
77
  const MIN_CONTENT_SIZE = 1024 * 1024; // 1 MB
78
78
  const CONTENT_COUNT_TO_MERGE = 10;
79
+ const MIN_ITEMS_IN_FRESH_PACK = 100;
79
80
  const MAX_ITEMS_IN_FRESH_PACK = 50000;
81
+ const MAX_TIME_IN_FRESH_PACK = 1 * 60 * 1000; // 1 min
80
82
 
81
83
  class PackItemInfo {
82
84
  /**
@@ -99,6 +101,7 @@ class Pack {
99
101
  this.itemInfo = new Map();
100
102
  /** @type {string[]} */
101
103
  this.requests = [];
104
+ this.requestsTimeout = undefined;
102
105
  /** @type {Map<string, PackItemInfo>} */
103
106
  this.freshContent = new Map();
104
107
  /** @type {(undefined | PackContent)[]} */
@@ -108,6 +111,16 @@ class Pack {
108
111
  this.maxAge = maxAge;
109
112
  }
110
113
 
114
+ _addRequest(identifier) {
115
+ this.requests.push(identifier);
116
+ if (this.requestsTimeout === undefined) {
117
+ this.requestsTimeout = setTimeout(() => {
118
+ this.requests.push(undefined);
119
+ this.requestsTimeout = undefined;
120
+ }, MAX_TIME_IN_FRESH_PACK);
121
+ }
122
+ }
123
+
111
124
  /**
112
125
  * @param {string} identifier unique name for the resource
113
126
  * @param {string | null} etag etag of the resource
@@ -115,7 +128,7 @@ class Pack {
115
128
  */
116
129
  get(identifier, etag) {
117
130
  const info = this.itemInfo.get(identifier);
118
- this.requests.push(identifier);
131
+ this._addRequest(identifier);
119
132
  if (info === undefined) {
120
133
  return undefined;
121
134
  }
@@ -147,12 +160,12 @@ class Pack {
147
160
  if (info === undefined) {
148
161
  const newInfo = new PackItemInfo(identifier, etag, data);
149
162
  this.itemInfo.set(identifier, newInfo);
150
- this.requests.push(identifier);
163
+ this._addRequest(identifier);
151
164
  this.freshContent.set(identifier, newInfo);
152
165
  } else {
153
166
  const loc = info.location;
154
167
  if (loc >= 0) {
155
- this.requests.push(identifier);
168
+ this._addRequest(identifier);
156
169
  this.freshContent.set(identifier, info);
157
170
  const content = this.content[loc];
158
171
  content.delete(identifier);
@@ -220,27 +233,39 @@ class Pack {
220
233
  }
221
234
 
222
235
  _persistFreshContent() {
223
- if (this.freshContent.size > 0) {
224
- const packCount = Math.ceil(
225
- this.freshContent.size / MAX_ITEMS_IN_FRESH_PACK
226
- );
227
- const itemsPerPack = Math.ceil(this.freshContent.size / packCount);
228
- this.logger.log(`${this.freshContent.size} fresh items in cache`);
229
- const packs = Array.from({ length: packCount }, () => {
236
+ const itemsCount = this.freshContent.size;
237
+ if (itemsCount > 0) {
238
+ const packCount = Math.ceil(itemsCount / MAX_ITEMS_IN_FRESH_PACK);
239
+ const itemsPerPack = Math.ceil(itemsCount / packCount);
240
+ const packs = [];
241
+ let i = 0;
242
+ let ignoreNextTimeTick = false;
243
+ const createNextPack = () => {
230
244
  const loc = this._findLocation();
231
245
  this.content[loc] = null; // reserve
232
- return {
246
+ const pack = {
233
247
  /** @type {Set<string>} */
234
248
  items: new Set(),
235
249
  /** @type {Map<string, any>} */
236
250
  map: new Map(),
237
251
  loc
238
252
  };
239
- });
240
- let i = 0;
241
- let pack = packs[0];
242
- let packIndex = 0;
253
+ packs.push(pack);
254
+ return pack;
255
+ };
256
+ let pack = createNextPack();
257
+ if (this.requestsTimeout !== undefined)
258
+ clearTimeout(this.requestsTimeout);
243
259
  for (const identifier of this.requests) {
260
+ if (identifier === undefined) {
261
+ if (ignoreNextTimeTick) {
262
+ ignoreNextTimeTick = false;
263
+ } else if (pack.items.size >= MIN_ITEMS_IN_FRESH_PACK) {
264
+ i = 0;
265
+ pack = createNextPack();
266
+ }
267
+ continue;
268
+ }
244
269
  const info = this.freshContent.get(identifier);
245
270
  if (info === undefined) continue;
246
271
  pack.items.add(identifier);
@@ -250,9 +275,11 @@ class Pack {
250
275
  this.freshContent.delete(identifier);
251
276
  if (++i > itemsPerPack) {
252
277
  i = 0;
253
- pack = packs[++packIndex];
278
+ pack = createNextPack();
279
+ ignoreNextTimeTick = true;
254
280
  }
255
281
  }
282
+ this.requests.length = 0;
256
283
  for (const pack of packs) {
257
284
  this.content[pack.loc] = new PackContent(
258
285
  pack.items,
@@ -260,6 +287,15 @@ class Pack {
260
287
  new PackContentItems(pack.map)
261
288
  );
262
289
  }
290
+ this.logger.log(
291
+ `${itemsCount} fresh items in cache put into pack ${
292
+ packs.length > 1
293
+ ? packs
294
+ .map(pack => `${pack.loc} (${pack.items.size} items)`)
295
+ .join(", ")
296
+ : packs[0].loc
297
+ }`
298
+ );
263
299
  }
264
300
  }
265
301
 
@@ -332,7 +368,9 @@ class Pack {
332
368
  addToMergedMap.push(async map => {
333
369
  // unpack existing content
334
370
  // after that values are accessible in .content
335
- await content.unpack();
371
+ await content.unpack(
372
+ "it should be merged with other small pack contents"
373
+ );
336
374
  for (const [identifier, value] of content.content) {
337
375
  map.set(identifier, value);
338
376
  }
@@ -392,7 +430,9 @@ class Pack {
392
430
  usedItems,
393
431
  new Set(usedItems),
394
432
  async () => {
395
- await content.unpack();
433
+ await content.unpack(
434
+ "it should be splitted into used and unused items"
435
+ );
396
436
  const map = new Map();
397
437
  for (const identifier of usedItems) {
398
438
  map.set(identifier, content.content.get(identifier));
@@ -417,7 +457,9 @@ class Pack {
417
457
  unusedItems,
418
458
  usedOfUnusedItems,
419
459
  async () => {
420
- await content.unpack();
460
+ await content.unpack(
461
+ "it should be splitted into used and unused items"
462
+ );
421
463
  const map = new Map();
422
464
  for (const identifier of unusedItems) {
423
465
  map.set(identifier, content.content.get(identifier));
@@ -466,7 +508,9 @@ class Pack {
466
508
  this.content[loc] =
467
509
  items.size > 0
468
510
  ? new PackContent(items, usedItems, async () => {
469
- await content.unpack();
511
+ await content.unpack(
512
+ "it contains old items that should be garbage collected"
513
+ );
470
514
  const map = new Map();
471
515
  for (const identifier of items) {
472
516
  map.set(identifier, content.content.get(identifier));
@@ -496,7 +540,7 @@ class Pack {
496
540
  const content = this.content[i];
497
541
  if (content !== undefined) {
498
542
  write(content.items);
499
- writeSeparate(content.getLazyContentItems(), { name: `${i}` });
543
+ content.writeLazy(lazy => writeSeparate(lazy, { name: `${i}` }));
500
544
  } else {
501
545
  write(undefined); // undefined marks an empty content slot
502
546
  }
@@ -669,6 +713,25 @@ makeSerializable(
669
713
  );
670
714
 
671
715
  class PackContent {
716
+ /*
717
+ This class can be in these states:
718
+ | this.lazy | this.content | this.outdated | state
719
+ A1 | undefined | Map | false | fresh content
720
+ A2 | undefined | Map | true | (will not happen)
721
+ B1 | lazy () => {} | undefined | false | not deserialized
722
+ B2 | lazy () => {} | undefined | true | not deserialized, but some items has been removed
723
+ C1 | lazy* () => {} | Map | false | deserialized
724
+ C2 | lazy* () => {} | Map | true | deserialized, and some items has been removed
725
+
726
+ this.used is a subset of this.items.
727
+ this.items is a subset of this.content.keys() resp. this.lazy().map.keys()
728
+ When this.outdated === false, this.items === this.content.keys() resp. this.lazy().map.keys()
729
+ When this.outdated === true, this.items should be used to recreated this.lazy/this.content.
730
+ When this.lazy and this.content is set, they contain the same data.
731
+ this.get must only be called with a valid item from this.items.
732
+ In state C this.lazy is unMemoized
733
+ */
734
+
672
735
  /**
673
736
  * @param {Set<string>} items keys
674
737
  * @param {Set<string>} usedItems used keys
@@ -678,7 +741,7 @@ class PackContent {
678
741
  */
679
742
  constructor(items, usedItems, dataOrFn, logger, lazyName) {
680
743
  this.items = items;
681
- /** @type {function(): Promise<PackContentItems> | PackContentItems } */
744
+ /** @type {function(): Promise<PackContentItems> | PackContentItems} */
682
745
  this.lazy = typeof dataOrFn === "function" ? dataOrFn : undefined;
683
746
  /** @type {Map<string, any>} */
684
747
  this.content = typeof dataOrFn === "function" ? undefined : dataOrFn.map;
@@ -693,6 +756,8 @@ class PackContent {
693
756
  if (this.content) {
694
757
  return this.content.get(identifier);
695
758
  }
759
+
760
+ // We are in state B
696
761
  const { lazyName } = this;
697
762
  let timeMessage;
698
763
  if (lazyName) {
@@ -715,6 +780,7 @@ class PackContent {
715
780
  if (timeMessage) {
716
781
  this.logger.timeEnd(timeMessage);
717
782
  }
783
+ // Move to state C
718
784
  this.content = map;
719
785
  this.lazy = SerializerMiddleware.unMemoizeLazy(this.lazy);
720
786
  return map.get(identifier);
@@ -724,6 +790,7 @@ class PackContent {
724
790
  if (timeMessage) {
725
791
  this.logger.timeEnd(timeMessage);
726
792
  }
793
+ // Move to state C
727
794
  this.content = map;
728
795
  this.lazy = SerializerMiddleware.unMemoizeLazy(this.lazy);
729
796
  return map.get(identifier);
@@ -731,10 +798,13 @@ class PackContent {
731
798
  }
732
799
 
733
800
  /**
801
+ * @param {string} reason explanation why unpack is necessary
734
802
  * @returns {void | Promise} maybe a promise if lazy
735
803
  */
736
- unpack() {
804
+ unpack(reason) {
737
805
  if (this.content) return;
806
+
807
+ // Move from state B to C
738
808
  if (this.lazy) {
739
809
  const { lazyName } = this;
740
810
  let timeMessage;
@@ -744,6 +814,11 @@ class PackContent {
744
814
  timeMessage = `unpack cache content ${lazyName} (${formatSize(
745
815
  this.getSize()
746
816
  )})`;
817
+ this.logger.log(
818
+ `starting to unpack cache content ${lazyName} (${formatSize(
819
+ this.getSize()
820
+ )}) because ${reason}`
821
+ );
747
822
  this.logger.time(timeMessage);
748
823
  }
749
824
  const value = this.lazy();
@@ -782,48 +857,93 @@ class PackContent {
782
857
  }
783
858
 
784
859
  /**
785
- * @returns {function(): PackContentItems | Promise<PackContentItems>} lazy content items
860
+ * @template T
861
+ * @param {function(any): function(): Promise<PackContentItems> | PackContentItems} write write function
862
+ * @returns {void}
786
863
  */
787
- getLazyContentItems() {
788
- if (!this.outdated && this.lazy) return this.lazy;
864
+ writeLazy(write) {
865
+ if (!this.outdated && this.lazy) {
866
+ // State B1 or C1
867
+ // this.lazy is still the valid deserialized version
868
+ write(this.lazy);
869
+ return;
870
+ }
789
871
  if (!this.outdated && this.content) {
872
+ // State A1
790
873
  const map = new Map(this.content);
791
- return (this.lazy = memoize(() => new PackContentItems(map)));
874
+ // Move to state C1
875
+ this.lazy = SerializerMiddleware.unMemoizeLazy(
876
+ write(() => new PackContentItems(map))
877
+ );
878
+ return;
792
879
  }
793
- this.outdated = false;
794
880
  if (this.content) {
795
- return (this.lazy = memoize(() => {
796
- /** @type {Map<string, any>} */
797
- const map = new Map();
798
- for (const item of this.items) {
799
- map.set(item, this.content.get(item));
800
- }
801
- return new PackContentItems(map);
802
- }));
881
+ // State A2 or C2
882
+ /** @type {Map<string, any>} */
883
+ const map = new Map();
884
+ for (const item of this.items) {
885
+ map.set(item, this.content.get(item));
886
+ }
887
+ // Move to state C1
888
+ this.outdated = false;
889
+ this.content = map;
890
+ this.lazy = SerializerMiddleware.unMemoizeLazy(
891
+ write(() => new PackContentItems(map))
892
+ );
893
+ return;
803
894
  }
804
- const lazy = this.lazy;
805
- return (this.lazy = () => {
806
- const value = lazy();
807
- if (value instanceof Promise) {
808
- return value.then(data => {
895
+ // State B2
896
+ const { lazyName } = this;
897
+ let timeMessage;
898
+ if (lazyName) {
899
+ // only log once
900
+ this.lazyName = undefined;
901
+ timeMessage = `unpack cache content ${lazyName} (${formatSize(
902
+ this.getSize()
903
+ )})`;
904
+ this.logger.log(
905
+ `starting to unpack cache content ${lazyName} (${formatSize(
906
+ this.getSize()
907
+ )}) because it's outdated and need to be serialized`
908
+ );
909
+ this.logger.time(timeMessage);
910
+ }
911
+ const value = this.lazy();
912
+ this.outdated = false;
913
+ if (value instanceof Promise) {
914
+ // Move to state B1
915
+ this.lazy = write(() =>
916
+ value.then(data => {
917
+ if (timeMessage) {
918
+ this.logger.timeEnd(timeMessage);
919
+ }
809
920
  const oldMap = data.map;
810
921
  /** @type {Map<string, any>} */
811
922
  const map = new Map();
812
923
  for (const item of this.items) {
813
924
  map.set(item, oldMap.get(item));
814
925
  }
926
+ // Move to state C1 (or maybe C2)
927
+ this.content = map;
928
+ this.lazy = SerializerMiddleware.unMemoizeLazy(this.lazy);
929
+
815
930
  return new PackContentItems(map);
816
- });
817
- } else {
818
- const oldMap = value.map;
819
- /** @type {Map<string, any>} */
820
- const map = new Map();
821
- for (const item of this.items) {
822
- map.set(item, oldMap.get(item));
823
- }
824
- return new PackContentItems(map);
931
+ })
932
+ );
933
+ } else {
934
+ // Move to state C1
935
+ if (timeMessage) {
936
+ this.logger.timeEnd(timeMessage);
825
937
  }
826
- });
938
+ const oldMap = value.map;
939
+ /** @type {Map<string, any>} */
940
+ const map = new Map();
941
+ for (const item of this.items) {
942
+ map.set(item, oldMap.get(item));
943
+ }
944
+ this.content = map;
945
+ this.lazy = write(() => new PackContentItems(map));
946
+ }
827
947
  }
828
948
  }
829
949
 
@@ -1110,10 +1230,10 @@ class PackFileCacheStrategy {
1110
1230
  const packPromise = this.packPromise;
1111
1231
  if (packPromise === undefined) return Promise.resolve();
1112
1232
  const reportProgress = ProgressPlugin.getReporter(this.compiler);
1113
- this.packPromise = undefined;
1114
1233
  return (this.storePromise = packPromise
1115
1234
  .then(pack => {
1116
1235
  if (!pack.invalid) return;
1236
+ this.packPromise = undefined;
1117
1237
  this.logger.log(`Storing pack...`);
1118
1238
  let promise;
1119
1239
  const newBuildDependencies = new Set();
@@ -259,7 +259,6 @@ const applyExperimentsDefaults = (experiments, { production, development }) => {
259
259
  D(experiments, "asyncWebAssembly", false);
260
260
  D(experiments, "outputModule", false);
261
261
  D(experiments, "asset", false);
262
- D(experiments, "executeModule", false);
263
262
  D(experiments, "layers", false);
264
263
  D(experiments, "lazyCompilation", false);
265
264
  D(experiments, "buildHttp", false);
@@ -1039,7 +1039,9 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1039
1039
  ids,
1040
1040
  runtimeRequirements
1041
1041
  ),
1042
- InitFragment.STAGE_HARMONY_IMPORTS,
1042
+ moduleGraph.isAsync(importedModule)
1043
+ ? InitFragment.STAGE_ASYNC_HARMONY_IMPORTS
1044
+ : InitFragment.STAGE_HARMONY_IMPORTS,
1043
1045
  dep.sourceOrder
1044
1046
  )
1045
1047
  );
@@ -1100,7 +1102,9 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1100
1102
  initFragments.push(
1101
1103
  new InitFragment(
1102
1104
  `${content}\n/* harmony reexport (unknown) */ ${RuntimeGlobals.definePropertyGetters}(${exportsName}, __WEBPACK_REEXPORT_OBJECT__);\n`,
1103
- InitFragment.STAGE_HARMONY_IMPORTS,
1105
+ moduleGraph.isAsync(importedModule)
1106
+ ? InitFragment.STAGE_ASYNC_HARMONY_IMPORTS
1107
+ : InitFragment.STAGE_HARMONY_IMPORTS,
1104
1108
  dep.sourceOrder
1105
1109
  )
1106
1110
  );
@@ -37,11 +37,9 @@ const LoaderImportDependency = require("./LoaderImportDependency");
37
37
  class LoaderPlugin {
38
38
  /**
39
39
  * @param {Object} options options
40
- * @param {boolean=} options.enableExecuteModule execute module enabled
41
40
  */
42
- constructor(options = {}) {
43
- this._enableExecuteModule = !!options.enableExecuteModule;
44
- }
41
+ constructor(options = {}) {}
42
+
45
43
  /**
46
44
  * Apply the plugin
47
45
  * @param {Compiler} compiler the compiler instance
@@ -155,106 +153,104 @@ class LoaderPlugin {
155
153
  );
156
154
  };
157
155
 
158
- if (this._enableExecuteModule) {
159
- /**
160
- * @param {string} request the request string to load the module from
161
- * @param {ImportModuleOptions=} options options
162
- * @param {ImportModuleCallback=} callback callback returning the exports
163
- * @returns {void}
164
- */
165
- const importModule = (request, options, callback) => {
166
- const dep = new LoaderImportDependency(request);
167
- dep.loc = {
168
- name: request
169
- };
170
- const factory = compilation.dependencyFactories.get(
171
- /** @type {DepConstructor} */ (dep.constructor)
156
+ /**
157
+ * @param {string} request the request string to load the module from
158
+ * @param {ImportModuleOptions=} options options
159
+ * @param {ImportModuleCallback=} callback callback returning the exports
160
+ * @returns {void}
161
+ */
162
+ const importModule = (request, options, callback) => {
163
+ const dep = new LoaderImportDependency(request);
164
+ dep.loc = {
165
+ name: request
166
+ };
167
+ const factory = compilation.dependencyFactories.get(
168
+ /** @type {DepConstructor} */ (dep.constructor)
169
+ );
170
+ if (factory === undefined) {
171
+ return callback(
172
+ new Error(
173
+ `No module factory available for dependency type: ${dep.constructor.name}`
174
+ )
172
175
  );
173
- if (factory === undefined) {
174
- return callback(
175
- new Error(
176
- `No module factory available for dependency type: ${dep.constructor.name}`
177
- )
178
- );
179
- }
180
- compilation.buildQueue.increaseParallelism();
181
- compilation.handleModuleCreation(
182
- {
183
- factory,
184
- dependencies: [dep],
185
- originModule: loaderContext._module,
186
- contextInfo: {
187
- issuerLayer: options.layer
188
- },
189
- context: loaderContext.context,
190
- connectOrigin: false
176
+ }
177
+ compilation.buildQueue.increaseParallelism();
178
+ compilation.handleModuleCreation(
179
+ {
180
+ factory,
181
+ dependencies: [dep],
182
+ originModule: loaderContext._module,
183
+ contextInfo: {
184
+ issuerLayer: options.layer
191
185
  },
192
- err => {
193
- compilation.buildQueue.decreaseParallelism();
194
- if (err) {
195
- return callback(err);
196
- }
197
- const referencedModule = moduleGraph.getModule(dep);
198
- if (!referencedModule) {
199
- return callback(new Error("Cannot load the module"));
200
- }
201
- compilation.executeModule(
202
- referencedModule,
203
- {
204
- entryOptions: {
205
- publicPath: options.publicPath
206
- }
207
- },
208
- (err, result) => {
209
- if (err) return callback(err);
210
- for (const d of result.fileDependencies) {
211
- loaderContext.addDependency(d);
212
- }
213
- for (const d of result.contextDependencies) {
214
- loaderContext.addContextDependency(d);
215
- }
216
- for (const d of result.missingDependencies) {
217
- loaderContext.addMissingDependency(d);
218
- }
219
- for (const d of result.buildDependencies) {
220
- loaderContext.addBuildDependency(d);
221
- }
222
- if (result.cacheable === false)
223
- loaderContext.cacheable(false);
224
- for (const [name, { source, info }] of result.assets) {
225
- const { buildInfo } = loaderContext._module;
226
- if (!buildInfo.assets) {
227
- buildInfo.assets = Object.create(null);
228
- buildInfo.assetsInfo = new Map();
229
- }
230
- buildInfo.assets[name] = source;
231
- buildInfo.assetsInfo.set(name, info);
186
+ context: loaderContext.context,
187
+ connectOrigin: false
188
+ },
189
+ err => {
190
+ compilation.buildQueue.decreaseParallelism();
191
+ if (err) {
192
+ return callback(err);
193
+ }
194
+ const referencedModule = moduleGraph.getModule(dep);
195
+ if (!referencedModule) {
196
+ return callback(new Error("Cannot load the module"));
197
+ }
198
+ compilation.executeModule(
199
+ referencedModule,
200
+ {
201
+ entryOptions: {
202
+ publicPath: options.publicPath
203
+ }
204
+ },
205
+ (err, result) => {
206
+ if (err) return callback(err);
207
+ for (const d of result.fileDependencies) {
208
+ loaderContext.addDependency(d);
209
+ }
210
+ for (const d of result.contextDependencies) {
211
+ loaderContext.addContextDependency(d);
212
+ }
213
+ for (const d of result.missingDependencies) {
214
+ loaderContext.addMissingDependency(d);
215
+ }
216
+ for (const d of result.buildDependencies) {
217
+ loaderContext.addBuildDependency(d);
218
+ }
219
+ if (result.cacheable === false)
220
+ loaderContext.cacheable(false);
221
+ for (const [name, { source, info }] of result.assets) {
222
+ const { buildInfo } = loaderContext._module;
223
+ if (!buildInfo.assets) {
224
+ buildInfo.assets = Object.create(null);
225
+ buildInfo.assetsInfo = new Map();
232
226
  }
233
- callback(null, result.exports);
227
+ buildInfo.assets[name] = source;
228
+ buildInfo.assetsInfo.set(name, info);
234
229
  }
235
- );
236
- }
237
- );
238
- };
230
+ callback(null, result.exports);
231
+ }
232
+ );
233
+ }
234
+ );
235
+ };
239
236
 
240
- /**
241
- * @param {string} request the request string to load the module from
242
- * @param {ImportModuleOptions} options options
243
- * @param {ImportModuleCallback=} callback callback returning the exports
244
- * @returns {Promise<any> | void} exports
245
- */
246
- loaderContext.importModule = (request, options, callback) => {
247
- if (!callback) {
248
- return new Promise((resolve, reject) => {
249
- importModule(request, options || {}, (err, result) => {
250
- if (err) reject(err);
251
- else resolve(result);
252
- });
237
+ /**
238
+ * @param {string} request the request string to load the module from
239
+ * @param {ImportModuleOptions} options options
240
+ * @param {ImportModuleCallback=} callback callback returning the exports
241
+ * @returns {Promise<any> | void} exports
242
+ */
243
+ loaderContext.importModule = (request, options, callback) => {
244
+ if (!callback) {
245
+ return new Promise((resolve, reject) => {
246
+ importModule(request, options || {}, (err, result) => {
247
+ if (err) reject(err);
248
+ else resolve(result);
253
249
  });
254
- }
255
- return importModule(request, options || {}, callback);
256
- };
257
- }
250
+ });
251
+ }
252
+ return importModule(request, options || {}, callback);
253
+ };
258
254
  }
259
255
  );
260
256
  });
@@ -78,6 +78,10 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
78
78
  const result = new ConcatSource(source);
79
79
  const exportsInfo = moduleGraph.getExportsInfo(module);
80
80
  const exports = [];
81
+ const isAsync = moduleGraph.isAsync(module);
82
+ if (isAsync) {
83
+ result.add(`__webpack_exports__ = await __webpack_exports__;\n`);
84
+ }
81
85
  for (const exportInfo of exportsInfo.orderedExports) {
82
86
  if (!exportInfo.provided) continue;
83
87
  const varName = `__webpack_exports__${Template.toIdentifier(