webpack 5.64.1 → 5.65.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/README.md +0 -6
  2. package/lib/ExternalModule.js +1 -1
  3. package/lib/FileSystemInfo.js +6 -2
  4. package/lib/RuntimeTemplate.js +92 -2
  5. package/lib/WatchIgnorePlugin.js +14 -1
  6. package/lib/Watching.js +31 -17
  7. package/lib/asset/AssetGenerator.js +7 -6
  8. package/lib/config/browserslistTargetHandler.js +38 -1
  9. package/lib/config/defaults.js +1 -1
  10. package/lib/config/target.js +10 -0
  11. package/lib/container/ContainerEntryModule.js +4 -3
  12. package/lib/esm/ModuleChunkFormatPlugin.js +74 -49
  13. package/lib/index.js +3 -0
  14. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +2 -2
  15. package/lib/javascript/ChunkHelpers.js +33 -0
  16. package/lib/javascript/JavascriptParser.js +16 -8
  17. package/lib/javascript/StartupHelpers.js +1 -25
  18. package/lib/library/AssignLibraryPlugin.js +5 -10
  19. package/lib/node/NodeWatchFileSystem.js +85 -31
  20. package/lib/sharing/ConsumeSharedModule.js +4 -0
  21. package/lib/sharing/ConsumeSharedRuntimeModule.js +25 -4
  22. package/lib/stats/DefaultStatsPrinterPlugin.js +1 -1
  23. package/lib/util/create-schema-validation.js +9 -2
  24. package/lib/util/extractUrlAndGlobal.js +3 -0
  25. package/lib/util/fs.js +10 -0
  26. package/lib/web/JsonpChunkLoadingRuntimeModule.js +1 -1
  27. package/lib/webpack.js +9 -1
  28. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +2 -1
  29. package/package.json +3 -3
  30. package/schemas/WebpackOptions.check.js +1 -1
  31. package/schemas/WebpackOptions.json +8 -0
  32. package/schemas/plugins/DllReferencePlugin.check.js +1 -1
  33. package/schemas/plugins/HashedModuleIdsPlugin.check.js +1 -1
  34. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  35. package/schemas/plugins/asset/AssetParserOptions.check.js +1 -1
  36. package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.js +1 -1
  37. package/schemas/plugins/optimize/LimitChunkCountPlugin.check.js +1 -1
  38. package/schemas/plugins/optimize/MinChunkSizePlugin.check.js +1 -1
  39. package/types.d.ts +61 -19
package/README.md CHANGED
@@ -9,8 +9,6 @@
9
9
 
10
10
  [![node][node]][node-url]
11
11
  [![deps][deps]][deps-url]
12
- [![tests][tests]][tests-url]
13
- [![builds][builds]][builds-url]
14
12
  [![builds2][builds2]][builds2-url]
15
13
  [![coverage][cover]][cover-url]
16
14
  [![licenses][licenses]][licenses-url]
@@ -703,12 +701,8 @@ src="https://static.monei.net/monei-logo.svg" height="30" alt="MONEI"></a>
703
701
  [node-url]: https://nodejs.org
704
702
  [deps]: https://img.shields.io/david/webpack/webpack.svg
705
703
  [deps-url]: https://david-dm.org/webpack/webpack
706
- [tests]: https://img.shields.io/travis/webpack/webpack/main.svg
707
- [tests-url]: https://travis-ci.org/webpack/webpack
708
704
  [prs]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
709
705
  [prs-url]: https://webpack.js.org/contribute/
710
- [builds-url]: https://ci.appveyor.com/project/sokra/webpack/branch/main
711
- [builds]: https://ci.appveyor.com/api/projects/status/github/webpack/webpack?svg=true
712
706
  [builds2]: https://dev.azure.com/webpack/webpack/_apis/build/status/webpack.webpack
713
707
  [builds2-url]: https://dev.azure.com/webpack/webpack/_build/latest?definitionId=3
714
708
  [licenses-url]: https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fwebpack%2Fwebpack?ref=badge_shield
@@ -536,7 +536,7 @@ class ExternalModule extends Module {
536
536
  case "global":
537
537
  return getSourceForGlobalVariableExternal(
538
538
  request,
539
- runtimeTemplate.outputOptions.globalObject
539
+ runtimeTemplate.globalObject
540
540
  );
541
541
  case "commonjs":
542
542
  case "commonjs2":
@@ -2256,7 +2256,9 @@ class FileSystemInfo {
2256
2256
  for (const path of managedItems) {
2257
2257
  const cache = this._managedItems.get(path);
2258
2258
  if (cache !== undefined) {
2259
- managedFiles.add(join(this.fs, path, "package.json"));
2259
+ if (cache !== "missing") {
2260
+ managedFiles.add(join(this.fs, path, "package.json"));
2261
+ }
2260
2262
  managedItemInfo.set(path, cache);
2261
2263
  } else {
2262
2264
  jobs++;
@@ -2269,7 +2271,9 @@ class FileSystemInfo {
2269
2271
  }
2270
2272
  jobError();
2271
2273
  } else if (entry) {
2272
- managedFiles.add(join(this.fs, path, "package.json"));
2274
+ if (entry !== "missing") {
2275
+ managedFiles.add(join(this.fs, path, "package.json"));
2276
+ }
2273
2277
  managedItemInfo.set(path, entry);
2274
2278
  jobDone();
2275
2279
  } else {
@@ -50,6 +50,27 @@ Module has these incoming connections: ${Array.from(
50
50
  ).join("")}`;
51
51
  };
52
52
 
53
+ /**
54
+ * @param {string|undefined} definition global object definition
55
+ * @returns {string} save to use global object
56
+ */
57
+ function getGlobalObject(definition) {
58
+ if (!definition) return definition;
59
+ const trimmed = definition.trim();
60
+
61
+ if (
62
+ // identifier, we do not need real identifier regarding ECMAScript/Unicode
63
+ trimmed.match(/^[_\p{L}][_0-9\p{L}]*$/iu) ||
64
+ // iife
65
+ // call expression
66
+ // expression in parentheses
67
+ trimmed.match(/^([_\p{L}][_0-9\p{L}]*)?\(.*\)$/iu)
68
+ )
69
+ return trimmed;
70
+
71
+ return `Object(${trimmed})`;
72
+ }
73
+
53
74
  class RuntimeTemplate {
54
75
  /**
55
76
  * @param {Compilation} compilation the compilation
@@ -60,6 +81,7 @@ class RuntimeTemplate {
60
81
  this.compilation = compilation;
61
82
  this.outputOptions = outputOptions || {};
62
83
  this.requestShortener = requestShortener;
84
+ this.globalObject = getGlobalObject(outputOptions.globalObject);
63
85
  }
64
86
 
65
87
  isIIFE() {
@@ -78,6 +100,10 @@ class RuntimeTemplate {
78
100
  return this.outputOptions.environment.arrowFunction;
79
101
  }
80
102
 
103
+ supportsOptionalChaining() {
104
+ return this.outputOptions.environment.optionalChaining;
105
+ }
106
+
81
107
  supportsForOf() {
82
108
  return this.outputOptions.environment.forOf;
83
109
  }
@@ -99,8 +125,7 @@ class RuntimeTemplate {
99
125
  }
100
126
 
101
127
  supportTemplateLiteral() {
102
- // TODO
103
- return false;
128
+ return this.outputOptions.environment.templateLiteral;
104
129
  }
105
130
 
106
131
  returningFunction(returnValue, args = "") {
@@ -115,6 +140,71 @@ class RuntimeTemplate {
115
140
  : `function(${args}) {\n${Template.indent(body)}\n}`;
116
141
  }
117
142
 
143
+ /**
144
+ * @param {Array<string|{expr: string}>} args args
145
+ * @returns {string} result expression
146
+ */
147
+ concatenation(...args) {
148
+ const len = args.length;
149
+
150
+ if (len === 2) return this._es5Concatenation(args);
151
+ if (len === 0) return '""';
152
+ if (len === 1) {
153
+ return typeof args[0] === "string"
154
+ ? JSON.stringify(args[0])
155
+ : `"" + ${args[0].expr}`;
156
+ }
157
+ if (!this.supportTemplateLiteral()) return this._es5Concatenation(args);
158
+
159
+ // cost comparison between template literal and concatenation:
160
+ // both need equal surroundings: `xxx` vs "xxx"
161
+ // template literal has constant cost of 3 chars for each expression
162
+ // es5 concatenation has cost of 3 + n chars for n expressions in row
163
+ // when a es5 concatenation ends with an expression it reduces cost by 3
164
+ // when a es5 concatenation starts with an single expression it reduces cost by 3
165
+ // e. g. `${a}${b}${c}` (3*3 = 9) is longer than ""+a+b+c ((3+3)-3 = 3)
166
+ // e. g. `x${a}x${b}x${c}x` (3*3 = 9) is shorter than "x"+a+"x"+b+"x"+c+"x" (4+4+4 = 12)
167
+
168
+ let templateCost = 0;
169
+ let concatenationCost = 0;
170
+
171
+ let lastWasExpr = false;
172
+ for (const arg of args) {
173
+ const isExpr = typeof arg !== "string";
174
+ if (isExpr) {
175
+ templateCost += 3;
176
+ concatenationCost += lastWasExpr ? 1 : 4;
177
+ }
178
+ lastWasExpr = isExpr;
179
+ }
180
+ if (lastWasExpr) concatenationCost -= 3;
181
+ if (typeof args[0] !== "string" && typeof args[1] === "string")
182
+ concatenationCost -= 3;
183
+
184
+ if (concatenationCost <= templateCost) return this._es5Concatenation(args);
185
+
186
+ return `\`${args
187
+ .map(arg => (typeof arg === "string" ? arg : `\${${arg.expr}}`))
188
+ .join("")}\``;
189
+ }
190
+
191
+ /**
192
+ * @param {Array<string|{expr: string}>} args args (len >= 2)
193
+ * @returns {string} result expression
194
+ * @private
195
+ */
196
+ _es5Concatenation(args) {
197
+ const str = args
198
+ .map(arg => (typeof arg === "string" ? JSON.stringify(arg) : arg.expr))
199
+ .join(" + ");
200
+
201
+ // when the first two args are expression, we need to prepend "" + to force string
202
+ // concatenation instead of number addition.
203
+ return typeof args[0] !== "string" && typeof args[1] !== "string"
204
+ ? `"" + ${str}`
205
+ : str;
206
+ }
207
+
118
208
  expressionFunction(expression, args = "") {
119
209
  return this.supportsArrowFunction()
120
210
  ? `(${args}) => (${expression})`
@@ -87,7 +87,20 @@ class IgnoringWatchFileSystem {
87
87
  fileTimestamps.set(path, IGNORE_TIME_ENTRY);
88
88
  }
89
89
  return fileTimestamps;
90
- }
90
+ },
91
+ getInfo:
92
+ watcher.getInfo &&
93
+ (() => {
94
+ const info = watcher.getInfo();
95
+ const { fileTimeInfoEntries, contextTimeInfoEntries } = info;
96
+ for (const path of ignoredFiles) {
97
+ fileTimeInfoEntries.set(path, IGNORE_TIME_ENTRY);
98
+ }
99
+ for (const path of ignoredDirs) {
100
+ contextTimeInfoEntries.set(path, IGNORE_TIME_ENTRY);
101
+ }
102
+ return info;
103
+ })
91
104
  };
92
105
  }
93
106
  }
package/lib/Watching.js CHANGED
@@ -109,30 +109,44 @@ class Watching {
109
109
  this.lastWatcherStartTime = Date.now();
110
110
  }
111
111
  this.compiler.fsStartTime = Date.now();
112
- this._mergeWithCollected(
113
- changedFiles ||
114
- (this.pausedWatcher &&
112
+ if (
113
+ changedFiles &&
114
+ removedFiles &&
115
+ fileTimeInfoEntries &&
116
+ contextTimeInfoEntries
117
+ ) {
118
+ this._mergeWithCollected(changedFiles, removedFiles);
119
+ this.compiler.fileTimestamps = fileTimeInfoEntries;
120
+ this.compiler.contextTimestamps = contextTimeInfoEntries;
121
+ } else if (this.pausedWatcher) {
122
+ if (this.pausedWatcher.getInfo) {
123
+ const {
124
+ changes,
125
+ removals,
126
+ fileTimeInfoEntries,
127
+ contextTimeInfoEntries
128
+ } = this.pausedWatcher.getInfo();
129
+ this._mergeWithCollected(changes, removals);
130
+ this.compiler.fileTimestamps = fileTimeInfoEntries;
131
+ this.compiler.contextTimestamps = contextTimeInfoEntries;
132
+ } else {
133
+ this._mergeWithCollected(
115
134
  this.pausedWatcher.getAggregatedChanges &&
116
- this.pausedWatcher.getAggregatedChanges()),
117
- (this.compiler.removedFiles =
118
- removedFiles ||
119
- (this.pausedWatcher &&
135
+ this.pausedWatcher.getAggregatedChanges(),
120
136
  this.pausedWatcher.getAggregatedRemovals &&
121
- this.pausedWatcher.getAggregatedRemovals()))
122
- );
123
-
137
+ this.pausedWatcher.getAggregatedRemovals()
138
+ );
139
+ this.compiler.fileTimestamps =
140
+ this.pausedWatcher.getFileTimeInfoEntries();
141
+ this.compiler.contextTimestamps =
142
+ this.pausedWatcher.getContextTimeInfoEntries();
143
+ }
144
+ }
124
145
  this.compiler.modifiedFiles = this._collectedChangedFiles;
125
146
  this._collectedChangedFiles = undefined;
126
147
  this.compiler.removedFiles = this._collectedRemovedFiles;
127
148
  this._collectedRemovedFiles = undefined;
128
149
 
129
- this.compiler.fileTimestamps =
130
- fileTimeInfoEntries ||
131
- (this.pausedWatcher && this.pausedWatcher.getFileTimeInfoEntries());
132
- this.compiler.contextTimestamps =
133
- contextTimeInfoEntries ||
134
- (this.pausedWatcher && this.pausedWatcher.getContextTimeInfoEntries());
135
-
136
150
  const run = () => {
137
151
  if (this.compiler.idle) {
138
152
  return this.compiler.cache.endIdle(err => {
@@ -228,7 +228,7 @@ class AssetGenerator extends Generator {
228
228
  contentHash
229
229
  }
230
230
  );
231
- let publicPath;
231
+ let assetPath;
232
232
  if (this.publicPath !== undefined) {
233
233
  const { path, info } =
234
234
  runtimeTemplate.compilation.getAssetPathWithInfo(
@@ -241,11 +241,14 @@ class AssetGenerator extends Generator {
241
241
  contentHash
242
242
  }
243
243
  );
244
- publicPath = JSON.stringify(path);
245
244
  assetInfo = mergeAssetInfo(assetInfo, info);
245
+ assetPath = JSON.stringify(path + filename);
246
246
  } else {
247
- publicPath = RuntimeGlobals.publicPath;
248
247
  runtimeRequirements.add(RuntimeGlobals.publicPath); // add __webpack_require__.p
248
+ assetPath = runtimeTemplate.concatenation(
249
+ { expr: RuntimeGlobals.publicPath },
250
+ filename
251
+ );
249
252
  }
250
253
  assetInfo = {
251
254
  sourceFilename,
@@ -264,9 +267,7 @@ class AssetGenerator extends Generator {
264
267
  }
265
268
 
266
269
  return new RawSource(
267
- `${
268
- RuntimeGlobals.module
269
- }.exports = ${publicPath} + ${JSON.stringify(filename)};`
270
+ `${RuntimeGlobals.module}.exports = ${assetPath};`
270
271
  );
271
272
  }
272
273
  }
@@ -274,7 +274,44 @@ const resolve = browsers => {
274
274
  // kaios: Unknown support
275
275
  node: [12, 0]
276
276
  }),
277
-
277
+ optionalChaining: rawChecker({
278
+ chrome: 80,
279
+ and_chr: 80,
280
+ edge: 80,
281
+ firefox: 74,
282
+ and_ff: 79,
283
+ // ie: Not supported,
284
+ opera: 67,
285
+ op_mob: 64,
286
+ safari: [13, 1],
287
+ ios_saf: [13, 4],
288
+ samsung: 13,
289
+ android: 80,
290
+ // and_qq: Not supported
291
+ // baidu: Not supported
292
+ // and_uc: Not supported
293
+ // kaios: Not supported
294
+ node: 14
295
+ }),
296
+ templateLiteral: rawChecker({
297
+ chrome: 41,
298
+ and_chr: 41,
299
+ edge: 13,
300
+ firefox: 34,
301
+ and_ff: 34,
302
+ // ie: Not supported,
303
+ opera: 29,
304
+ op_mob: 64,
305
+ safari: [9, 1],
306
+ ios_saf: 9,
307
+ samsung: 4,
308
+ android: 41,
309
+ and_qq: [10, 4],
310
+ baidu: [7, 12],
311
+ and_uc: [12, 12],
312
+ kaios: [2, 5],
313
+ node: 4
314
+ }),
278
315
  browser: browserProperty,
279
316
  electron: false,
280
317
  node: nodeProperty,
@@ -832,7 +832,7 @@ const applyOutputDefaults = (
832
832
  D(output, "chunkLoadTimeout", 120000);
833
833
  D(output, "hashFunction", futureDefaults ? "xxhash64" : "md4");
834
834
  D(output, "hashDigest", "hex");
835
- D(output, "hashDigestLength", 20);
835
+ D(output, "hashDigestLength", futureDefaults ? 16 : 20);
836
836
  D(output, "strictModuleExceptionHandling", false);
837
837
 
838
838
  const optimistic = v => v || v === undefined;
@@ -59,6 +59,8 @@ const getDefaultTarget = context => {
59
59
  * @property {boolean | null} dynamicImport async import() is available
60
60
  * @property {boolean | null} dynamicImportInWorker async import() is available when creating a worker
61
61
  * @property {boolean | null} module ESM syntax is available (when in module)
62
+ * @property {boolean | null} optionalChaining optional chaining is available
63
+ * @property {boolean | null} templateLiteral template literal is available
62
64
  */
63
65
 
64
66
  ///** @typedef {PlatformTargetProperties | ApiTargetProperties | EcmaTargetProperties | PlatformTargetProperties & ApiTargetProperties | PlatformTargetProperties & EcmaTargetProperties | ApiTargetProperties & EcmaTargetProperties} TargetProperties */
@@ -167,6 +169,8 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis
167
169
 
168
170
  globalThis: v(12),
169
171
  const: v(6),
172
+ templateLiteral: v(4),
173
+ optionalChaining: v(14),
170
174
  arrowFunction: v(6),
171
175
  forOf: v(5),
172
176
  destructuring: v(6),
@@ -206,6 +210,8 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis
206
210
 
207
211
  globalThis: v(5),
208
212
  const: v(1, 1),
213
+ templateLiteral: v(1, 1),
214
+ optionalChaining: v(8),
209
215
  arrowFunction: v(1, 1),
210
216
  forOf: v(0, 36),
211
217
  destructuring: v(1, 1),
@@ -241,6 +247,8 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis
241
247
 
242
248
  globalThis: v(0, 43),
243
249
  const: v(0, 15),
250
+ templateLiteral: v(0, 13),
251
+ optionalChaining: v(0, 44),
244
252
  arrowFunction: v(0, 15),
245
253
  forOf: v(0, 13),
246
254
  destructuring: v(0, 15),
@@ -260,6 +268,8 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis
260
268
  if (v < 1000) v = v + 2009;
261
269
  return {
262
270
  const: v >= 2015,
271
+ templateLiteral: v >= 2015,
272
+ optionalChaining: v >= 2020,
263
273
  arrowFunction: v >= 2015,
264
274
  forOf: v >= 2015,
265
275
  destructuring: v >= 2015,
@@ -10,6 +10,7 @@ const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
10
10
  const Module = require("../Module");
11
11
  const RuntimeGlobals = require("../RuntimeGlobals");
12
12
  const Template = require("../Template");
13
+ const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
13
14
  const makeSerializable = require("../util/makeSerializable");
14
15
  const ContainerExposedDependency = require("./ContainerExposedDependency");
15
16
 
@@ -104,6 +105,7 @@ class ContainerEntryModule extends Module {
104
105
  strict: true,
105
106
  topLevelDeclarations: new Set(["moduleMap", "get", "init"])
106
107
  };
108
+ this.buildMeta.exportsType = "namespace";
107
109
 
108
110
  this.clearDependenciesAndBlocks();
109
111
 
@@ -127,6 +129,7 @@ class ContainerEntryModule extends Module {
127
129
  }
128
130
  this.addBlock(block);
129
131
  }
132
+ this.addDependency(new StaticExportsDependency(["get", "init"], false));
130
133
 
131
134
  callback();
132
135
  }
@@ -217,10 +220,8 @@ class ContainerEntryModule extends Module {
217
220
  ])};`,
218
221
  `var init = ${runtimeTemplate.basicFunction("shareScope, initScope", [
219
222
  `if (!${RuntimeGlobals.shareScopeMap}) return;`,
220
- `var oldScope = ${RuntimeGlobals.shareScopeMap}[${JSON.stringify(
221
- this._shareScope
222
- )}];`,
223
223
  `var name = ${JSON.stringify(this._shareScope)}`,
224
+ `var oldScope = ${RuntimeGlobals.shareScopeMap}[name];`,
224
225
  `if(oldScope && oldScope !== shareScope) throw new Error("Container initialization failed as it has already been initialized with a different share scope");`,
225
226
  `${RuntimeGlobals.shareScopeMap}[name] = shareScope;`,
226
227
  `return ${RuntimeGlobals.initializeSharing}(name, initScope);`
@@ -5,18 +5,16 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const { ConcatSource, RawSource } = require("webpack-sources");
8
+ const { ConcatSource } = require("webpack-sources");
9
9
  const { RuntimeGlobals } = require("..");
10
10
  const HotUpdateChunk = require("../HotUpdateChunk");
11
11
  const Template = require("../Template");
12
+ const { getAllChunks } = require("../javascript/ChunkHelpers");
12
13
  const {
13
14
  getCompilationHooks,
14
15
  getChunkFilenameTemplate
15
16
  } = require("../javascript/JavascriptModulesPlugin");
16
- const {
17
- generateEntryStartup,
18
- updateHashForEntryStartup
19
- } = require("../javascript/StartupHelpers");
17
+ const { updateHashForEntryStartup } = require("../javascript/StartupHelpers");
20
18
 
21
19
  /** @typedef {import("../Compiler")} Compiler */
22
20
 
@@ -84,63 +82,90 @@ class ModuleChunkFormatPlugin {
84
82
  }
85
83
  )
86
84
  .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
85
 
100
86
  // remove filename, we only need the directory
101
- const outputFilename = currentOutputName.pop();
87
+ currentOutputName.pop();
102
88
 
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
- }
89
+ const getRelativePath = chunk => {
90
+ const baseOutputName = currentOutputName.slice();
91
+ const chunkOutputName = compilation
92
+ .getPath(
93
+ getChunkFilenameTemplate(
94
+ chunk,
95
+ compilation.outputOptions
96
+ ),
97
+ {
98
+ chunk: chunk,
99
+ contentHashType: "javascript"
100
+ }
101
+ )
102
+ .split("/");
112
103
 
113
- // create final path
114
- const runtimePath =
115
- (currentOutputName.length > 0
116
- ? "../".repeat(currentOutputName.length)
117
- : "./") + runtimeOutputName.join("/");
104
+ // remove common parts
105
+ while (
106
+ baseOutputName.length > 0 &&
107
+ chunkOutputName.length > 0 &&
108
+ baseOutputName[0] === chunkOutputName[0]
109
+ ) {
110
+ baseOutputName.shift();
111
+ chunkOutputName.shift();
112
+ }
113
+ // create final path
114
+ return (
115
+ (baseOutputName.length > 0
116
+ ? "../".repeat(baseOutputName.length)
117
+ : "./") + chunkOutputName.join("/")
118
+ );
119
+ };
118
120
 
119
121
  const entrySource = new ConcatSource();
120
122
  entrySource.add(source);
121
123
  entrySource.add(";\n\n// load runtime\n");
122
124
  entrySource.add(
123
125
  `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
126
+ getRelativePath(runtimeChunk)
130
127
  )};\n`
131
128
  );
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
- )
129
+
130
+ const startupSource = new ConcatSource();
131
+ startupSource.add(
132
+ `var __webpack_exec__ = ${runtimeTemplate.returningFunction(
133
+ `__webpack_require__(${RuntimeGlobals.entryModuleId} = moduleId)`,
134
+ "moduleId"
135
+ )}\n`
143
136
  );
137
+
138
+ const loadedChunks = new Set();
139
+ let index = 0;
140
+ for (let i = 0; i < entries.length; i++) {
141
+ const [module, entrypoint] = entries[i];
142
+ const final = i + 1 === entries.length;
143
+ const moduleId = chunkGraph.getModuleId(module);
144
+ const chunks = getAllChunks(
145
+ entrypoint,
146
+ runtimeChunk,
147
+ undefined
148
+ );
149
+ for (const chunk of chunks) {
150
+ if (loadedChunks.has(chunk)) continue;
151
+ loadedChunks.add(chunk);
152
+ startupSource.add(
153
+ `import * as __webpack_chunk_${index}__ from ${JSON.stringify(
154
+ getRelativePath(chunk)
155
+ )};\n`
156
+ );
157
+ startupSource.add(
158
+ `${RuntimeGlobals.externalInstallChunk}(__webpack_chunk_${index}__);\n`
159
+ );
160
+ index++;
161
+ }
162
+ startupSource.add(
163
+ `${
164
+ final ? "var __webpack_exports__ = " : ""
165
+ }__webpack_exec__(${JSON.stringify(moduleId)});\n`
166
+ );
167
+ }
168
+
144
169
  entrySource.add(
145
170
  hooks.renderStartup.call(
146
171
  startupSource,
package/lib/index.js CHANGED
@@ -19,6 +19,7 @@ const memoize = require("./util/memoize");
19
19
  /** @typedef {import("../declarations/WebpackOptions").RuleSetRule} RuleSetRule */
20
20
  /** @typedef {import("../declarations/WebpackOptions").RuleSetUse} RuleSetUse */
21
21
  /** @typedef {import("../declarations/WebpackOptions").RuleSetUseItem} RuleSetUseItem */
22
+ /** @typedef {import("../declarations/WebpackOptions").StatsOptions} StatsOptions */
22
23
  /** @typedef {import("../declarations/WebpackOptions").WebpackOptions} Configuration */
23
24
  /** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptionsNormalized */
24
25
  /** @typedef {import("../declarations/WebpackOptions").WebpackPluginFunction} WebpackPluginFunction */
@@ -27,6 +28,8 @@ const memoize = require("./util/memoize");
27
28
  /** @typedef {import("./Compilation").AssetInfo} AssetInfo */
28
29
  /** @typedef {import("./MultiStats")} MultiStats */
29
30
  /** @typedef {import("./Parser").ParserState} ParserState */
31
+ /** @typedef {import("./ResolverFactory").ResolvePluginInstance} ResolvePluginInstance */
32
+ /** @typedef {import("./ResolverFactory").Resolver} Resolver */
30
33
  /** @typedef {import("./Watching")} Watching */
31
34
  /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsAsset} StatsAsset */
32
35
  /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsChunk} StatsChunk */
@@ -45,7 +45,7 @@ class ArrayPushCallbackChunkFormatPlugin {
45
45
  const { chunk, chunkGraph, runtimeTemplate } = renderContext;
46
46
  const hotUpdateChunk =
47
47
  chunk instanceof HotUpdateChunk ? chunk : null;
48
- const globalObject = runtimeTemplate.outputOptions.globalObject;
48
+ const globalObject = runtimeTemplate.globalObject;
49
49
  const source = new ConcatSource();
50
50
  const runtimeModules =
51
51
  chunkGraph.getChunkRuntimeModulesInOrder(chunk);
@@ -138,7 +138,7 @@ class ArrayPushCallbackChunkFormatPlugin {
138
138
  (chunk, hash, { chunkGraph, runtimeTemplate }) => {
139
139
  if (chunk.hasRuntime()) return;
140
140
  hash.update(
141
- `ArrayPushCallbackChunkFormatPlugin1${runtimeTemplate.outputOptions.chunkLoadingGlobal}${runtimeTemplate.outputOptions.hotUpdateGlobal}${runtimeTemplate.outputOptions.globalObject}`
141
+ `ArrayPushCallbackChunkFormatPlugin1${runtimeTemplate.outputOptions.chunkLoadingGlobal}${runtimeTemplate.outputOptions.hotUpdateGlobal}${runtimeTemplate.globalObject}`
142
142
  );
143
143
  const entries = Array.from(
144
144
  chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
@@ -0,0 +1,33 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const Entrypoint = require("../Entrypoint");
9
+
10
+ /** @typedef {import("../Chunk")} Chunk */
11
+
12
+ /**
13
+ * @param {Entrypoint} entrypoint a chunk group
14
+ * @param {Chunk} excludedChunk1 current chunk which is excluded
15
+ * @param {Chunk} excludedChunk2 runtime chunk which is excluded
16
+ * @returns {Set<Chunk>} chunks
17
+ */
18
+ const getAllChunks = (entrypoint, excludedChunk1, excludedChunk2) => {
19
+ const queue = new Set([entrypoint]);
20
+ const chunks = new Set();
21
+ for (const entrypoint of queue) {
22
+ for (const chunk of entrypoint.chunks) {
23
+ if (chunk === excludedChunk1) continue;
24
+ if (chunk === excludedChunk2) continue;
25
+ chunks.add(chunk);
26
+ }
27
+ for (const parent of entrypoint.parentsIterable) {
28
+ if (parent instanceof Entrypoint) queue.add(parent);
29
+ }
30
+ }
31
+ return chunks;
32
+ };
33
+ exports.getAllChunks = getAllChunks;