webpack 5.12.3 → 5.16.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 (39) hide show
  1. package/lib/AutomaticPrefetchPlugin.js +1 -1
  2. package/lib/ChunkGraph.js +14 -4
  3. package/lib/Compilation.js +20 -15
  4. package/lib/Compiler.js +6 -3
  5. package/lib/ContextModule.js +2 -2
  6. package/lib/ContextModuleFactory.js +6 -4
  7. package/lib/ExportsInfo.js +0 -1
  8. package/lib/ExternalModuleFactoryPlugin.js +46 -3
  9. package/lib/FileSystemInfo.js +288 -157
  10. package/lib/IgnoreErrorModuleFactory.js +39 -0
  11. package/lib/MultiCompiler.js +2 -0
  12. package/lib/NormalModuleFactory.js +26 -7
  13. package/lib/WatchIgnorePlugin.js +6 -1
  14. package/lib/WebpackIsIncludedPlugin.js +85 -0
  15. package/lib/WebpackOptionsApply.js +2 -0
  16. package/lib/cache/PackFileCacheStrategy.js +5 -5
  17. package/lib/dependencies/AMDDefineDependency.js +1 -1
  18. package/lib/dependencies/HarmonyImportSpecifierDependency.js +2 -17
  19. package/lib/dependencies/URLDependency.js +45 -3
  20. package/lib/dependencies/URLPlugin.js +33 -7
  21. package/lib/dependencies/WebpackIsIncludedDependency.js +80 -0
  22. package/lib/ids/IdHelpers.js +8 -3
  23. package/lib/javascript/JavascriptModulesPlugin.js +4 -3
  24. package/lib/library/AssignLibraryPlugin.js +13 -4
  25. package/lib/library/EnableLibraryPlugin.js +12 -0
  26. package/lib/optimize/InnerGraph.js +32 -0
  27. package/lib/optimize/SplitChunksPlugin.js +4 -1
  28. package/lib/serialization/FileMiddleware.js +1 -1
  29. package/lib/sharing/ProvideSharedModule.js +1 -1
  30. package/lib/sharing/ShareRuntimeModule.js +2 -2
  31. package/lib/stats/DefaultStatsPrinterPlugin.js +6 -0
  32. package/lib/util/fs.js +51 -11
  33. package/lib/util/internalSerializables.js +2 -0
  34. package/lib/util/processAsyncTree.js +61 -0
  35. package/package.json +9 -7
  36. package/schemas/WebpackOptions.json +62 -25
  37. package/schemas/plugins/container/ContainerPlugin.json +2 -1
  38. package/schemas/plugins/container/ModuleFederationPlugin.json +2 -1
  39. package/types.d.ts +339 -236
@@ -0,0 +1,39 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Ivan Kopeykin @vankop
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const ModuleFactory = require("./ModuleFactory");
9
+
10
+ /** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
11
+ /** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
12
+ /** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
13
+
14
+ /**
15
+ * Ignores error when module is unresolved
16
+ */
17
+ class IgnoreErrorModuleFactory extends ModuleFactory {
18
+ /**
19
+ * @param {NormalModuleFactory} normalModuleFactory normalModuleFactory instance
20
+ */
21
+ constructor(normalModuleFactory) {
22
+ super();
23
+
24
+ this.normalModuleFactory = normalModuleFactory;
25
+ }
26
+
27
+ /**
28
+ * @param {ModuleFactoryCreateData} data data object
29
+ * @param {function(Error=, ModuleFactoryResult=): void} callback callback
30
+ * @returns {void}
31
+ */
32
+ create(data, callback) {
33
+ this.normalModuleFactory.create(data, (err, result) => {
34
+ return callback(null, result);
35
+ });
36
+ }
37
+ }
38
+
39
+ module.exports = IgnoreErrorModuleFactory;
@@ -226,6 +226,7 @@ module.exports = class MultiCompiler {
226
226
  }
227
227
  }
228
228
  }
229
+ /** @type {string[]} */
229
230
  const errors = missing.map(m => `Compiler dependency \`${m}\` not found.`);
230
231
  const stack = this.compilers.filter(c => !targetFound(c));
231
232
  while (stack.length > 0) {
@@ -241,6 +242,7 @@ module.exports = class MultiCompiler {
241
242
  }
242
243
  }
243
244
  if (edges.size > 0) {
245
+ /** @type {string[]} */
244
246
  const lines = Array.from(edges)
245
247
  .sort(sortEdges)
246
248
  .map(edge => `${edge.source.name} -> ${edge.target.name}`);
@@ -147,10 +147,19 @@ const mergeGlobalOptions = (globalOptions, type, localOptions) => {
147
147
  };
148
148
 
149
149
  // TODO webpack 6 remove
150
- const deprecationChangedHookMessage = name =>
151
- `NormalModuleFactory.${name} is no longer a waterfall hook, but a bailing hook instead. ` +
152
- "Do not return the passed object, but modify it instead. " +
153
- "Returning false will ignore the request and results in no module created.";
150
+ const deprecationChangedHookMessage = (name, hook) => {
151
+ const names = hook.taps
152
+ .map(tapped => {
153
+ return tapped.name;
154
+ })
155
+ .join(", ");
156
+
157
+ return (
158
+ `NormalModuleFactory.${name} (${names}) is no longer a waterfall hook, but a bailing hook instead. ` +
159
+ "Do not return the passed object, but modify it instead. " +
160
+ "Returning false will ignore the request and results in no module created."
161
+ );
162
+ };
154
163
 
155
164
  const dependencyCache = new WeakMap();
156
165
 
@@ -270,7 +279,7 @@ class NormalModuleFactory extends ModuleFactory {
270
279
 
271
280
  if (typeof result === "object")
272
281
  throw new Error(
273
- deprecationChangedHookMessage("resolve") +
282
+ deprecationChangedHookMessage("resolve", this.hooks.resolve) +
274
283
  " Returning a Module object will result in this module used as result."
275
284
  );
276
285
 
@@ -278,7 +287,12 @@ class NormalModuleFactory extends ModuleFactory {
278
287
  if (err) return callback(err);
279
288
 
280
289
  if (typeof result === "object")
281
- throw new Error(deprecationChangedHookMessage("afterResolve"));
290
+ throw new Error(
291
+ deprecationChangedHookMessage(
292
+ "afterResolve",
293
+ this.hooks.afterResolve
294
+ )
295
+ );
282
296
 
283
297
  // Ignored
284
298
  if (result === false) return callback();
@@ -682,7 +696,12 @@ class NormalModuleFactory extends ModuleFactory {
682
696
  }
683
697
 
684
698
  if (typeof result === "object")
685
- throw new Error(deprecationChangedHookMessage("beforeResolve"));
699
+ throw new Error(
700
+ deprecationChangedHookMessage(
701
+ "beforeResolve",
702
+ this.hooks.beforeResolve
703
+ )
704
+ );
686
705
 
687
706
  this.hooks.factorize.callAsync(resolveData, (err, module) => {
688
707
  if (err) {
@@ -10,10 +10,15 @@ const schema = require("../schemas/plugins/WatchIgnorePlugin.json");
10
10
 
11
11
  /** @typedef {import("../declarations/plugins/WatchIgnorePlugin").WatchIgnorePluginOptions} WatchIgnorePluginOptions */
12
12
  /** @typedef {import("./Compiler")} Compiler */
13
+ /** @typedef {import("./util/fs").WatchFileSystem} WatchFileSystem */
13
14
 
14
15
  const IGNORE_TIME_ENTRY = "ignore";
15
16
 
16
17
  class IgnoringWatchFileSystem {
18
+ /**
19
+ * @param {WatchFileSystem} wfs original file system
20
+ * @param {(string|RegExp)[]} paths ignored paths
21
+ */
17
22
  constructor(wfs, paths) {
18
23
  this.wfs = wfs;
19
24
  this.paths = paths;
@@ -63,7 +68,7 @@ class IgnoringWatchFileSystem {
63
68
  close: () => watcher.close(),
64
69
  pause: () => watcher.pause(),
65
70
  getContextTimeInfoEntries: () => {
66
- const dirTimestamps = watcher.getContextInfoEntries();
71
+ const dirTimestamps = watcher.getContextTimeInfoEntries();
67
72
  for (const path of ignoredDirs) {
68
73
  dirTimestamps.set(path, IGNORE_TIME_ENTRY);
69
74
  }
@@ -0,0 +1,85 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Ivan Kopeykin @vankop
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const IgnoreErrorModuleFactory = require("./IgnoreErrorModuleFactory");
9
+ const WebpackIsIncludedDependency = require("./dependencies/WebpackIsIncludedDependency");
10
+ const {
11
+ toConstantDependency
12
+ } = require("./javascript/JavascriptParserHelpers");
13
+
14
+ /** @typedef {import("enhanced-resolve/lib/Resolver")} Resolver */
15
+ /** @typedef {import("./Compiler")} Compiler */
16
+ /** @typedef {import("./Module")} Module */
17
+ /** @typedef {import("./javascript/JavascriptParser")} JavascriptParser */
18
+
19
+ class WebpackIsIncludedPlugin {
20
+ /**
21
+ * @param {Compiler} compiler the compiler instance
22
+ * @returns {void}
23
+ */
24
+ apply(compiler) {
25
+ compiler.hooks.compilation.tap(
26
+ "WebpackIsIncludedPlugin",
27
+ (compilation, { normalModuleFactory }) => {
28
+ compilation.dependencyFactories.set(
29
+ WebpackIsIncludedDependency,
30
+ new IgnoreErrorModuleFactory(normalModuleFactory)
31
+ );
32
+ compilation.dependencyTemplates.set(
33
+ WebpackIsIncludedDependency,
34
+ new WebpackIsIncludedDependency.Template()
35
+ );
36
+
37
+ /**
38
+ * @param {JavascriptParser} parser the parser
39
+ * @returns {void}
40
+ */
41
+ const handler = parser => {
42
+ parser.hooks.call
43
+ .for("__webpack_is_included__")
44
+ .tap("WebpackIsIncludedPlugin", expr => {
45
+ if (
46
+ expr.type !== "CallExpression" ||
47
+ expr.arguments.length !== 1 ||
48
+ expr.arguments[0].type === "SpreadElement"
49
+ )
50
+ return;
51
+
52
+ const request = parser.evaluateExpression(expr.arguments[0]);
53
+
54
+ if (!request.isString()) return;
55
+
56
+ const dep = new WebpackIsIncludedDependency(
57
+ request.string,
58
+ expr.range
59
+ );
60
+ dep.loc = expr.loc;
61
+ parser.state.module.addDependency(dep);
62
+ return true;
63
+ });
64
+ parser.hooks.typeof
65
+ .for("__webpack_is_included__")
66
+ .tap(
67
+ "WebpackIsIncludedPlugin",
68
+ toConstantDependency(parser, JSON.stringify("function"))
69
+ );
70
+ };
71
+ normalModuleFactory.hooks.parser
72
+ .for("javascript/auto")
73
+ .tap("WebpackIsIncludedPlugin", handler);
74
+ normalModuleFactory.hooks.parser
75
+ .for("javascript/dynamic")
76
+ .tap("WebpackIsIncludedPlugin", handler);
77
+ normalModuleFactory.hooks.parser
78
+ .for("javascript/esm")
79
+ .tap("WebpackIsIncludedPlugin", handler);
80
+ }
81
+ );
82
+ }
83
+ }
84
+
85
+ module.exports = WebpackIsIncludedPlugin;
@@ -22,6 +22,7 @@ const APIPlugin = require("./APIPlugin");
22
22
  const CompatibilityPlugin = require("./CompatibilityPlugin");
23
23
  const ConstPlugin = require("./ConstPlugin");
24
24
  const ExportsInfoApiPlugin = require("./ExportsInfoApiPlugin");
25
+ const WebpackIsIncludedPlugin = require("./WebpackIsIncludedPlugin");
25
26
 
26
27
  const TemplatedPathPlugin = require("./TemplatedPathPlugin");
27
28
  const UseStrictPlugin = require("./UseStrictPlugin");
@@ -272,6 +273,7 @@ class WebpackOptionsApply extends OptionsApply {
272
273
  }
273
274
  new APIPlugin().apply(compiler);
274
275
  new ExportsInfoApiPlugin().apply(compiler);
276
+ new WebpackIsIncludedPlugin().apply(compiler);
275
277
  new ConstPlugin().apply(compiler);
276
278
  new UseStrictPlugin().apply(compiler);
277
279
  new RequireIncludePlugin().apply(compiler);
@@ -1072,18 +1072,18 @@ class PackFileCacheStrategy {
1072
1072
  return promise.then(() => {
1073
1073
  if (reportProgress) reportProgress(0.8, "serialize pack");
1074
1074
  this.logger.time(`store pack`);
1075
+ const updatedBuildDependencies = new Set(this.buildDependencies);
1076
+ for (const dep of newBuildDependencies) {
1077
+ updatedBuildDependencies.add(dep);
1078
+ }
1075
1079
  const content = new PackContainer(
1076
1080
  pack,
1077
1081
  this.version,
1078
1082
  this.buildSnapshot,
1079
- this.buildDependencies,
1083
+ updatedBuildDependencies,
1080
1084
  this.resolveResults,
1081
1085
  this.resolveBuildDependenciesSnapshot
1082
1086
  );
1083
- // You might think this breaks all access to the existing pack
1084
- // which are still referenced, but serializing the pack memorizes
1085
- // all data in the pack and makes it no longer need the backing file
1086
- // So it's safe to replace the pack file
1087
1087
  return this.fileSerializer
1088
1088
  .serialize(content, {
1089
1089
  filename: `${this.cacheLocation}/index.pack`,
@@ -79,7 +79,7 @@ const DEFINITIONS = {
79
79
  lof: {
80
80
  definition: "var XXX, XXXfactory, XXXmodule;",
81
81
  content:
82
- "!(XXXfactory = (#), (typeof XXXfactory === 'function' ? (XXXmodule = { id: YYY, exports: {}, loaded: false }), (XXX = XXXfactory.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule)), (XXXmodule.loaded = true), XXX === undefined && (XXX = XXXmodule.exports) : XXX = XXXfactory))",
82
+ "!(XXXfactory = (#), (typeof XXXfactory === 'function' ? ((XXXmodule = { id: YYY, exports: {}, loaded: false }), (XXX = XXXfactory.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule)), (XXXmodule.loaded = true), XXX === undefined && (XXX = XXXmodule.exports)) : XXX = XXXfactory))",
83
83
  requests: [RuntimeGlobals.require, RuntimeGlobals.module]
84
84
  },
85
85
  laf: {
@@ -6,7 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const Dependency = require("../Dependency");
9
- const { UsageState } = require("../ExportsInfo");
9
+ const { isDependencyUsedByExports } = require("../optimize/InnerGraph");
10
10
  const makeSerializable = require("../util/makeSerializable");
11
11
  const propertyAccess = require("../util/propertyAccess");
12
12
  const HarmonyImportDependency = require("./HarmonyImportDependency");
@@ -84,7 +84,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
84
84
  */
85
85
  getCondition(moduleGraph) {
86
86
  return (connection, runtime) =>
87
- this.checkUsedByExports(moduleGraph, runtime);
87
+ isDependencyUsedByExports(this, this.usedByExports, moduleGraph, runtime);
88
88
  }
89
89
 
90
90
  /**
@@ -95,21 +95,6 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
95
95
  return false;
96
96
  }
97
97
 
98
- checkUsedByExports(moduleGraph, runtime) {
99
- if (this.usedByExports === false) return false;
100
- if (this.usedByExports !== true && this.usedByExports !== undefined) {
101
- const selfModule = moduleGraph.getParentModule(this);
102
- const exportsInfo = moduleGraph.getExportsInfo(selfModule);
103
- let used = false;
104
- for (const exportName of this.usedByExports) {
105
- if (exportsInfo.getUsed(exportName, runtime) !== UsageState.Unused)
106
- used = true;
107
- }
108
- if (!used) return false;
109
- }
110
- return true;
111
- }
112
-
113
98
  /**
114
99
  * Returns list of exports referenced by this dependency
115
100
  * @param {ModuleGraph} moduleGraph module graph
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const RuntimeGlobals = require("../RuntimeGlobals");
9
+ const { isDependencyUsedByExports } = require("../optimize/InnerGraph");
9
10
  const makeSerializable = require("../util/makeSerializable");
10
11
  const ModuleDependency = require("./ModuleDependency");
11
12
 
@@ -15,16 +16,23 @@ const ModuleDependency = require("./ModuleDependency");
15
16
  /** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
16
17
  /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
17
18
  /** @typedef {import("../ModuleGraph")} ModuleGraph */
19
+ /** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
20
+ /** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
18
21
  /** @typedef {import("../util/Hash")} Hash */
22
+ /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
19
23
 
20
24
  class URLDependency extends ModuleDependency {
21
25
  /**
22
26
  * @param {string} request request
23
- * @param {[number, number]} range range
27
+ * @param {[number, number]} range range of the arguments of new URL( |> ... <| )
28
+ * @param {[number, number]} outerRange range of the full |> new URL(...) <|
24
29
  */
25
- constructor(request, range) {
30
+ constructor(request, range, outerRange) {
26
31
  super(request);
27
32
  this.range = range;
33
+ this.outerRange = outerRange;
34
+ /** @type {Set<string> | boolean} */
35
+ this.usedByExports = undefined;
28
36
  }
29
37
 
30
38
  get type() {
@@ -34,6 +42,29 @@ class URLDependency extends ModuleDependency {
34
42
  get category() {
35
43
  return "url";
36
44
  }
45
+
46
+ /**
47
+ * @param {ModuleGraph} moduleGraph module graph
48
+ * @returns {function(ModuleGraphConnection, RuntimeSpec): ConnectionState} function to determine if the connection is active
49
+ */
50
+ getCondition(moduleGraph) {
51
+ return (connection, runtime) =>
52
+ isDependencyUsedByExports(this, this.usedByExports, moduleGraph, runtime);
53
+ }
54
+
55
+ serialize(context) {
56
+ const { write } = context;
57
+ write(this.outerRange);
58
+ write(this.usedByExports);
59
+ super.serialize(context);
60
+ }
61
+
62
+ deserialize(context) {
63
+ const { read } = context;
64
+ this.outerRange = read();
65
+ this.usedByExports = read();
66
+ super.deserialize(context);
67
+ }
37
68
  }
38
69
 
39
70
  URLDependency.Template = class URLDependencyTemplate extends (
@@ -50,9 +81,20 @@ URLDependency.Template = class URLDependencyTemplate extends (
50
81
  chunkGraph,
51
82
  moduleGraph,
52
83
  runtimeRequirements,
53
- runtimeTemplate
84
+ runtimeTemplate,
85
+ runtime
54
86
  } = templateContext;
55
87
  const dep = /** @type {URLDependency} */ (dependency);
88
+ const connection = moduleGraph.getConnection(dep);
89
+ // Skip rendering depending when dependency is conditional
90
+ if (connection && !connection.isTargetActive(runtime)) {
91
+ source.replace(
92
+ dep.outerRange[0],
93
+ dep.outerRange[1] - 1,
94
+ "/* unused asset import */ undefined"
95
+ );
96
+ return;
97
+ }
56
98
 
57
99
  runtimeRequirements.add(RuntimeGlobals.baseURI);
58
100
  runtimeRequirements.add(RuntimeGlobals.require);
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const { approve } = require("../javascript/JavascriptParserHelpers");
9
+ const InnerGraph = require("../optimize/InnerGraph");
9
10
  const URLDependency = require("./URLDependency");
10
11
 
11
12
  /** @typedef {import("estree").NewExpression} NewExpressionNode */
@@ -32,10 +33,12 @@ class URLPlugin {
32
33
  */
33
34
  const parserCallback = (parser, parserOptions) => {
34
35
  if (parserOptions.url === false) return;
35
- parser.hooks.canRename.for("URL").tap("URLPlugin", approve);
36
- parser.hooks.new.for("URL").tap("URLPlugin", _expr => {
37
- const expr = /** @type {NewExpressionNode} */ (_expr);
38
36
 
37
+ /**
38
+ * @param {NewExpressionNode} expr expression
39
+ * @returns {undefined | string} request
40
+ */
41
+ const getUrlRequest = expr => {
39
42
  if (expr.arguments.length !== 2) return;
40
43
 
41
44
  const [arg1, arg2] = expr.arguments;
@@ -59,16 +62,39 @@ class URLPlugin {
59
62
 
60
63
  const request = parser.evaluateExpression(arg1).asString();
61
64
 
65
+ return request;
66
+ };
67
+
68
+ parser.hooks.canRename.for("URL").tap("URLPlugin", approve);
69
+ parser.hooks.new.for("URL").tap("URLPlugin", _expr => {
70
+ const expr = /** @type {NewExpressionNode} */ (_expr);
71
+
72
+ const request = getUrlRequest(expr);
73
+
62
74
  if (!request) return;
63
75
 
64
- const dep = new URLDependency(request, [
65
- arg1.range[0],
66
- arg2.range[1]
67
- ]);
76
+ const [arg1, arg2] = expr.arguments;
77
+ const dep = new URLDependency(
78
+ request,
79
+ [arg1.range[0], arg2.range[1]],
80
+ expr.range
81
+ );
68
82
  dep.loc = expr.loc;
69
83
  parser.state.module.addDependency(dep);
84
+ InnerGraph.onUsage(parser.state, e => (dep.usedByExports = e));
70
85
  return true;
71
86
  });
87
+ parser.hooks.isPure.for("NewExpression").tap("URLPlugin", _expr => {
88
+ const expr = /** @type {NewExpressionNode} */ (_expr);
89
+ const { callee } = expr;
90
+ if (callee.type !== "Identifier") return;
91
+ const calleeInfo = parser.getFreeInfoFromVariable(callee.name);
92
+ if (!calleeInfo || calleeInfo.name !== "URL") return;
93
+
94
+ const request = getUrlRequest(expr);
95
+
96
+ if (request) return true;
97
+ });
72
98
  };
73
99
 
74
100
  normalModuleFactory.hooks.parser
@@ -0,0 +1,80 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Ivan Kopeykin @vankop
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const Dependency = require("../Dependency");
9
+ const Template = require("../Template");
10
+ const makeSerializable = require("../util/makeSerializable");
11
+ const ModuleDependency = require("./ModuleDependency");
12
+
13
+ /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
14
+ /** @typedef {import("../Compilation")} Compilation */
15
+ /** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
16
+ /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
17
+ /** @typedef {import("../ModuleGraph")} ModuleGraph */
18
+ /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
19
+
20
+ class WebpackIsIncludedDependency extends ModuleDependency {
21
+ constructor(request, range) {
22
+ super(request);
23
+
24
+ this.weak = true;
25
+ this.range = range;
26
+ }
27
+
28
+ /**
29
+ * Returns list of exports referenced by this dependency
30
+ * @param {ModuleGraph} moduleGraph module graph
31
+ * @param {RuntimeSpec} runtime the runtime for which the module is analysed
32
+ * @returns {(string[] | ReferencedExport)[]} referenced exports
33
+ */
34
+ getReferencedExports(moduleGraph, runtime) {
35
+ // This doesn't use any export
36
+ return Dependency.NO_EXPORTS_REFERENCED;
37
+ }
38
+
39
+ get type() {
40
+ return "__webpack_is_included__";
41
+ }
42
+ }
43
+
44
+ makeSerializable(
45
+ WebpackIsIncludedDependency,
46
+ "webpack/lib/dependencies/WebpackIsIncludedDependency"
47
+ );
48
+
49
+ WebpackIsIncludedDependency.Template = class WebpackIsIncludedDependencyTemplate extends (
50
+ ModuleDependency.Template
51
+ ) {
52
+ /**
53
+ * @param {Dependency} dependency the dependency for which the template should be applied
54
+ * @param {ReplaceSource} source the current replace source which can be modified
55
+ * @param {DependencyTemplateContext} templateContext the context object
56
+ * @returns {void}
57
+ */
58
+ apply(dependency, source, { runtimeTemplate, chunkGraph, moduleGraph }) {
59
+ const dep = /** @type {WebpackIsIncludedDependency} */ (dependency);
60
+ const connection = moduleGraph.getConnection(dep);
61
+ const included = connection
62
+ ? chunkGraph.getNumberOfModuleChunks(connection.module) > 0
63
+ : false;
64
+ const comment = runtimeTemplate.outputOptions.pathinfo
65
+ ? Template.toComment(
66
+ `__webpack_is_included__ ${runtimeTemplate.requestShortener.shorten(
67
+ dep.request
68
+ )}`
69
+ )
70
+ : "";
71
+
72
+ source.replace(
73
+ dep.range[0],
74
+ dep.range[1] - 1,
75
+ `${comment}${JSON.stringify(included)}`
76
+ );
77
+ }
78
+ };
79
+
80
+ module.exports = WebpackIsIncludedDependency;
@@ -77,9 +77,14 @@ const shortenLongString = (string, delimiter) => {
77
77
  * @returns {string} short module name
78
78
  */
79
79
  const getShortModuleName = (module, context, associatedObjectForCache) => {
80
- return avoidNumber(
81
- module.libIdent({ context, associatedObjectForCache }) || ""
82
- );
80
+ const libIdent = module.libIdent({ context, associatedObjectForCache });
81
+ if (libIdent) return avoidNumber(libIdent);
82
+ const nameForCondition = module.nameForCondition();
83
+ if (nameForCondition)
84
+ return avoidNumber(
85
+ makePathsRelative(context, nameForCondition, associatedObjectForCache)
86
+ );
87
+ return "";
83
88
  };
84
89
  exports.getShortModuleName = getShortModuleName;
85
90
 
@@ -848,6 +848,7 @@ class JavascriptModulesPlugin {
848
848
  buf.push("");
849
849
  }
850
850
 
851
+ const maybeReturn = returnExportsFromRuntime ? "return " : "";
851
852
  if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
852
853
  if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
853
854
  /** @type {string[]} */
@@ -933,7 +934,7 @@ class JavascriptModulesPlugin {
933
934
  );
934
935
  buf.push("");
935
936
  startup.push("// run startup");
936
- startup.push(`return ${RuntimeGlobals.startup}();`);
937
+ startup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
937
938
  } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
938
939
  buf.push("// the startup function");
939
940
  buf.push(
@@ -951,7 +952,7 @@ class JavascriptModulesPlugin {
951
952
  startup.push("// startup");
952
953
  startup.push(Template.asString(buf2));
953
954
  afterStartup.push("// run runtime startup");
954
- afterStartup.push(`return ${RuntimeGlobals.startup}();`);
955
+ afterStartup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
955
956
  } else {
956
957
  startup.push("// startup");
957
958
  startup.push(Template.asString(buf2));
@@ -980,7 +981,7 @@ class JavascriptModulesPlugin {
980
981
  `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()}`
981
982
  );
982
983
  startup.push("// run startup");
983
- startup.push(`return ${RuntimeGlobals.startup}();`);
984
+ startup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
984
985
  }
985
986
  return result;
986
987
  }
@@ -87,6 +87,7 @@ const accessWithInit = (accessor, existingLength, initLast = false) => {
87
87
  * @property {string[] | "global"} prefix name prefix
88
88
  * @property {string | false} declare declare name as variable
89
89
  * @property {"error"|"copy"|"assign"} unnamed behavior for unnamed library name
90
+ * @property {"copy"|"assign"=} named behavior for named library name
90
91
  */
91
92
 
92
93
  /**
@@ -94,6 +95,9 @@ const accessWithInit = (accessor, existingLength, initLast = false) => {
94
95
  * @property {string | string[]} name
95
96
  */
96
97
 
98
+ const COMMON_LIBRARY_NAME_MESSAGE =
99
+ "Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.";
100
+
97
101
  /**
98
102
  * @typedef {AssignLibraryPluginParsed} T
99
103
  * @extends {AbstractLibraryPlugin<AssignLibraryPluginParsed>}
@@ -110,6 +114,7 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
110
114
  this.prefix = options.prefix;
111
115
  this.declare = options.declare;
112
116
  this.unnamed = options.unnamed;
117
+ this.named = options.named || "assign";
113
118
  }
114
119
 
115
120
  /**
@@ -120,11 +125,15 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
120
125
  const { name } = library;
121
126
  if (this.unnamed === "error") {
122
127
  if (typeof name !== "string" && !Array.isArray(name)) {
123
- throw new Error("Library name must be a string or string array");
128
+ throw new Error(
129
+ `Library name must be a string or string array. ${COMMON_LIBRARY_NAME_MESSAGE}`
130
+ );
124
131
  }
125
132
  } else {
126
133
  if (name && typeof name !== "string" && !Array.isArray(name)) {
127
- throw new Error("Library name must be a string, string array or unset");
134
+ throw new Error(
135
+ `Library name must be a string, string array or unset. ${COMMON_LIBRARY_NAME_MESSAGE}`
136
+ );
128
137
  }
129
138
  }
130
139
  return {
@@ -156,12 +165,12 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
156
165
  throw new Error(
157
166
  `Library name base (${base}) must be a valid identifier when using a var declaring library type. Either use a valid identifier (e. g. ${Template.toIdentifier(
158
167
  base
159
- )}) or use a different library type (e. g. 'type: "global"', which assign a property on the global scope instead of declaring a variable). Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.`
168
+ )}) or use a different library type (e. g. 'type: "global"', which assign a property on the global scope instead of declaring a variable). ${COMMON_LIBRARY_NAME_MESSAGE}`
160
169
  );
161
170
  }
162
171
  result.add(`${this.declare} ${base};`);
163
172
  }
164
- if (!options.name && this.unnamed === "copy") {
173
+ if (options.name ? this.named === "copy" : this.unnamed === "copy") {
165
174
  result.add(
166
175
  `(function(e, a) { for(var i in a) e[i] = a[i]; if(a.__esModule) Object.defineProperty(e, "__esModule", { value: true }); }(${accessWithInit(
167
176
  fullNameResolved,