webpack 5.65.0 → 5.69.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 (134) hide show
  1. package/README.md +1 -1
  2. package/lib/APIPlugin.js +33 -0
  3. package/lib/Cache.js +1 -1
  4. package/lib/CacheFacade.js +4 -11
  5. package/lib/Chunk.js +2 -0
  6. package/lib/ChunkGraph.js +1 -2
  7. package/lib/CleanPlugin.js +1 -1
  8. package/lib/Compilation.js +93 -47
  9. package/lib/Compiler.js +57 -3
  10. package/lib/ContextModule.js +100 -41
  11. package/lib/ContextModuleFactory.js +60 -21
  12. package/lib/DelegatedModule.js +1 -1
  13. package/lib/Dependency.js +10 -0
  14. package/lib/DependencyTemplate.js +9 -0
  15. package/lib/DependencyTemplates.js +1 -1
  16. package/lib/DllModule.js +1 -1
  17. package/lib/EvalDevToolModulePlugin.js +16 -1
  18. package/lib/EvalSourceMapDevToolPlugin.js +18 -1
  19. package/lib/ExportsInfo.js +4 -4
  20. package/lib/ExternalModule.js +93 -53
  21. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  22. package/lib/FileSystemInfo.js +29 -25
  23. package/lib/Generator.js +2 -0
  24. package/lib/HookWebpackError.js +1 -1
  25. package/lib/Module.js +25 -4
  26. package/lib/ModuleFilenameHelpers.js +5 -1
  27. package/lib/MultiCompiler.js +1 -1
  28. package/lib/MultiWatching.js +1 -1
  29. package/lib/NormalModule.js +9 -5
  30. package/lib/NormalModuleFactory.js +25 -27
  31. package/lib/ProgressPlugin.js +1 -1
  32. package/lib/RawModule.js +1 -1
  33. package/lib/RuntimeGlobals.js +29 -1
  34. package/lib/RuntimeModule.js +1 -1
  35. package/lib/RuntimePlugin.js +50 -0
  36. package/lib/RuntimeTemplate.js +21 -0
  37. package/lib/Template.js +2 -1
  38. package/lib/TemplatedPathPlugin.js +48 -23
  39. package/lib/Watching.js +2 -2
  40. package/lib/WebpackOptionsApply.js +43 -2
  41. package/lib/asset/AssetGenerator.js +67 -26
  42. package/lib/asset/AssetModulesPlugin.js +3 -0
  43. package/lib/asset/RawDataUrlModule.js +148 -0
  44. package/lib/async-modules/AwaitDependenciesInitFragment.js +4 -4
  45. package/lib/buildChunkGraph.js +1 -1
  46. package/lib/cache/ResolverCachePlugin.js +81 -29
  47. package/lib/cli.js +44 -3
  48. package/lib/config/defaults.js +86 -7
  49. package/lib/config/normalization.js +5 -0
  50. package/lib/container/ContainerEntryModule.js +4 -2
  51. package/lib/container/FallbackModule.js +4 -4
  52. package/lib/container/RemoteModule.js +4 -2
  53. package/lib/css/CssExportsGenerator.js +139 -0
  54. package/lib/css/CssGenerator.js +109 -0
  55. package/lib/css/CssLoadingRuntimeModule.js +440 -0
  56. package/lib/css/CssModulesPlugin.js +462 -0
  57. package/lib/css/CssParser.js +618 -0
  58. package/lib/css/walkCssTokens.js +659 -0
  59. package/lib/debug/ProfilingPlugin.js +15 -14
  60. package/lib/dependencies/ContextElementDependency.js +8 -2
  61. package/lib/dependencies/CreateScriptUrlDependency.js +12 -0
  62. package/lib/dependencies/CssExportDependency.js +85 -0
  63. package/lib/dependencies/CssImportDependency.js +75 -0
  64. package/lib/dependencies/CssLocalIdentifierDependency.js +119 -0
  65. package/lib/dependencies/CssSelfLocalIdentifierDependency.js +101 -0
  66. package/lib/dependencies/CssUrlDependency.js +132 -0
  67. package/lib/dependencies/ExportsInfoDependency.js +6 -0
  68. package/lib/dependencies/HarmonyCompatibilityDependency.js +5 -5
  69. package/lib/dependencies/ImportMetaPlugin.js +22 -3
  70. package/lib/dependencies/LoaderPlugin.js +2 -2
  71. package/lib/dependencies/URLDependency.js +3 -8
  72. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +1 -1
  73. package/lib/hmr/LazyCompilationPlugin.js +45 -21
  74. package/lib/hmr/lazyCompilationBackend.js +4 -2
  75. package/lib/ids/DeterministicModuleIdsPlugin.js +55 -35
  76. package/lib/ids/HashedModuleIdsPlugin.js +9 -12
  77. package/lib/ids/IdHelpers.js +24 -10
  78. package/lib/ids/NamedModuleIdsPlugin.js +6 -9
  79. package/lib/ids/NaturalModuleIdsPlugin.js +10 -13
  80. package/lib/ids/OccurrenceModuleIdsPlugin.js +13 -10
  81. package/lib/ids/SyncModuleIdsPlugin.js +140 -0
  82. package/lib/index.js +10 -0
  83. package/lib/javascript/JavascriptGenerator.js +1 -0
  84. package/lib/javascript/JavascriptModulesPlugin.js +27 -2
  85. package/lib/javascript/StartupHelpers.js +6 -5
  86. package/lib/library/AssignLibraryPlugin.js +34 -5
  87. package/lib/library/EnableLibraryPlugin.js +11 -0
  88. package/lib/node/NodeTargetPlugin.js +1 -0
  89. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +1 -1
  90. package/lib/node/RequireChunkLoadingRuntimeModule.js +1 -1
  91. package/lib/optimize/ConcatenatedModule.js +21 -9
  92. package/lib/runtime/AsyncModuleRuntimeModule.js +25 -15
  93. package/lib/runtime/CreateScriptRuntimeModule.js +36 -0
  94. package/lib/runtime/CreateScriptUrlRuntimeModule.js +9 -34
  95. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +76 -0
  96. package/lib/schemes/HttpUriPlugin.js +32 -11
  97. package/lib/serialization/FileMiddleware.js +44 -9
  98. package/lib/sharing/ConsumeSharedModule.js +4 -2
  99. package/lib/sharing/ProvideSharedModule.js +4 -2
  100. package/lib/sharing/utils.js +1 -1
  101. package/lib/stats/DefaultStatsFactoryPlugin.js +112 -67
  102. package/lib/stats/DefaultStatsPrinterPlugin.js +88 -23
  103. package/lib/util/ArrayHelpers.js +18 -4
  104. package/lib/util/AsyncQueue.js +1 -1
  105. package/lib/util/compileBooleanMatcher.js +1 -1
  106. package/lib/util/deterministicGrouping.js +1 -1
  107. package/lib/util/hash/xxhash64.js +2 -2
  108. package/lib/util/identifier.js +65 -44
  109. package/lib/util/internalSerializables.js +11 -0
  110. package/lib/util/nonNumericOnlyHash.js +22 -0
  111. package/lib/util/semver.js +17 -10
  112. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +9 -3
  113. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -2
  114. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +3 -11
  115. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +1 -1
  116. package/package.json +16 -23
  117. package/schemas/WebpackOptions.check.js +1 -1
  118. package/schemas/WebpackOptions.json +96 -1
  119. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  120. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  121. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  122. package/schemas/plugins/container/ContainerPlugin.json +2 -1
  123. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  124. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  125. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  126. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  127. package/schemas/plugins/container/ModuleFederationPlugin.json +3 -1
  128. package/schemas/plugins/css/CssGeneratorOptions.check.d.ts +7 -0
  129. package/schemas/plugins/css/CssGeneratorOptions.check.js +6 -0
  130. package/schemas/plugins/css/CssGeneratorOptions.json +3 -0
  131. package/schemas/plugins/css/CssParserOptions.check.d.ts +7 -0
  132. package/schemas/plugins/css/CssParserOptions.check.js +6 -0
  133. package/schemas/plugins/css/CssParserOptions.json +3 -0
  134. package/types.d.ts +295 -59
@@ -29,6 +29,7 @@ const { registerNotSerializable } = require("../util/serialization");
29
29
  /** @typedef {import("../RequestShortener")} RequestShortener */
30
30
  /** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
31
31
  /** @typedef {import("../WebpackError")} WebpackError */
32
+ /** @typedef {import("../dependencies/HarmonyImportDependency")} HarmonyImportDependency */
32
33
  /** @typedef {import("../util/Hash")} Hash */
33
34
  /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
34
35
 
@@ -38,7 +39,7 @@ const { registerNotSerializable } = require("../util/serialization");
38
39
  * @property {function(Module): { client: string, data: string, active: boolean }} module
39
40
  */
40
41
 
41
- const IGNORED_DEPENDENCY_TYPES = new Set([
42
+ const HMR_DEPENDENCY_TYPES = new Set([
42
43
  "import.meta.webpackHot.accept",
43
44
  "import.meta.webpackHot.decline",
44
45
  "module.hot.accept",
@@ -146,7 +147,7 @@ class LazyCompilationProxyModule extends Module {
146
147
 
147
148
  /**
148
149
  * @param {NeedBuildContext} context context info
149
- * @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
150
+ * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
150
151
  * @returns {void}
151
152
  */
152
153
  needBuild(context, callback) {
@@ -351,32 +352,55 @@ class LazyCompilationPlugin {
351
352
  "LazyCompilationPlugin",
352
353
  (originalModule, createData, resolveData) => {
353
354
  if (
354
- resolveData.dependencies.every(
355
+ resolveData.dependencies.every(dep =>
356
+ HMR_DEPENDENCY_TYPES.has(dep.type)
357
+ )
358
+ ) {
359
+ // for HMR only resolving, try to determine if the HMR accept/decline refers to
360
+ // an import() or not
361
+ const hmrDep = resolveData.dependencies[0];
362
+ const originModule =
363
+ compilation.moduleGraph.getParentModule(hmrDep);
364
+ const isReferringToDynamicImport = originModule.blocks.some(
365
+ block =>
366
+ block.dependencies.some(
367
+ dep =>
368
+ dep.type === "import()" &&
369
+ /** @type {HarmonyImportDependency} */ (dep).request ===
370
+ hmrDep.request
371
+ )
372
+ );
373
+ if (!isReferringToDynamicImport) return;
374
+ } else if (
375
+ !resolveData.dependencies.every(
355
376
  dep =>
356
- IGNORED_DEPENDENCY_TYPES.has(dep.type) ||
377
+ HMR_DEPENDENCY_TYPES.has(dep.type) ||
357
378
  (this.imports &&
358
379
  (dep.type === "import()" ||
359
380
  dep.type === "import() context element")) ||
360
381
  (this.entries && dep.type === "entry")
361
- ) &&
362
- !/webpack[/\\]hot[/\\]|webpack-dev-server[/\\]client/.test(
382
+ )
383
+ )
384
+ return;
385
+ if (
386
+ /webpack[/\\]hot[/\\]|webpack-dev-server[/\\]client|webpack-hot-middleware[/\\]client/.test(
363
387
  resolveData.request
364
- ) &&
365
- checkTest(this.test, originalModule)
366
- ) {
367
- const moduleInfo = backend.module(originalModule);
368
- if (!moduleInfo) return;
369
- const { client, data, active } = moduleInfo;
388
+ ) ||
389
+ !checkTest(this.test, originalModule)
390
+ )
391
+ return;
392
+ const moduleInfo = backend.module(originalModule);
393
+ if (!moduleInfo) return;
394
+ const { client, data, active } = moduleInfo;
370
395
 
371
- return new LazyCompilationProxyModule(
372
- compiler.context,
373
- originalModule,
374
- resolveData.request,
375
- client,
376
- data,
377
- active
378
- );
379
- }
396
+ return new LazyCompilationProxyModule(
397
+ compiler.context,
398
+ originalModule,
399
+ resolveData.request,
400
+ client,
401
+ data,
402
+ active
403
+ );
380
404
  }
381
405
  );
382
406
  compilation.dependencyFactories.set(
@@ -13,7 +13,7 @@
13
13
  /**
14
14
  * @callback BackendHandler
15
15
  * @param {Compiler} compiler compiler
16
- * @param {function(Error?, any?): void} callback callback
16
+ * @param {function((Error | null)=, any=): void} callback callback
17
17
  * @returns {void}
18
18
  */
19
19
 
@@ -68,7 +68,9 @@ module.exports = options => (compiler, callback) => {
68
68
  req.socket.setNoDelay(true);
69
69
  res.writeHead(200, {
70
70
  "content-type": "text/event-stream",
71
- "Access-Control-Allow-Origin": "*"
71
+ "Access-Control-Allow-Origin": "*",
72
+ "Access-Control-Allow-Methods": "*",
73
+ "Access-Control-Allow-Headers": "*"
72
74
  });
73
75
  res.write("\n");
74
76
  let moduleActivated = false;
@@ -9,7 +9,7 @@ const {
9
9
  compareModulesByPreOrderIndexOrIdentifier
10
10
  } = require("../util/comparators");
11
11
  const {
12
- getUsedModuleIds,
12
+ getUsedModuleIdsAndModules,
13
13
  getFullModuleName,
14
14
  assignDeterministicIds
15
15
  } = require("./IdHelpers");
@@ -18,8 +18,17 @@ const {
18
18
  /** @typedef {import("../Module")} Module */
19
19
 
20
20
  class DeterministicModuleIdsPlugin {
21
- constructor(options) {
22
- this.options = options || {};
21
+ /**
22
+ * @param {Object} options options
23
+ * @param {string=} options.context context relative to which module identifiers are computed
24
+ * @param {function(Module): boolean=} options.test selector function for modules
25
+ * @param {number=} options.maxLength maximum id length in digits (used as starting point)
26
+ * @param {number=} options.salt hash salt for ids
27
+ * @param {boolean=} options.fixedLength do not increase the maxLength to find an optimal id space size
28
+ * @param {boolean=} options.failOnConflict throw an error when id conflicts occur (instead of rehashing)
29
+ */
30
+ constructor(options = {}) {
31
+ this.options = options;
23
32
  }
24
33
 
25
34
  /**
@@ -31,40 +40,51 @@ class DeterministicModuleIdsPlugin {
31
40
  compiler.hooks.compilation.tap(
32
41
  "DeterministicModuleIdsPlugin",
33
42
  compilation => {
34
- compilation.hooks.moduleIds.tap(
35
- "DeterministicModuleIdsPlugin",
36
- modules => {
37
- const chunkGraph = compilation.chunkGraph;
38
- const context = this.options.context
39
- ? this.options.context
40
- : compiler.context;
41
- const maxLength = this.options.maxLength || 3;
43
+ compilation.hooks.moduleIds.tap("DeterministicModuleIdsPlugin", () => {
44
+ const chunkGraph = compilation.chunkGraph;
45
+ const context = this.options.context
46
+ ? this.options.context
47
+ : compiler.context;
48
+ const maxLength = this.options.maxLength || 3;
49
+ const failOnConflict = this.options.failOnConflict || false;
50
+ const fixedLength = this.options.fixedLength || false;
51
+ const salt = this.options.salt || 0;
52
+ let conflicts = 0;
42
53
 
43
- const usedIds = getUsedModuleIds(compilation);
44
- assignDeterministicIds(
45
- Array.from(modules).filter(module => {
46
- if (!module.needId) return false;
47
- if (chunkGraph.getNumberOfModuleChunks(module) === 0)
48
- return false;
49
- return chunkGraph.getModuleId(module) === null;
50
- }),
51
- module => getFullModuleName(module, context, compiler.root),
52
- compareModulesByPreOrderIndexOrIdentifier(
53
- compilation.moduleGraph
54
- ),
55
- (module, id) => {
56
- const size = usedIds.size;
57
- usedIds.add(`${id}`);
58
- if (size === usedIds.size) return false;
59
- chunkGraph.setModuleId(module, id);
60
- return true;
61
- },
62
- [Math.pow(10, maxLength)],
63
- 10,
64
- usedIds.size
54
+ const [usedIds, modules] = getUsedModuleIdsAndModules(
55
+ compilation,
56
+ this.options.test
57
+ );
58
+ assignDeterministicIds(
59
+ modules,
60
+ module => getFullModuleName(module, context, compiler.root),
61
+ failOnConflict
62
+ ? () => 0
63
+ : compareModulesByPreOrderIndexOrIdentifier(
64
+ compilation.moduleGraph
65
+ ),
66
+ (module, id) => {
67
+ const size = usedIds.size;
68
+ usedIds.add(`${id}`);
69
+ if (size === usedIds.size) {
70
+ conflicts++;
71
+ return false;
72
+ }
73
+ chunkGraph.setModuleId(module, id);
74
+ return true;
75
+ },
76
+ [Math.pow(10, maxLength)],
77
+ fixedLength ? 0 : 10,
78
+ usedIds.size,
79
+ salt
80
+ );
81
+ if (failOnConflict && conflicts)
82
+ throw new Error(
83
+ `Assigning deterministic module ids has lead to ${conflicts} conflict${
84
+ conflicts > 1 ? "s" : ""
85
+ }.\nIncrease the 'maxLength' to increase the id space and make conflicts less likely (recommended when there are many conflicts or application is expected to grow), or add an 'salt' number to try another hash starting value in the same id space (recommended when there is only a single conflict).`
65
86
  );
66
- }
67
- );
87
+ });
68
88
  }
69
89
  );
70
90
  }
@@ -10,7 +10,10 @@ const {
10
10
  } = require("../util/comparators");
11
11
  const createSchemaValidation = require("../util/create-schema-validation");
12
12
  const createHash = require("../util/createHash");
13
- const { getUsedModuleIds, getFullModuleName } = require("./IdHelpers");
13
+ const {
14
+ getUsedModuleIdsAndModules,
15
+ getFullModuleName
16
+ } = require("./IdHelpers");
14
17
 
15
18
  /** @typedef {import("../../declarations/plugins/HashedModuleIdsPlugin").HashedModuleIdsPluginOptions} HashedModuleIdsPluginOptions */
16
19
 
@@ -43,22 +46,16 @@ class HashedModuleIdsPlugin {
43
46
  apply(compiler) {
44
47
  const options = this.options;
45
48
  compiler.hooks.compilation.tap("HashedModuleIdsPlugin", compilation => {
46
- compilation.hooks.moduleIds.tap("HashedModuleIdsPlugin", modules => {
49
+ compilation.hooks.moduleIds.tap("HashedModuleIdsPlugin", () => {
47
50
  const chunkGraph = compilation.chunkGraph;
48
51
  const context = this.options.context
49
52
  ? this.options.context
50
53
  : compiler.context;
51
54
 
52
- const usedIds = getUsedModuleIds(compilation);
53
- const modulesInNaturalOrder = Array.from(modules)
54
- .filter(m => {
55
- if (!m.needId) return false;
56
- if (chunkGraph.getNumberOfModuleChunks(m) === 0) return false;
57
- return chunkGraph.getModuleId(module) === null;
58
- })
59
- .sort(
60
- compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
61
- );
55
+ const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
56
+ const modulesInNaturalOrder = modules.sort(
57
+ compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
58
+ );
62
59
  for (const module of modulesInNaturalOrder) {
63
60
  const ident = getFullModuleName(module, context, compiler.root);
64
61
  const hash = createHash(options.hashFunction);
@@ -234,11 +234,14 @@ const addToMapOfItems = (map, key, value) => {
234
234
 
235
235
  /**
236
236
  * @param {Compilation} compilation the compilation
237
- * @returns {Set<string>} used module ids as strings
237
+ * @param {function(Module): boolean=} filter filter modules
238
+ * @returns {[Set<string>, Module[]]} used module ids as strings and modules without id matching the filter
238
239
  */
239
- const getUsedModuleIds = compilation => {
240
+ const getUsedModuleIdsAndModules = (compilation, filter) => {
240
241
  const chunkGraph = compilation.chunkGraph;
241
242
 
243
+ const modules = [];
244
+
242
245
  /** @type {Set<string>} */
243
246
  const usedIds = new Set();
244
247
  if (compilation.usedModuleIds) {
@@ -248,15 +251,23 @@ const getUsedModuleIds = compilation => {
248
251
  }
249
252
 
250
253
  for (const module of compilation.modules) {
254
+ if (!module.needId) continue;
251
255
  const moduleId = chunkGraph.getModuleId(module);
252
256
  if (moduleId !== null) {
253
257
  usedIds.add(moduleId + "");
258
+ } else {
259
+ if (
260
+ (!filter || filter(module)) &&
261
+ chunkGraph.getNumberOfModuleChunks(module) !== 0
262
+ ) {
263
+ modules.push(module);
264
+ }
254
265
  }
255
266
  }
256
267
 
257
- return usedIds;
268
+ return [usedIds, modules];
258
269
  };
259
- exports.getUsedModuleIds = getUsedModuleIds;
270
+ exports.getUsedModuleIdsAndModules = getUsedModuleIdsAndModules;
260
271
 
261
272
  /**
262
273
  * @param {Compilation} compilation the compilation
@@ -359,6 +370,7 @@ exports.assignNames = assignNames;
359
370
  * @param {number[]} ranges usable ranges for ids
360
371
  * @param {number} expandFactor factor to create more ranges
361
372
  * @param {number} extraSpace extra space to allocate, i. e. when some ids are already used
373
+ * @param {number} salt salting number to initialize hashing
362
374
  * @returns {void}
363
375
  */
364
376
  const assignDeterministicIds = (
@@ -368,7 +380,8 @@ const assignDeterministicIds = (
368
380
  assignId,
369
381
  ranges = [10],
370
382
  expandFactor = 10,
371
- extraSpace = 0
383
+ extraSpace = 0,
384
+ salt = 0
372
385
  ) => {
373
386
  items.sort(comparator);
374
387
 
@@ -384,15 +397,17 @@ const assignDeterministicIds = (
384
397
  i++;
385
398
  if (i < ranges.length) {
386
399
  range = Math.min(ranges[i], Number.MAX_SAFE_INTEGER);
387
- } else {
400
+ } else if (expandFactor) {
388
401
  range = Math.min(range * expandFactor, Number.MAX_SAFE_INTEGER);
402
+ } else {
403
+ break;
389
404
  }
390
405
  }
391
406
 
392
407
  for (const item of items) {
393
408
  const ident = getName(item);
394
409
  let id;
395
- let i = 0;
410
+ let i = salt;
396
411
  do {
397
412
  id = numberHash(ident + i++, range);
398
413
  } while (!assignId(item, id));
@@ -401,15 +416,14 @@ const assignDeterministicIds = (
401
416
  exports.assignDeterministicIds = assignDeterministicIds;
402
417
 
403
418
  /**
419
+ * @param {Set<string>} usedIds used ids
404
420
  * @param {Iterable<Module>} modules the modules
405
421
  * @param {Compilation} compilation the compilation
406
422
  * @returns {void}
407
423
  */
408
- const assignAscendingModuleIds = (modules, compilation) => {
424
+ const assignAscendingModuleIds = (usedIds, modules, compilation) => {
409
425
  const chunkGraph = compilation.chunkGraph;
410
426
 
411
- const usedIds = getUsedModuleIds(compilation);
412
-
413
427
  let nextId = 0;
414
428
  let assignId;
415
429
  if (usedIds.size > 0) {
@@ -10,7 +10,7 @@ const {
10
10
  getShortModuleName,
11
11
  getLongModuleName,
12
12
  assignNames,
13
- getUsedModuleIds,
13
+ getUsedModuleIdsAndModules,
14
14
  assignAscendingModuleIds
15
15
  } = require("./IdHelpers");
16
16
 
@@ -31,27 +31,24 @@ class NamedModuleIdsPlugin {
31
31
  const { root } = compiler;
32
32
  compiler.hooks.compilation.tap("NamedModuleIdsPlugin", compilation => {
33
33
  const { hashFunction } = compilation.outputOptions;
34
- compilation.hooks.moduleIds.tap("NamedModuleIdsPlugin", modules => {
34
+ compilation.hooks.moduleIds.tap("NamedModuleIdsPlugin", () => {
35
35
  const chunkGraph = compilation.chunkGraph;
36
36
  const context = this.options.context
37
37
  ? this.options.context
38
38
  : compiler.context;
39
39
 
40
+ const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
40
41
  const unnamedModules = assignNames(
41
- Array.from(modules).filter(module => {
42
- if (!module.needId) return false;
43
- if (chunkGraph.getNumberOfModuleChunks(module) === 0) return false;
44
- return chunkGraph.getModuleId(module) === null;
45
- }),
42
+ modules,
46
43
  m => getShortModuleName(m, context, root),
47
44
  (m, shortName) =>
48
45
  getLongModuleName(shortName, m, context, hashFunction, root),
49
46
  compareModulesByIdentifier,
50
- getUsedModuleIds(compilation),
47
+ usedIds,
51
48
  (m, name) => chunkGraph.setModuleId(m, name)
52
49
  );
53
50
  if (unnamedModules.length > 0) {
54
- assignAscendingModuleIds(unnamedModules, compilation);
51
+ assignAscendingModuleIds(usedIds, unnamedModules, compilation);
55
52
  }
56
53
  });
57
54
  });
@@ -8,7 +8,10 @@
8
8
  const {
9
9
  compareModulesByPreOrderIndexOrIdentifier
10
10
  } = require("../util/comparators");
11
- const { assignAscendingModuleIds } = require("./IdHelpers");
11
+ const {
12
+ assignAscendingModuleIds,
13
+ getUsedModuleIdsAndModules
14
+ } = require("./IdHelpers");
12
15
 
13
16
  /** @typedef {import("../Compiler")} Compiler */
14
17
  /** @typedef {import("../Module")} Module */
@@ -22,18 +25,12 @@ class NaturalModuleIdsPlugin {
22
25
  apply(compiler) {
23
26
  compiler.hooks.compilation.tap("NaturalModuleIdsPlugin", compilation => {
24
27
  compilation.hooks.moduleIds.tap("NaturalModuleIdsPlugin", modules => {
25
- const chunkGraph = compilation.chunkGraph;
26
- const modulesInNaturalOrder = Array.from(modules)
27
- .filter(
28
- m =>
29
- m.needId &&
30
- chunkGraph.getNumberOfModuleChunks(m) > 0 &&
31
- chunkGraph.getModuleId(m) === null
32
- )
33
- .sort(
34
- compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
35
- );
36
- assignAscendingModuleIds(modulesInNaturalOrder, compilation);
28
+ const [usedIds, modulesInNaturalOrder] =
29
+ getUsedModuleIdsAndModules(compilation);
30
+ modulesInNaturalOrder.sort(
31
+ compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
32
+ );
33
+ assignAscendingModuleIds(usedIds, modulesInNaturalOrder, compilation);
37
34
  });
38
35
  });
39
36
  }
@@ -9,7 +9,10 @@ const {
9
9
  compareModulesByPreOrderIndexOrIdentifier
10
10
  } = require("../util/comparators");
11
11
  const createSchemaValidation = require("../util/create-schema-validation");
12
- const { assignAscendingModuleIds } = require("./IdHelpers");
12
+ const {
13
+ assignAscendingModuleIds,
14
+ getUsedModuleIdsAndModules
15
+ } = require("./IdHelpers");
13
16
 
14
17
  /** @typedef {import("../../declarations/plugins/ids/OccurrenceModuleIdsPlugin").OccurrenceModuleIdsPluginOptions} OccurrenceModuleIdsPluginOptions */
15
18
  /** @typedef {import("../Compiler")} Compiler */
@@ -44,15 +47,11 @@ class OccurrenceModuleIdsPlugin {
44
47
  compiler.hooks.compilation.tap("OccurrenceModuleIdsPlugin", compilation => {
45
48
  const moduleGraph = compilation.moduleGraph;
46
49
 
47
- compilation.hooks.moduleIds.tap("OccurrenceModuleIdsPlugin", modules => {
50
+ compilation.hooks.moduleIds.tap("OccurrenceModuleIdsPlugin", () => {
48
51
  const chunkGraph = compilation.chunkGraph;
49
52
 
50
- const modulesInOccurrenceOrder = Array.from(modules).filter(
51
- m =>
52
- m.needId &&
53
- chunkGraph.getNumberOfModuleChunks(m) > 0 &&
54
- chunkGraph.getModuleId(m) === null
55
- );
53
+ const [usedIds, modulesInOccurrenceOrder] =
54
+ getUsedModuleIdsAndModules(compilation);
56
55
 
57
56
  const occursInInitialChunksMap = new Map();
58
57
  const occursInAllChunksMap = new Map();
@@ -121,7 +120,7 @@ class OccurrenceModuleIdsPlugin {
121
120
  }
122
121
  }
123
122
 
124
- for (const m of modules) {
123
+ for (const m of modulesInOccurrenceOrder) {
125
124
  const result =
126
125
  countOccurs(m) +
127
126
  chunkGraph.getNumberOfModuleChunks(m) +
@@ -147,7 +146,11 @@ class OccurrenceModuleIdsPlugin {
147
146
  return naturalCompare(a, b);
148
147
  });
149
148
 
150
- assignAscendingModuleIds(modulesInOccurrenceOrder, compilation);
149
+ assignAscendingModuleIds(
150
+ usedIds,
151
+ modulesInOccurrenceOrder,
152
+ compilation
153
+ );
151
154
  });
152
155
  });
153
156
  }
@@ -0,0 +1,140 @@
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 { WebpackError } = require("..");
9
+ const { getUsedModuleIdsAndModules } = require("./IdHelpers");
10
+
11
+ /** @typedef {import("../Compiler")} Compiler */
12
+ /** @typedef {import("../Module")} Module */
13
+
14
+ const plugin = "SyncModuleIdsPlugin";
15
+
16
+ class SyncModuleIdsPlugin {
17
+ /**
18
+ * @param {Object} options options
19
+ * @param {string} options.path path to file
20
+ * @param {string=} options.context context for module names
21
+ * @param {function(Module): boolean} options.test selector for modules
22
+ * @param {"read" | "create" | "merge" | "update"=} options.mode operation mode (defaults to merge)
23
+ */
24
+ constructor({ path, context, test, mode }) {
25
+ this._path = path;
26
+ this._context = context;
27
+ this._test = test || (() => true);
28
+ const readAndWrite = !mode || mode === "merge" || mode === "update";
29
+ this._read = readAndWrite || mode === "read";
30
+ this._write = readAndWrite || mode === "create";
31
+ this._prune = mode === "update";
32
+ }
33
+
34
+ /**
35
+ * Apply the plugin
36
+ * @param {Compiler} compiler the compiler instance
37
+ * @returns {void}
38
+ */
39
+ apply(compiler) {
40
+ /** @type {Map<string, string | number>} */
41
+ let data;
42
+ let dataChanged = false;
43
+ if (this._read) {
44
+ compiler.hooks.readRecords.tapAsync(plugin, callback => {
45
+ const fs = compiler.intermediateFileSystem;
46
+ fs.readFile(this._path, (err, buffer) => {
47
+ if (err) {
48
+ if (err.code !== "ENOENT") {
49
+ return callback(err);
50
+ }
51
+ return callback();
52
+ }
53
+ const json = JSON.parse(buffer.toString());
54
+ data = new Map();
55
+ for (const key of Object.keys(json)) {
56
+ data.set(key, json[key]);
57
+ }
58
+ dataChanged = false;
59
+ return callback();
60
+ });
61
+ });
62
+ }
63
+ if (this._write) {
64
+ compiler.hooks.emitRecords.tapAsync(plugin, callback => {
65
+ if (!data || !dataChanged) return callback();
66
+ const json = {};
67
+ const sorted = Array.from(data).sort(([a], [b]) => (a < b ? -1 : 1));
68
+ for (const [key, value] of sorted) {
69
+ json[key] = value;
70
+ }
71
+ const fs = compiler.intermediateFileSystem;
72
+ fs.writeFile(this._path, JSON.stringify(json), callback);
73
+ });
74
+ }
75
+ compiler.hooks.thisCompilation.tap(plugin, compilation => {
76
+ const associatedObjectForCache = compiler.root;
77
+ const context = this._context || compiler.context;
78
+ if (this._read) {
79
+ compilation.hooks.reviveModules.tap(plugin, (_1, _2) => {
80
+ if (!data) return;
81
+ const { chunkGraph } = compilation;
82
+ const [usedIds, modules] = getUsedModuleIdsAndModules(
83
+ compilation,
84
+ this._test
85
+ );
86
+ for (const module of modules) {
87
+ const name = module.libIdent({
88
+ context,
89
+ associatedObjectForCache
90
+ });
91
+ if (!name) continue;
92
+ const id = data.get(name);
93
+ const idAsString = `${id}`;
94
+ if (usedIds.has(idAsString)) {
95
+ const err = new WebpackError(
96
+ `SyncModuleIdsPlugin: Unable to restore id '${id}' from '${this._path}' as it's already used.`
97
+ );
98
+ err.module = module;
99
+ compilation.errors.push(err);
100
+ }
101
+ chunkGraph.setModuleId(module, id);
102
+ usedIds.add(idAsString);
103
+ }
104
+ });
105
+ }
106
+ if (this._write) {
107
+ compilation.hooks.recordModules.tap(plugin, modules => {
108
+ const { chunkGraph } = compilation;
109
+ let oldData = data;
110
+ if (!oldData) {
111
+ oldData = data = new Map();
112
+ } else if (this._prune) {
113
+ data = new Map();
114
+ }
115
+ for (const module of modules) {
116
+ if (this._test(module)) {
117
+ const name = module.libIdent({
118
+ context,
119
+ associatedObjectForCache
120
+ });
121
+ if (!name) continue;
122
+ const id = chunkGraph.getModuleId(module);
123
+ if (id === null) continue;
124
+ const oldId = oldData.get(name);
125
+ if (oldId !== id) {
126
+ dataChanged = true;
127
+ } else if (data === oldData) {
128
+ continue;
129
+ }
130
+ data.set(name, id);
131
+ }
132
+ }
133
+ if (data.size !== oldData.size) dataChanged = true;
134
+ });
135
+ }
136
+ });
137
+ }
138
+ }
139
+
140
+ module.exports = SyncModuleIdsPlugin;