webpack 5.21.0 → 5.23.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.

Files changed (61) hide show
  1. package/lib/ChunkGraph.js +3 -2
  2. package/lib/CodeGenerationResults.js +2 -1
  3. package/lib/Compilation.js +91 -40
  4. package/lib/EvalDevToolModulePlugin.js +4 -0
  5. package/lib/EvalSourceMapDevToolPlugin.js +4 -0
  6. package/lib/ExportsInfo.js +1 -0
  7. package/lib/ExternalModule.js +8 -7
  8. package/lib/FlagDependencyUsagePlugin.js +7 -6
  9. package/lib/JavascriptMetaInfoPlugin.js +62 -0
  10. package/lib/LibManifestPlugin.js +1 -13
  11. package/lib/Module.js +2 -3
  12. package/lib/MultiCompiler.js +170 -77
  13. package/lib/MultiStats.js +9 -6
  14. package/lib/NormalModuleFactory.js +135 -22
  15. package/lib/RuntimeGlobals.js +5 -0
  16. package/lib/RuntimePlugin.js +10 -1
  17. package/lib/Watching.js +70 -27
  18. package/lib/WebpackOptionsApply.js +7 -7
  19. package/lib/config/defaults.js +26 -10
  20. package/lib/config/target.js +1 -1
  21. package/lib/container/ContainerEntryModule.js +2 -1
  22. package/lib/dependencies/AMDDefineDependency.js +1 -1
  23. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +8 -0
  24. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +2 -1
  25. package/lib/dependencies/HarmonyExportInitFragment.js +2 -3
  26. package/lib/dependencies/HarmonyImportSpecifierDependency.js +9 -2
  27. package/lib/dependencies/LoaderPlugin.js +9 -2
  28. package/lib/dependencies/URLDependency.js +35 -13
  29. package/lib/dependencies/URLPlugin.js +3 -1
  30. package/lib/dependencies/WorkerPlugin.js +7 -1
  31. package/lib/hmr/LazyCompilationPlugin.js +2 -2
  32. package/lib/index.js +1 -0
  33. package/lib/javascript/CommonJsChunkFormatPlugin.js +15 -4
  34. package/lib/javascript/JavascriptModulesPlugin.js +143 -78
  35. package/lib/javascript/JavascriptParser.js +1 -0
  36. package/lib/json/JsonGenerator.js +29 -8
  37. package/lib/library/AbstractLibraryPlugin.js +108 -32
  38. package/lib/library/AmdLibraryPlugin.js +12 -6
  39. package/lib/library/AssignLibraryPlugin.js +137 -26
  40. package/lib/library/EnableLibraryPlugin.js +18 -7
  41. package/lib/library/ExportPropertyLibraryPlugin.js +16 -5
  42. package/lib/library/JsonpLibraryPlugin.js +3 -1
  43. package/lib/library/ModuleLibraryPlugin.js +100 -0
  44. package/lib/library/SystemLibraryPlugin.js +1 -1
  45. package/lib/node/NodeTargetPlugin.js +1 -1
  46. package/lib/optimize/ConcatenatedModule.js +54 -35
  47. package/lib/optimize/InnerGraph.js +5 -4
  48. package/lib/runtime/GetChunkFilenameRuntimeModule.js +2 -3
  49. package/lib/runtime/RelativeUrlRuntimeModule.js +41 -0
  50. package/lib/runtime/StartupChunkDependenciesPlugin.js +1 -0
  51. package/lib/serialization/ObjectMiddleware.js +34 -19
  52. package/lib/stats/DefaultStatsFactoryPlugin.js +1 -12
  53. package/lib/stats/DefaultStatsPrinterPlugin.js +19 -6
  54. package/lib/util/IterableHelpers.js +46 -0
  55. package/lib/util/LazyBucketSortedSet.js +3 -2
  56. package/lib/util/SetHelpers.js +11 -0
  57. package/lib/webpack.js +56 -50
  58. package/package.json +3 -3
  59. package/schemas/WebpackOptions.json +8 -1
  60. package/types.d.ts +38 -7
  61. package/lib/FlagUsingEvalPlugin.js +0 -44
@@ -18,6 +18,7 @@ const { tryRunOrWebpackError } = require("../HookWebpackError");
18
18
  const HotUpdateChunk = require("../HotUpdateChunk");
19
19
  const RuntimeGlobals = require("../RuntimeGlobals");
20
20
  const Template = require("../Template");
21
+ const { last, someInIterable } = require("../util/IterableHelpers");
21
22
  const StringXor = require("../util/StringXor");
22
23
  const { compareModulesByIdentifier } = require("../util/comparators");
23
24
  const createHash = require("../util/createHash");
@@ -37,19 +38,6 @@ const JavascriptParser = require("./JavascriptParser");
37
38
  /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
38
39
  /** @typedef {import("../util/Hash")} Hash */
39
40
 
40
- /**
41
- * @template T
42
- * @param {Iterable<T>} iterable iterable
43
- * @param {function(T): boolean} filter predicate
44
- * @returns {boolean} true, if some items match the filter predicate
45
- */
46
- const someInIterable = (iterable, filter) => {
47
- for (const item of iterable) {
48
- if (filter(item)) return true;
49
- }
50
- return false;
51
- };
52
-
53
41
  /**
54
42
  * @param {Chunk} chunk a chunk
55
43
  * @param {ChunkGraph} chunkGraph the chunk graph
@@ -93,6 +81,8 @@ const chunkHasJs = (chunk, chunkGraph) => {
93
81
  * @property {string} hash hash to be used for render call
94
82
  */
95
83
 
84
+ /** @typedef {RenderContext & { inlined: boolean }} StartupRenderContext */
85
+
96
86
  /**
97
87
  * @typedef {Object} CompilationHooks
98
88
  * @property {SyncWaterfallHook<[Source, Module, RenderContext]>} renderModuleContent
@@ -101,7 +91,10 @@ const chunkHasJs = (chunk, chunkGraph) => {
101
91
  * @property {SyncWaterfallHook<[Source, RenderContext]>} renderChunk
102
92
  * @property {SyncWaterfallHook<[Source, RenderContext]>} renderMain
103
93
  * @property {SyncWaterfallHook<[Source, RenderContext]>} render
94
+ * @property {SyncWaterfallHook<[Source, Module, StartupRenderContext]>} renderStartup
104
95
  * @property {SyncWaterfallHook<[string, RenderBootstrapContext]>} renderRequire
96
+ * @property {SyncBailHook<[Module, RenderBootstrapContext], string>} inlineInRuntimeBailout
97
+ * @property {SyncBailHook<[Module, RenderContext], string>} embedInRuntimeBailout
105
98
  * @property {SyncHook<[Chunk, Hash, ChunkHashContext]>} chunkHash
106
99
  * @property {SyncBailHook<[Chunk, RenderContext], boolean>} useSourceMap
107
100
  */
@@ -139,9 +132,16 @@ class JavascriptModulesPlugin {
139
132
  "renderContext"
140
133
  ]),
141
134
  render: new SyncWaterfallHook(["source", "renderContext"]),
135
+ renderStartup: new SyncWaterfallHook([
136
+ "source",
137
+ "module",
138
+ "startupRenderContext"
139
+ ]),
142
140
  renderChunk: new SyncWaterfallHook(["source", "renderContext"]),
143
141
  renderMain: new SyncWaterfallHook(["source", "renderContext"]),
144
142
  renderRequire: new SyncWaterfallHook(["code", "renderContext"]),
143
+ inlineInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
144
+ embedInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
145
145
  chunkHash: new SyncHook(["chunk", "hash", "context"]),
146
146
  useSourceMap: new SyncBailHook(["chunk", "renderContext"])
147
147
  };
@@ -641,6 +641,9 @@ class JavascriptModulesPlugin {
641
641
  )
642
642
  );
643
643
  }
644
+ const lastInlinedModule = last(inlinedModules);
645
+ const startupSource = new ConcatSource();
646
+ startupSource.add(`var __webpack_exports__ = {};\n`);
644
647
  for (const m of inlinedModules) {
645
648
  const renderedModule = this.renderModule(
646
649
  m,
@@ -650,25 +653,59 @@ class JavascriptModulesPlugin {
650
653
  );
651
654
  if (renderedModule) {
652
655
  const innerStrict = !allStrict && m.buildInfo.strict;
653
- const iife = innerStrict || inlinedModules.size > 1 || chunkModules;
654
- if (iife) {
655
- if (runtimeTemplate.supportsArrowFunction()) {
656
- source.add("(() => {\n");
657
- if (innerStrict) source.add('"use strict";\n');
658
- source.add(renderedModule);
659
- source.add("\n})();\n\n");
656
+ const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
657
+ m,
658
+ chunk.runtime
659
+ );
660
+ const exports = runtimeRequirements.has(RuntimeGlobals.exports);
661
+ const webpackExports =
662
+ exports && m.exportsArgument === "__webpack_exports__";
663
+ let iife = innerStrict
664
+ ? "it need to be in strict mode."
665
+ : inlinedModules.size > 1
666
+ ? // TODO check globals and top-level declarations of other entries and chunk modules
667
+ // to make a better decision
668
+ "it need to be isolated against other entry modules."
669
+ : chunkModules
670
+ ? "it need to be isolated against other modules in the chunk."
671
+ : exports && !webpackExports
672
+ ? `it uses a non-standard name for the exports (${m.exportsArgument}).`
673
+ : hooks.embedInRuntimeBailout.call(m, renderContext);
674
+ let footer;
675
+ if (iife !== undefined) {
676
+ startupSource.add(
677
+ `// This entry need to be wrapped in an IIFE because ${iife}\n`
678
+ );
679
+ const arrow = runtimeTemplate.supportsArrowFunction();
680
+ if (arrow) {
681
+ startupSource.add("(() => {\n");
682
+ footer = "\n})();\n\n";
660
683
  } else {
661
- source.add("!function() {\n");
662
- if (innerStrict) source.add('"use strict";\n');
663
- source.add(renderedModule);
664
- source.add("\n}();\n");
684
+ startupSource.add("!function() {\n");
685
+ footer = "\n}();\n";
665
686
  }
687
+ if (innerStrict) startupSource.add('"use strict";\n');
666
688
  } else {
667
- source.add(renderedModule);
668
- source.add("\n");
689
+ footer = "\n";
690
+ }
691
+ if (exports) {
692
+ if (m !== lastInlinedModule)
693
+ startupSource.add(`var ${m.exportsArgument} = {};\n`);
694
+ else if (m.exportsArgument !== "__webpack_exports__")
695
+ startupSource.add(
696
+ `var ${m.exportsArgument} = __webpack_exports__;\n`
697
+ );
669
698
  }
699
+ startupSource.add(renderedModule);
700
+ startupSource.add(footer);
670
701
  }
671
702
  }
703
+ source.add(
704
+ hooks.renderStartup.call(startupSource, lastInlinedModule, {
705
+ ...renderContext,
706
+ inlined: true
707
+ })
708
+ );
672
709
  if (bootstrap.afterStartup.length > 0) {
673
710
  const afterStartup = Template.asString(bootstrap.afterStartup) + "\n";
674
711
  source.add(
@@ -681,21 +718,36 @@ class JavascriptModulesPlugin {
681
718
  );
682
719
  }
683
720
  } else {
684
- const startup =
685
- Template.asString([
686
- ...bootstrap.beforeStartup,
687
- ...bootstrap.startup,
688
- ...bootstrap.afterStartup
689
- ]) + "\n";
721
+ const lastEntryModule = last(
722
+ chunkGraph.getChunkEntryModulesIterable(chunk)
723
+ );
724
+ const toSource = useSourceMap
725
+ ? (content, name) =>
726
+ new OriginalSource(Template.asString(content), name)
727
+ : content => new RawSource(Template.asString(content));
690
728
  source.add(
691
729
  new PrefixSource(
692
730
  prefix,
693
- useSourceMap
694
- ? new OriginalSource(startup, "webpack/startup")
695
- : new RawSource(startup)
731
+ new ConcatSource(
732
+ toSource(bootstrap.beforeStartup, "webpack/before-startup"),
733
+ "\n",
734
+ hooks.renderStartup.call(
735
+ toSource(bootstrap.startup.concat(""), "webpack/startup"),
736
+ lastEntryModule,
737
+ {
738
+ ...renderContext,
739
+ inlined: false
740
+ }
741
+ ),
742
+ toSource(bootstrap.afterStartup, "webpack/after-startup"),
743
+ "\n"
744
+ )
696
745
  )
697
746
  );
698
747
  }
748
+ if (runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime)) {
749
+ source.add(`${prefix}return __webpack_exports__;\n`);
750
+ }
699
751
  if (iife) {
700
752
  source.add("/******/ })()\n");
701
753
  }
@@ -758,23 +810,15 @@ class JavascriptModulesPlugin {
758
810
  RuntimeGlobals.moduleFactories
759
811
  );
760
812
  const moduleUsed = runtimeRequirements.has(RuntimeGlobals.module);
761
- const exportsUsed = runtimeRequirements.has(RuntimeGlobals.exports);
762
813
  const requireScopeUsed = runtimeRequirements.has(
763
814
  RuntimeGlobals.requireScope
764
815
  );
765
816
  const interceptModuleExecution = runtimeRequirements.has(
766
817
  RuntimeGlobals.interceptModuleExecution
767
818
  );
768
- const returnExportsFromRuntime = runtimeRequirements.has(
769
- RuntimeGlobals.returnExportsFromRuntime
770
- );
771
819
 
772
820
  const useRequire =
773
- requireFunction ||
774
- interceptModuleExecution ||
775
- returnExportsFromRuntime ||
776
- moduleUsed ||
777
- exportsUsed;
821
+ requireFunction || interceptModuleExecution || moduleUsed;
778
822
 
779
823
  const result = {
780
824
  header: [],
@@ -802,12 +846,6 @@ class JavascriptModulesPlugin {
802
846
  );
803
847
  result.allowInlineStartup = false;
804
848
  }
805
- if (result.allowInlineStartup && returnExportsFromRuntime) {
806
- startup.push(
807
- "// module exports must be returned from runtime so entry inlining is disabled"
808
- );
809
- result.allowInlineStartup = false;
810
- }
811
849
 
812
850
  if (useRequire || moduleCache) {
813
851
  buf.push("// The module cache");
@@ -848,7 +886,6 @@ class JavascriptModulesPlugin {
848
886
  buf.push("");
849
887
  }
850
888
 
851
- const maybeReturn = returnExportsFromRuntime ? "return " : "";
852
889
  if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
853
890
  if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
854
891
  /** @type {string[]} */
@@ -856,11 +893,7 @@ class JavascriptModulesPlugin {
856
893
  const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(
857
894
  chunk
858
895
  );
859
- buf2.push(
860
- returnExportsFromRuntime
861
- ? "// Load entry module and return exports"
862
- : "// Load entry module"
863
- );
896
+ buf2.push("// Load entry module and return exports");
864
897
  let i = chunkGraph.getNumberOfEntryModules(chunk);
865
898
  for (const entryModule of chunkGraph.getChunkEntryModulesIterable(
866
899
  chunk
@@ -884,8 +917,29 @@ class JavascriptModulesPlugin {
884
917
  );
885
918
  result.allowInlineStartup = false;
886
919
  }
887
- const mayReturn =
888
- --i === 0 && returnExportsFromRuntime ? "return " : "";
920
+ if (
921
+ result.allowInlineStartup &&
922
+ (!entryModule.buildInfo ||
923
+ !entryModule.buildInfo.topLevelDeclarations)
924
+ ) {
925
+ buf2.push(
926
+ "// This entry module doesn't tell about it's top-level declarations so it can't be inlined"
927
+ );
928
+ result.allowInlineStartup = false;
929
+ }
930
+ if (result.allowInlineStartup) {
931
+ const bailout = hooks.inlineInRuntimeBailout.call(
932
+ entryModule,
933
+ renderContext
934
+ );
935
+ if (bailout !== undefined) {
936
+ buf2.push(
937
+ `// This entry module can't be inlined because ${bailout}`
938
+ );
939
+ result.allowInlineStartup = false;
940
+ }
941
+ }
942
+ i--;
889
943
  const moduleId = chunkGraph.getModuleId(entryModule);
890
944
  const entryRuntimeRequirements = chunkGraph.getModuleRuntimeRequirements(
891
945
  entryModule,
@@ -896,45 +950,56 @@ class JavascriptModulesPlugin {
896
950
  moduleIdExpr = `${RuntimeGlobals.entryModuleId} = ${moduleIdExpr}`;
897
951
  }
898
952
  if (useRequire) {
899
- buf2.push(`${mayReturn}__webpack_require__(${moduleIdExpr});`);
953
+ buf2.push(
954
+ `${
955
+ i === 0 ? "var __webpack_exports__ = " : ""
956
+ }__webpack_require__(${moduleIdExpr});`
957
+ );
900
958
  if (result.allowInlineStartup) {
901
959
  if (entryRuntimeRequirements.has(RuntimeGlobals.module)) {
902
960
  result.allowInlineStartup = false;
903
961
  buf2.push(
904
962
  "// This entry module used 'module' so it can't be inlined"
905
963
  );
906
- } else if (entryRuntimeRequirements.has(RuntimeGlobals.exports)) {
907
- buf2.push(
908
- "// This entry module used 'exports' so it can't be inlined"
909
- );
910
- result.allowInlineStartup = false;
911
964
  }
912
965
  }
913
- } else if (requireScopeUsed) {
914
- buf2.push(
915
- `__webpack_modules__[${moduleIdExpr}](0, 0, __webpack_require__);`
916
- );
917
966
  } else {
918
- buf2.push(`__webpack_modules__[${moduleIdExpr}]();`);
967
+ if (i === 0) buf2.push("var __webpack_exports__ = {};");
968
+ if (requireScopeUsed) {
969
+ buf2.push(
970
+ `__webpack_modules__[${moduleIdExpr}](0, ${
971
+ i === 0 ? "__webpack_exports__" : "{}"
972
+ }, __webpack_require__);`
973
+ );
974
+ } else if (entryRuntimeRequirements.has(RuntimeGlobals.exports)) {
975
+ buf2.push(
976
+ `__webpack_modules__[${moduleIdExpr}](0, ${
977
+ i === 0 ? "__webpack_exports__" : "{}"
978
+ });`
979
+ );
980
+ } else {
981
+ buf2.push(`__webpack_modules__[${moduleIdExpr}]();`);
982
+ }
919
983
  }
920
984
  }
921
985
  if (
922
986
  runtimeRequirements.has(RuntimeGlobals.startup) ||
923
- ((returnExportsFromRuntime ||
924
- runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) &&
987
+ (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) &&
925
988
  runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter))
926
989
  ) {
927
990
  result.allowInlineStartup = false;
928
991
  buf.push("// the startup function");
929
992
  buf.push(
930
- `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction(
931
- "",
932
- buf2
933
- )};`
993
+ `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction("", [
994
+ ...buf2,
995
+ "return __webpack_exports__;"
996
+ ])};`
934
997
  );
935
998
  buf.push("");
936
999
  startup.push("// run startup");
937
- startup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
1000
+ startup.push(
1001
+ `var __webpack_exports__ = ${RuntimeGlobals.startup}();`
1002
+ );
938
1003
  } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
939
1004
  buf.push("// the startup function");
940
1005
  buf.push(
@@ -952,7 +1017,7 @@ class JavascriptModulesPlugin {
952
1017
  startup.push("// startup");
953
1018
  startup.push(Template.asString(buf2));
954
1019
  afterStartup.push("// run runtime startup");
955
- afterStartup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
1020
+ afterStartup.push(`${RuntimeGlobals.startup}();`);
956
1021
  } else {
957
1022
  startup.push("// startup");
958
1023
  startup.push(Template.asString(buf2));
@@ -981,7 +1046,7 @@ class JavascriptModulesPlugin {
981
1046
  `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
982
1047
  );
983
1048
  startup.push("// run startup");
984
- startup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
1049
+ startup.push(`var __webpack_exports__ = ${RuntimeGlobals.startup}();`);
985
1050
  }
986
1051
  return result;
987
1052
  }
@@ -224,6 +224,7 @@ class JavascriptParser extends Parser {
224
224
  varDeclarationConst: new HookMap(() => new SyncBailHook(["declaration"])),
225
225
  /** @type {HookMap<SyncBailHook<[DeclarationNode], boolean | void>>} */
226
226
  varDeclarationVar: new HookMap(() => new SyncBailHook(["declaration"])),
227
+ /** @type {HookMap<SyncBailHook<[IdentifierNode], boolean | void>>} */
227
228
  pattern: new HookMap(() => new SyncBailHook(["pattern"])),
228
229
  /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
229
230
  canRename: new HookMap(() => new SyncBailHook(["initExpression"])),
@@ -38,14 +38,13 @@ const stringifySafe = data => {
38
38
  const createObjectForExportsInfo = (data, exportsInfo, runtime) => {
39
39
  if (exportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused)
40
40
  return data;
41
- const reducedData = Array.isArray(data) ? [] : {};
42
- for (const exportInfo of exportsInfo.exports) {
43
- if (exportInfo.name in reducedData) return data;
44
- }
41
+ const isArray = Array.isArray(data);
42
+ const reducedData = isArray ? [] : {};
45
43
  for (const key of Object.keys(data)) {
46
44
  const exportInfo = exportsInfo.getReadOnlyExportInfo(key);
47
45
  const used = exportInfo.getUsed(runtime);
48
46
  if (used === UsageState.Unused) continue;
47
+
49
48
  let value;
50
49
  if (used === UsageState.OnlyPropertiesUsed && exportInfo.exportsInfo) {
51
50
  value = createObjectForExportsInfo(
@@ -59,7 +58,13 @@ const createObjectForExportsInfo = (data, exportsInfo, runtime) => {
59
58
  const name = exportInfo.getUsedName(key, runtime);
60
59
  reducedData[name] = value;
61
60
  }
62
- if (Array.isArray(reducedData)) {
61
+ if (isArray) {
62
+ let arrayLengthWhenUsed =
63
+ exportsInfo.getReadOnlyExportInfo("length").getUsed(runtime) !==
64
+ UsageState.Unused
65
+ ? data.length
66
+ : undefined;
67
+
63
68
  let sizeObjectMinusArray = 0;
64
69
  for (let i = 0; i < reducedData.length; i++) {
65
70
  if (reducedData[i] === undefined) {
@@ -68,8 +73,24 @@ const createObjectForExportsInfo = (data, exportsInfo, runtime) => {
68
73
  sizeObjectMinusArray += `${i}`.length + 3;
69
74
  }
70
75
  }
71
- if (sizeObjectMinusArray < 0) return Object.assign({}, reducedData);
72
- for (let i = 0; i < reducedData.length; i++) {
76
+ if (arrayLengthWhenUsed !== undefined) {
77
+ sizeObjectMinusArray +=
78
+ `${arrayLengthWhenUsed}`.length +
79
+ 8 -
80
+ (arrayLengthWhenUsed - reducedData.length) * 2;
81
+ }
82
+ if (sizeObjectMinusArray < 0)
83
+ return Object.assign(
84
+ arrayLengthWhenUsed === undefined
85
+ ? {}
86
+ : { length: arrayLengthWhenUsed },
87
+ reducedData
88
+ );
89
+ const generatedLength =
90
+ arrayLengthWhenUsed !== undefined
91
+ ? Math.max(arrayLengthWhenUsed, reducedData.length)
92
+ : reducedData.length;
93
+ for (let i = 0; i < generatedLength; i++) {
73
94
  if (reducedData[i] === undefined) {
74
95
  reducedData[i] = 0;
75
96
  }
@@ -143,7 +164,7 @@ class JsonGenerator extends Generator {
143
164
  const jsonStr = stringifySafe(finalJson);
144
165
  const jsonExpr =
145
166
  jsonStr.length > 20 && typeof finalJson === "object"
146
- ? `JSON.parse(${JSON.stringify(jsonStr)})`
167
+ ? `JSON.parse('${jsonStr.replace(/[\\']/g, "\\$&")}')`
147
168
  : jsonStr;
148
169
  let content;
149
170
  if (concatenationScope) {
@@ -17,8 +17,12 @@ const JavascriptModulesPlugin = require("../javascript/JavascriptModulesPlugin")
17
17
  /** @typedef {import("../Compiler")} Compiler */
18
18
  /** @typedef {import("../Module")} Module */
19
19
  /** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
20
+ /** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
20
21
  /** @typedef {import("../util/Hash")} Hash */
21
22
 
23
+ const COMMON_LIBRARY_NAME_MESSAGE =
24
+ "Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.";
25
+
22
26
  /**
23
27
  * @template T
24
28
  * @typedef {Object} LibraryContext
@@ -49,28 +53,36 @@ class AbstractLibraryPlugin {
49
53
  apply(compiler) {
50
54
  const { _pluginName } = this;
51
55
  compiler.hooks.thisCompilation.tap(_pluginName, compilation => {
52
- compilation.hooks.finishModules.tap(_pluginName, () => {
53
- for (const [
54
- name,
55
- {
56
- dependencies: deps,
57
- options: { library }
58
- }
59
- ] of compilation.entries) {
60
- const options = this._parseOptionsCached(
61
- library !== undefined ? library : compilation.outputOptions.library
62
- );
63
- if (options !== false) {
64
- const dep = deps[deps.length - 1];
65
- if (dep) {
66
- const module = compilation.moduleGraph.getModule(dep);
67
- if (module) {
68
- this.finishEntryModule(module, name, { options, compilation });
56
+ compilation.hooks.finishModules.tap(
57
+ { name: _pluginName, stage: 10 },
58
+ () => {
59
+ for (const [
60
+ name,
61
+ {
62
+ dependencies: deps,
63
+ options: { library }
64
+ }
65
+ ] of compilation.entries) {
66
+ const options = this._parseOptionsCached(
67
+ library !== undefined
68
+ ? library
69
+ : compilation.outputOptions.library
70
+ );
71
+ if (options !== false) {
72
+ const dep = deps[deps.length - 1];
73
+ if (dep) {
74
+ const module = compilation.moduleGraph.getModule(dep);
75
+ if (module) {
76
+ this.finishEntryModule(module, name, {
77
+ options,
78
+ compilation
79
+ });
80
+ }
69
81
  }
70
82
  }
71
83
  }
72
84
  }
73
- });
85
+ );
74
86
 
75
87
  const getOptionsForChunk = chunk => {
76
88
  if (compilation.chunkGraph.getNumberOfEntryModules(chunk) === 0)
@@ -82,23 +94,64 @@ class AbstractLibraryPlugin {
82
94
  );
83
95
  };
84
96
 
85
- compilation.hooks.additionalChunkRuntimeRequirements.tap(
86
- _pluginName,
87
- (chunk, set) => {
88
- const options = getOptionsForChunk(chunk);
89
- if (options !== false) {
90
- this.runtimeRequirements(chunk, set, { options, compilation });
97
+ if (
98
+ this.render !== AbstractLibraryPlugin.prototype.render ||
99
+ this.runtimeRequirements !==
100
+ AbstractLibraryPlugin.prototype.runtimeRequirements
101
+ ) {
102
+ compilation.hooks.additionalChunkRuntimeRequirements.tap(
103
+ _pluginName,
104
+ (chunk, set) => {
105
+ const options = getOptionsForChunk(chunk);
106
+ if (options !== false) {
107
+ this.runtimeRequirements(chunk, set, { options, compilation });
108
+ }
91
109
  }
92
- }
93
- );
110
+ );
111
+ }
94
112
 
95
113
  const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
96
114
 
97
- hooks.render.tap(_pluginName, (source, renderContext) => {
98
- const options = getOptionsForChunk(renderContext.chunk);
99
- if (options === false) return source;
100
- return this.render(source, renderContext, { options, compilation });
101
- });
115
+ if (this.render !== AbstractLibraryPlugin.prototype.render) {
116
+ hooks.render.tap(_pluginName, (source, renderContext) => {
117
+ const options = getOptionsForChunk(renderContext.chunk);
118
+ if (options === false) return source;
119
+ return this.render(source, renderContext, { options, compilation });
120
+ });
121
+ }
122
+
123
+ if (
124
+ this.embedInRuntimeBailout !==
125
+ AbstractLibraryPlugin.prototype.embedInRuntimeBailout
126
+ ) {
127
+ hooks.embedInRuntimeBailout.tap(
128
+ _pluginName,
129
+ (module, renderContext) => {
130
+ const options = getOptionsForChunk(renderContext.chunk);
131
+ if (options === false) return;
132
+ return this.embedInRuntimeBailout(module, renderContext, {
133
+ options,
134
+ compilation
135
+ });
136
+ }
137
+ );
138
+ }
139
+
140
+ if (
141
+ this.renderStartup !== AbstractLibraryPlugin.prototype.renderStartup
142
+ ) {
143
+ hooks.renderStartup.tap(
144
+ _pluginName,
145
+ (source, module, renderContext) => {
146
+ const options = getOptionsForChunk(renderContext.chunk);
147
+ if (options === false) return source;
148
+ return this.renderStartup(source, module, renderContext, {
149
+ options,
150
+ compilation
151
+ });
152
+ }
153
+ );
154
+ }
102
155
 
103
156
  hooks.chunkHash.tap(_pluginName, (chunk, hash, context) => {
104
157
  const options = getOptionsForChunk(chunk);
@@ -141,6 +194,16 @@ class AbstractLibraryPlugin {
141
194
  */
142
195
  finishEntryModule(module, entryName, libraryContext) {}
143
196
 
197
+ /**
198
+ * @param {Module} module the exporting entry module
199
+ * @param {RenderContext} renderContext render context
200
+ * @param {LibraryContext<T>} libraryContext context
201
+ * @returns {string | undefined} bailout reason
202
+ */
203
+ embedInRuntimeBailout(module, renderContext, libraryContext) {
204
+ return undefined;
205
+ }
206
+
144
207
  /**
145
208
  * @param {Chunk} chunk the chunk
146
209
  * @param {Set<string>} set runtime requirements
@@ -148,7 +211,8 @@ class AbstractLibraryPlugin {
148
211
  * @returns {void}
149
212
  */
150
213
  runtimeRequirements(chunk, set, libraryContext) {
151
- set.add(RuntimeGlobals.returnExportsFromRuntime);
214
+ if (this.render !== AbstractLibraryPlugin.prototype.render)
215
+ set.add(RuntimeGlobals.returnExportsFromRuntime);
152
216
  }
153
217
 
154
218
  /**
@@ -161,6 +225,17 @@ class AbstractLibraryPlugin {
161
225
  return source;
162
226
  }
163
227
 
228
+ /**
229
+ * @param {Source} source source
230
+ * @param {Module} module module
231
+ * @param {StartupRenderContext} renderContext render context
232
+ * @param {LibraryContext<T>} libraryContext context
233
+ * @returns {Source} source with library export
234
+ */
235
+ renderStartup(source, module, renderContext, libraryContext) {
236
+ return source;
237
+ }
238
+
164
239
  /**
165
240
  * @param {Chunk} chunk the chunk
166
241
  * @param {Hash} hash hash
@@ -177,4 +252,5 @@ class AbstractLibraryPlugin {
177
252
  }
178
253
  }
179
254
 
255
+ AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE = COMMON_LIBRARY_NAME_MESSAGE;
180
256
  module.exports = AbstractLibraryPlugin;
@@ -55,11 +55,15 @@ class AmdLibraryPlugin extends AbstractLibraryPlugin {
55
55
  const { name } = library;
56
56
  if (this.requireAsWrapper) {
57
57
  if (name) {
58
- throw new Error("AMD library name must be unset");
58
+ throw new Error(
59
+ `AMD library name must be unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
60
+ );
59
61
  }
60
62
  } else {
61
63
  if (name && typeof name !== "string") {
62
- throw new Error("AMD library name must be a simple string or unset");
64
+ throw new Error(
65
+ `AMD library name must be a simple string or unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
66
+ );
63
67
  }
64
68
  }
65
69
  return {
@@ -99,10 +103,12 @@ class AmdLibraryPlugin extends AbstractLibraryPlugin {
99
103
  )
100
104
  .join(", ");
101
105
 
102
- const fnStart = modern
103
- ? `(${externalsArguments}) => `
104
- : `function(${externalsArguments}) { return `;
105
- const fnEnd = modern ? "" : "}";
106
+ const iife = runtimeTemplate.isIIFE();
107
+ const fnStart =
108
+ (modern
109
+ ? `(${externalsArguments}) => {`
110
+ : `function(${externalsArguments}) {`) + (iife ? " return " : "\n");
111
+ const fnEnd = iife ? ";\n}" : "\n}";
106
112
 
107
113
  if (this.requireAsWrapper) {
108
114
  return new ConcatSource(