webpack 5.36.0 → 5.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (110) hide show
  1. package/README.md +5 -8
  2. package/bin/webpack.js +0 -0
  3. package/lib/CacheFacade.js +3 -3
  4. package/lib/Chunk.js +10 -5
  5. package/lib/ChunkGraph.js +58 -35
  6. package/lib/Compilation.js +116 -98
  7. package/lib/Compiler.js +31 -17
  8. package/lib/ConcatenationScope.js +2 -1
  9. package/lib/ContextModule.js +3 -3
  10. package/lib/ContextReplacementPlugin.js +4 -3
  11. package/lib/DefinePlugin.js +16 -12
  12. package/lib/EntryPlugin.js +1 -1
  13. package/lib/EvalSourceMapDevToolPlugin.js +3 -1
  14. package/lib/FileSystemInfo.js +25 -31
  15. package/lib/FlagDependencyExportsPlugin.js +8 -7
  16. package/lib/FlagDependencyUsagePlugin.js +2 -4
  17. package/lib/HotModuleReplacementPlugin.js +20 -30
  18. package/lib/InitFragment.js +21 -6
  19. package/lib/JavascriptMetaInfoPlugin.js +2 -1
  20. package/lib/MainTemplate.js +2 -3
  21. package/lib/ModuleFilenameHelpers.js +4 -2
  22. package/lib/ModuleGraph.js +2 -2
  23. package/lib/ModuleGraphConnection.js +6 -2
  24. package/lib/ModuleInfoHeaderPlugin.js +2 -3
  25. package/lib/MultiCompiler.js +31 -27
  26. package/lib/NormalModule.js +38 -7
  27. package/lib/NormalModuleFactory.js +27 -23
  28. package/lib/RecordIdsPlugin.js +5 -4
  29. package/lib/ResolverFactory.js +10 -7
  30. package/lib/RuntimeGlobals.js +7 -0
  31. package/lib/RuntimePlugin.js +19 -1
  32. package/lib/SourceMapDevToolPlugin.js +14 -15
  33. package/lib/Template.js +4 -2
  34. package/lib/Watching.js +83 -46
  35. package/lib/WebpackOptionsApply.js +1 -0
  36. package/lib/asset/AssetGenerator.js +19 -23
  37. package/lib/buildChunkGraph.js +28 -23
  38. package/lib/cache/PackFileCacheStrategy.js +77 -13
  39. package/lib/config/defaults.js +24 -10
  40. package/lib/config/normalization.js +17 -7
  41. package/lib/debug/ProfilingPlugin.js +4 -3
  42. package/lib/dependencies/AMDRequireDependency.js +3 -3
  43. package/lib/dependencies/CommonJsExportRequireDependency.js +2 -3
  44. package/lib/dependencies/CommonJsExportsParserPlugin.js +3 -1
  45. package/lib/dependencies/CommonJsImportsParserPlugin.js +2 -4
  46. package/lib/dependencies/CommonJsPlugin.js +8 -7
  47. package/lib/dependencies/CommonJsRequireContextDependency.js +2 -1
  48. package/lib/dependencies/ContextDependencyHelpers.js +10 -8
  49. package/lib/dependencies/CreateScriptUrlDependency.js +54 -0
  50. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +11 -13
  51. package/lib/dependencies/HarmonyExportInitFragment.js +47 -0
  52. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +2 -4
  53. package/lib/dependencies/HarmonyImportSpecifierDependency.js +4 -11
  54. package/lib/dependencies/ImportDependency.js +3 -3
  55. package/lib/dependencies/ImportParserPlugin.js +2 -4
  56. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +2 -3
  57. package/lib/dependencies/RequireEnsureDependency.js +3 -3
  58. package/lib/dependencies/WorkerDependency.js +6 -6
  59. package/lib/dependencies/WorkerPlugin.js +47 -20
  60. package/lib/hmr/LazyCompilationPlugin.js +6 -4
  61. package/lib/ids/HashedModuleIdsPlugin.js +3 -3
  62. package/lib/ids/OccurrenceModuleIdsPlugin.js +2 -3
  63. package/lib/index.js +5 -3
  64. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -6
  65. package/lib/javascript/CommonJsChunkFormatPlugin.js +2 -3
  66. package/lib/javascript/JavascriptGenerator.js +3 -1
  67. package/lib/javascript/JavascriptModulesPlugin.js +15 -23
  68. package/lib/javascript/JavascriptParser.js +10 -8
  69. package/lib/library/AssignLibraryPlugin.js +4 -2
  70. package/lib/node/NodeWatchFileSystem.js +19 -4
  71. package/lib/optimize/AggressiveSplittingPlugin.js +5 -4
  72. package/lib/optimize/ConcatenatedModule.js +22 -27
  73. package/lib/optimize/FlagIncludedChunksPlugin.js +4 -6
  74. package/lib/optimize/InnerGraph.js +9 -11
  75. package/lib/optimize/InnerGraphPlugin.js +3 -1
  76. package/lib/optimize/ModuleConcatenationPlugin.js +7 -10
  77. package/lib/optimize/RealContentHashPlugin.js +14 -16
  78. package/lib/optimize/SideEffectsFlagPlugin.js +6 -5
  79. package/lib/optimize/SplitChunksPlugin.js +13 -15
  80. package/lib/runtime/CreateScriptUrlRuntimeModule.js +61 -0
  81. package/lib/runtime/EnsureChunkRuntimeModule.js +9 -8
  82. package/lib/runtime/LoadScriptRuntimeModule.js +12 -5
  83. package/lib/runtime/OnChunksLoadedRuntimeModule.js +38 -37
  84. package/lib/serialization/BinaryMiddleware.js +2 -3
  85. package/lib/serialization/FileMiddleware.js +3 -1
  86. package/lib/serialization/ObjectMiddleware.js +11 -7
  87. package/lib/stats/DefaultStatsFactoryPlugin.js +2 -3
  88. package/lib/stats/DefaultStatsPrinterPlugin.js +11 -9
  89. package/lib/stats/StatsFactory.js +2 -1
  90. package/lib/stats/StatsPrinter.js +3 -3
  91. package/lib/util/LazyBucketSortedSet.js +3 -3
  92. package/lib/util/cleverMerge.js +3 -1
  93. package/lib/util/comparators.js +13 -13
  94. package/lib/util/fs.js +8 -8
  95. package/lib/util/identifier.js +2 -1
  96. package/lib/util/internalSerializables.js +2 -0
  97. package/lib/validateSchema.js +5 -3
  98. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +4 -4
  99. package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +5 -4
  100. package/lib/wasm-sync/WebAssemblyGenerator.js +89 -83
  101. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +2 -1
  102. package/lib/wasm-sync/WebAssemblyParser.js +6 -5
  103. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -4
  104. package/lib/webpack.js +11 -7
  105. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +13 -1
  106. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +14 -4
  107. package/package.json +9 -6
  108. package/schemas/WebpackOptions.check.js +1 -1
  109. package/schemas/WebpackOptions.json +103 -60
  110. package/types.d.ts +463 -280
package/README.md CHANGED
@@ -169,17 +169,14 @@ or are automatically applied via regex from your webpack configuration.
169
169
 
170
170
  #### Transpiling
171
171
 
172
- | Name | Status | Install Size | Description |
173
- | :--------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------: | :-------------: | :--------------------------------------------------------------------------------------------------- |
174
- | <a href="https://github.com/babel/babel-loader"><img width="48" height="48" title="babel-loader" src="https://worldvectorlogo.com/logos/babel-10.svg"></a> | ![babel-npm] | ![babel-size] | Loads ES2015+ code and transpiles to ES5 using <a href="https://github.com/babel/babel">Babel</a> |
175
- | <a href="https://github.com/jupl/traceur-loader"><img width="48" height="48" src="https://google.github.com/traceur-compiler/logo/tc.svg"></a> | ![traceur-npm] | ![traceur-size] | Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler) |
176
- | <a href="https://github.com/TypeStrong/ts-loader"><img width="48" height="48" src="https://cdn.rawgit.com/Microsoft/TypeScript/master/doc/logo.svg"></a> | ![type-npm] | ![type-size] | Loads TypeScript like JavaScript |
177
- | <a href="https://github.com/webpack-contrib/coffee-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![coffee-npm] | ![coffee-size] | Loads CoffeeScript like JavaScript |
172
+ | Name | Status | Install Size | Description |
173
+ | :--------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------: | :------------: | :------------------------------------------------------------------------------------------------ |
174
+ | <a href="https://github.com/babel/babel-loader"><img width="48" height="48" title="babel-loader" src="https://worldvectorlogo.com/logos/babel-10.svg"></a> | ![babel-npm] | ![babel-size] | Loads ES2015+ code and transpiles to ES5 using <a href="https://github.com/babel/babel">Babel</a> |
175
+ | <a href="https://github.com/TypeStrong/ts-loader"><img width="48" height="48" src="https://cdn.rawgit.com/Microsoft/TypeScript/master/doc/logo.svg"></a> | ![type-npm] | ![type-size] | Loads TypeScript like JavaScript |
176
+ | <a href="https://github.com/webpack-contrib/coffee-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![coffee-npm] | ![coffee-size] | Loads CoffeeScript like JavaScript |
178
177
 
179
178
  [babel-npm]: https://img.shields.io/npm/v/babel-loader.svg
180
179
  [babel-size]: https://packagephobia.com/badge?p=babel-loader
181
- [traceur-npm]: https://img.shields.io/npm/v/traceur-loader.svg
182
- [traceur-size]: https://packagephobia.com/badge?p=traceur-loader
183
180
  [coffee-npm]: https://img.shields.io/npm/v/coffee-loader.svg
184
181
  [coffee-size]: https://packagephobia.com/badge?p=coffee-loader
185
182
  [type-npm]: https://img.shields.io/npm/v/ts-loader.svg
package/bin/webpack.js CHANGED
File without changes
@@ -90,9 +90,9 @@ class MultiItemCache {
90
90
  * @returns {Promise<void>} promise signals when the value is stored
91
91
  */
92
92
  storePromise(data) {
93
- return Promise.all(
94
- this._items.map(item => item.storePromise(data))
95
- ).then(() => {});
93
+ return Promise.all(this._items.map(item => item.storePromise(data))).then(
94
+ () => {}
95
+ );
96
96
  }
97
97
  }
98
98
 
package/lib/Chunk.js CHANGED
@@ -547,9 +547,8 @@ class Chunk {
547
547
  xor.add(chunkGraph.getModuleHash(m, this.runtime));
548
548
  }
549
549
  xor.updateHash(hash);
550
- const entryModules = chunkGraph.getChunkEntryModulesWithChunkGroupIterable(
551
- this
552
- );
550
+ const entryModules =
551
+ chunkGraph.getChunkEntryModulesWithChunkGroupIterable(this);
553
552
  for (const [m, chunkGroup] of entryModules) {
554
553
  hash.update("entry");
555
554
  hash.update(`${chunkGraph.getModuleId(m)}`);
@@ -568,9 +567,15 @@ class Chunk {
568
567
  Array.from(this.groupsIterable, g => new Set(g.chunks))
569
568
  );
570
569
 
571
- for (const chunkGroup of this.groupsIterable) {
570
+ const initialQueue = new Set(this.groupsIterable);
571
+
572
+ for (const chunkGroup of initialQueue) {
572
573
  for (const child of chunkGroup.childrenIterable) {
573
- queue.add(child);
574
+ if (child instanceof Entrypoint) {
575
+ initialQueue.add(child);
576
+ } else {
577
+ queue.add(child);
578
+ }
574
579
  }
575
580
  }
576
581
 
package/lib/ChunkGraph.js CHANGED
@@ -1446,17 +1446,37 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
1446
1446
  runtime
1447
1447
  ).toString(16);
1448
1448
  const connections = this.moduleGraph.getOutgoingConnections(module);
1449
+ /** @type {Set<Module>} */
1450
+ const activeNamespaceModules = new Set();
1449
1451
  /** @type {Map<string, Module | Set<Module>>} */
1450
1452
  const connectedModules = new Map();
1451
- for (const connection of connections) {
1452
- let stateInfo;
1453
- if (typeof runtime === "string") {
1453
+ const processConnection = (connection, stateInfo) => {
1454
+ const module = connection.module;
1455
+ stateInfo += module.getExportsType(this.moduleGraph, strict);
1456
+ // cspell:word Tnamespace
1457
+ if (stateInfo === "Tnamespace") activeNamespaceModules.add(module);
1458
+ else {
1459
+ const oldModule = connectedModules.get(stateInfo);
1460
+ if (oldModule === undefined) {
1461
+ connectedModules.set(stateInfo, module);
1462
+ } else if (oldModule instanceof Set) {
1463
+ oldModule.add(module);
1464
+ } else if (oldModule !== module) {
1465
+ connectedModules.set(stateInfo, new Set([oldModule, module]));
1466
+ }
1467
+ }
1468
+ };
1469
+ if (runtime === undefined || typeof runtime === "string") {
1470
+ for (const connection of connections) {
1454
1471
  const state = connection.getActiveState(runtime);
1455
1472
  if (state === false) continue;
1456
- stateInfo = activeStateToString(state);
1457
- } else {
1473
+ processConnection(connection, state === true ? "T" : "O");
1474
+ }
1475
+ } else {
1476
+ // cspell:word Tnamespace
1477
+ for (const connection of connections) {
1458
1478
  const states = new Set();
1459
- stateInfo = "";
1479
+ let stateInfo = "";
1460
1480
  forEachRuntime(
1461
1481
  runtime,
1462
1482
  runtime => {
@@ -1471,46 +1491,49 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
1471
1491
  if (state === false) continue;
1472
1492
  stateInfo = activeStateToString(state);
1473
1493
  }
1474
- }
1475
- const module = connection.module;
1476
- stateInfo += module.getExportsType(this.moduleGraph, strict);
1477
- const oldModule = connectedModules.get(stateInfo);
1478
- if (oldModule === undefined) {
1479
- connectedModules.set(stateInfo, module);
1480
- } else if (oldModule instanceof Set) {
1481
- oldModule.add(module);
1482
- } else if (oldModule !== module) {
1483
- connectedModules.set(stateInfo, new Set([oldModule, module]));
1494
+ processConnection(connection, stateInfo);
1484
1495
  }
1485
1496
  }
1486
- if (connectedModules.size === 0) return graphHash;
1497
+ // cspell:word Tnamespace
1498
+ if (activeNamespaceModules.size === 0 && connectedModules.size === 0)
1499
+ return graphHash;
1487
1500
  const connectedModulesInOrder =
1488
1501
  connectedModules.size > 1
1489
1502
  ? Array.from(connectedModules).sort(([a], [b]) => (a < b ? -1 : 1))
1490
1503
  : connectedModules;
1491
1504
  const hash = createHash("md4");
1505
+ const addModuleToHash = module => {
1506
+ hash.update(
1507
+ this._getModuleGraphHashBigInt(
1508
+ this._getChunkGraphModule(module),
1509
+ module,
1510
+ runtime
1511
+ ).toString(16)
1512
+ );
1513
+ };
1514
+ const addModulesToHash = modules => {
1515
+ let xor = ZERO_BIG_INT;
1516
+ for (const m of modules) {
1517
+ xor =
1518
+ xor ^
1519
+ this._getModuleGraphHashBigInt(
1520
+ this._getChunkGraphModule(m),
1521
+ m,
1522
+ runtime
1523
+ );
1524
+ }
1525
+ hash.update(xor.toString(16));
1526
+ };
1527
+ if (activeNamespaceModules.size === 1)
1528
+ addModuleToHash(activeNamespaceModules.values().next().value);
1529
+ else if (activeNamespaceModules.size > 1)
1530
+ addModulesToHash(activeNamespaceModules);
1492
1531
  for (const [stateInfo, modules] of connectedModulesInOrder) {
1493
1532
  hash.update(stateInfo);
1494
1533
  if (modules instanceof Set) {
1495
- let xor = ZERO_BIG_INT;
1496
- for (const m of modules) {
1497
- xor =
1498
- xor ^
1499
- this._getModuleGraphHashBigInt(
1500
- this._getChunkGraphModule(m),
1501
- m,
1502
- runtime
1503
- );
1504
- }
1505
- hash.update(xor.toString(16));
1534
+ addModulesToHash(modules);
1506
1535
  } else {
1507
- hash.update(
1508
- this._getModuleGraphHashBigInt(
1509
- this._getChunkGraphModule(modules),
1510
- modules,
1511
- runtime
1512
- ).toString(16)
1513
- );
1536
+ addModuleToHash(modules);
1514
1537
  }
1515
1538
  }
1516
1539
  hash.update(graphHash);
@@ -510,7 +510,8 @@ class Compilation {
510
510
  * @returns {FakeHook<Pick<AsyncSeriesHook<T>, "tap" | "tapAsync" | "tapPromise" | "name">>} fake hook which redirects
511
511
  */
512
512
  const createProcessAssetsHook = (name, stage, getArgs, code) => {
513
- const errorMessage = reason => `Can't automatically convert plugin using Compilation.hooks.${name} to Compilation.hooks.processAssets because ${reason}.
513
+ const errorMessage =
514
+ reason => `Can't automatically convert plugin using Compilation.hooks.${name} to Compilation.hooks.processAssets because ${reason}.
514
515
  BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a single Compilation.hooks.processAssets hook.`;
515
516
  const getOptions = options => {
516
517
  if (typeof options === "string") options = { name: options };
@@ -1375,84 +1376,114 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1375
1376
  * @returns {void}
1376
1377
  */
1377
1378
  _processModuleDependencies(module, callback) {
1378
- const dependencies = new Map();
1379
-
1380
1379
  /**
1381
1380
  * @type {Array<{factory: ModuleFactory, dependencies: Dependency[], originModule: Module|null}>}
1382
1381
  */
1383
1382
  const sortedDependencies = [];
1384
1383
 
1385
- let currentBlock = module;
1384
+ /** @type {DependenciesBlock} */
1385
+ let currentBlock;
1386
1386
 
1387
+ /** @type {Map<ModuleFactory, Map<string, Dependency[]>>} */
1388
+ let dependencies;
1389
+ /** @type {DepConstructor} */
1387
1390
  let factoryCacheKey;
1391
+ /** @type {ModuleFactory} */
1392
+ let factoryCacheKey2;
1393
+ /** @type {Map<string, Dependency[]>} */
1388
1394
  let factoryCacheValue;
1389
- let factoryCacheValue2;
1390
- let listCacheKey;
1395
+ /** @type {string} */
1396
+ let listCacheKey1;
1397
+ /** @type {string} */
1398
+ let listCacheKey2;
1399
+ /** @type {Dependency[]} */
1391
1400
  let listCacheValue;
1392
1401
 
1402
+ /**
1403
+ * @param {Dependency} dep dependency
1404
+ * @returns {void}
1405
+ */
1393
1406
  const processDependency = dep => {
1394
1407
  this.moduleGraph.setParents(dep, currentBlock, module);
1395
1408
  const resourceIdent = dep.getResourceIdentifier();
1396
- if (resourceIdent) {
1397
- // Here webpack is using heuristic that assumes
1398
- // mostly esm dependencies would be used
1399
- // so we don't allocate extra string for them
1409
+ if (resourceIdent !== undefined && resourceIdent !== null) {
1400
1410
  const category = dep.category;
1401
- const cacheKey =
1402
- category === esmDependencyCategory
1403
- ? resourceIdent
1404
- : `${category}${resourceIdent}`;
1405
- const constructor = dep.constructor;
1406
- let innerMap;
1407
- let factory;
1411
+ const constructor = /** @type {DepConstructor} */ (dep.constructor);
1408
1412
  if (factoryCacheKey === constructor) {
1409
- innerMap = factoryCacheValue;
1410
- if (listCacheKey === cacheKey) {
1413
+ // Fast path 1: same constructor as prev item
1414
+ if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
1415
+ // Super fast path 1: also same resource
1411
1416
  listCacheValue.push(dep);
1412
1417
  return;
1413
1418
  }
1414
1419
  } else {
1415
- factory = this.dependencyFactories.get(dep.constructor);
1420
+ const factory = this.dependencyFactories.get(constructor);
1416
1421
  if (factory === undefined) {
1417
1422
  throw new Error(
1418
- `No module factory available for dependency type: ${dep.constructor.name}`
1423
+ `No module factory available for dependency type: ${constructor.name}`
1419
1424
  );
1420
1425
  }
1421
- innerMap = dependencies.get(factory);
1422
- if (innerMap === undefined) {
1423
- dependencies.set(factory, (innerMap = new Map()));
1426
+ if (factoryCacheKey2 === factory) {
1427
+ // Fast path 2: same factory as prev item
1428
+ factoryCacheKey = constructor;
1429
+ if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
1430
+ // Super fast path 2: also same resource
1431
+ listCacheValue.push(dep);
1432
+ return;
1433
+ }
1434
+ } else {
1435
+ // Slow path
1436
+ if (factoryCacheKey2 !== undefined) {
1437
+ // Archive last cache entry
1438
+ if (dependencies === undefined) dependencies = new Map();
1439
+ dependencies.set(factoryCacheKey2, factoryCacheValue);
1440
+ factoryCacheValue = dependencies.get(factory);
1441
+ if (factoryCacheValue === undefined) {
1442
+ factoryCacheValue = new Map();
1443
+ }
1444
+ } else {
1445
+ factoryCacheValue = new Map();
1446
+ }
1447
+ factoryCacheKey = constructor;
1448
+ factoryCacheKey2 = factory;
1424
1449
  }
1425
- factoryCacheKey = constructor;
1426
- factoryCacheValue = innerMap;
1427
- factoryCacheValue2 = factory;
1428
1450
  }
1429
- let list = innerMap.get(cacheKey);
1451
+ // Here webpack is using heuristic that assumes
1452
+ // mostly esm dependencies would be used
1453
+ // so we don't allocate extra string for them
1454
+ const cacheKey =
1455
+ category === esmDependencyCategory
1456
+ ? resourceIdent
1457
+ : `${category}${resourceIdent}`;
1458
+ let list = factoryCacheValue.get(cacheKey);
1430
1459
  if (list === undefined) {
1431
- innerMap.set(cacheKey, (list = []));
1460
+ factoryCacheValue.set(cacheKey, (list = []));
1432
1461
  sortedDependencies.push({
1433
- factory: factoryCacheValue2,
1462
+ factory: factoryCacheKey2,
1434
1463
  dependencies: list,
1435
1464
  originModule: module
1436
1465
  });
1437
1466
  }
1438
1467
  list.push(dep);
1439
- listCacheKey = cacheKey;
1468
+ listCacheKey1 = category;
1469
+ listCacheKey2 = resourceIdent;
1440
1470
  listCacheValue = list;
1441
1471
  }
1442
1472
  };
1443
1473
 
1444
- const processDependenciesBlock = block => {
1445
- if (block.dependencies) {
1446
- currentBlock = block;
1447
- for (const dep of block.dependencies) processDependency(dep);
1448
- }
1449
- if (block.blocks) {
1450
- for (const b of block.blocks) processDependenciesBlock(b);
1451
- }
1452
- };
1453
-
1454
1474
  try {
1455
- processDependenciesBlock(module);
1475
+ /** @type {DependenciesBlock[]} */
1476
+ const queue = [module];
1477
+ do {
1478
+ const block = queue.pop();
1479
+ if (block.dependencies) {
1480
+ currentBlock = block;
1481
+ for (const dep of block.dependencies) processDependency(dep);
1482
+ }
1483
+ if (block.blocks) {
1484
+ for (const b of block.blocks) queue.push(b);
1485
+ }
1486
+ } while (queue.length !== 0);
1456
1487
  } catch (e) {
1457
1488
  return callback(e);
1458
1489
  }
@@ -1585,9 +1616,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1585
1616
  let creatingModuleDuringBuildSet = undefined;
1586
1617
  if (!recursive && this.buildQueue.isProcessing(originModule)) {
1587
1618
  // Track build dependency
1588
- creatingModuleDuringBuildSet = this.creatingModuleDuringBuild.get(
1589
- originModule
1590
- );
1619
+ creatingModuleDuringBuildSet =
1620
+ this.creatingModuleDuringBuild.get(originModule);
1591
1621
  if (creatingModuleDuringBuildSet === undefined) {
1592
1622
  creatingModuleDuringBuildSet = new Set();
1593
1623
  this.creatingModuleDuringBuild.set(
@@ -1716,11 +1746,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1716
1746
  module: result
1717
1747
  };
1718
1748
  }
1719
- const {
1720
- fileDependencies,
1721
- contextDependencies,
1722
- missingDependencies
1723
- } = result;
1749
+ const { fileDependencies, contextDependencies, missingDependencies } =
1750
+ result;
1724
1751
  if (fileDependencies) {
1725
1752
  this.fileDependencies.addAll(fileDependencies);
1726
1753
  }
@@ -2286,7 +2313,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2286
2313
  }
2287
2314
  ] of this.entries) {
2288
2315
  if (dependOn && runtime) {
2289
- const err = new WebpackError(`Entrypoint '${name}' has 'dependOn' and 'runtime' specified. This is not valid.
2316
+ const err =
2317
+ new WebpackError(`Entrypoint '${name}' has 'dependOn' and 'runtime' specified. This is not valid.
2290
2318
  Entrypoints that depend on other entrypoints do not have their own runtime.
2291
2319
  They will use the runtime(s) from referenced entrypoints instead.
2292
2320
  Remove the 'runtime' option from the entrypoint.`);
@@ -2327,11 +2355,12 @@ Remove the 'runtime' option from the entrypoint.`);
2327
2355
  let chunk = this.namedChunks.get(runtime);
2328
2356
  if (chunk) {
2329
2357
  if (!runtimeChunks.has(chunk)) {
2330
- const err = new WebpackError(`Entrypoint '${name}' has a 'runtime' option which points to another entrypoint named '${runtime}'.
2358
+ const err =
2359
+ new WebpackError(`Entrypoint '${name}' has a 'runtime' option which points to another entrypoint named '${runtime}'.
2331
2360
  It's not valid to use other entrypoints as runtime chunk.
2332
2361
  Did you mean to use 'dependOn: ${JSON.stringify(
2333
- runtime
2334
- )}' instead to allow using entrypoint '${name}' within the runtime of entrypoint '${runtime}'? For this '${runtime}' must always be loaded when '${name}' is used.
2362
+ runtime
2363
+ )}' instead to allow using entrypoint '${name}' within the runtime of entrypoint '${runtime}'? For this '${runtime}' must always be loaded when '${name}' is used.
2335
2364
  Or do you want to use the entrypoints '${name}' and '${runtime}' independently on the same page with a shared runtime? In this case give them both the same value for the 'runtime' option. It must be a name not already used by an entrypoint.`);
2336
2365
  const entryChunk = entry.getEntrypointChunk();
2337
2366
  err.chunk = entryChunk;
@@ -2591,12 +2620,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2591
2620
  _runCodeGenerationJobs(jobs, callback) {
2592
2621
  let statModulesFromCache = 0;
2593
2622
  let statModulesGenerated = 0;
2594
- const {
2595
- chunkGraph,
2596
- moduleGraph,
2597
- dependencyTemplates,
2598
- runtimeTemplate
2599
- } = this;
2623
+ const { chunkGraph, moduleGraph, dependencyTemplates, runtimeTemplate } =
2624
+ this;
2600
2625
  const results = this.codeGenerationResults;
2601
2626
  const errors = [];
2602
2627
  asyncLib.eachLimit(
@@ -2743,17 +2768,15 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2743
2768
  chunkGraphEntries = this._getChunkGraphEntries()
2744
2769
  } = {}) {
2745
2770
  const context = { chunkGraph, codeGenerationResults };
2746
- const additionalModuleRuntimeRequirements = this.hooks
2747
- .additionalModuleRuntimeRequirements;
2771
+ const additionalModuleRuntimeRequirements =
2772
+ this.hooks.additionalModuleRuntimeRequirements;
2748
2773
  const runtimeRequirementInModule = this.hooks.runtimeRequirementInModule;
2749
2774
  for (const module of modules) {
2750
2775
  if (chunkGraph.getNumberOfModuleChunks(module) > 0) {
2751
2776
  for (const runtime of chunkGraph.getModuleRuntimes(module)) {
2752
2777
  let set;
2753
- const runtimeRequirements = codeGenerationResults.getRuntimeRequirements(
2754
- module,
2755
- runtime
2756
- );
2778
+ const runtimeRequirements =
2779
+ codeGenerationResults.getRuntimeRequirements(module, runtime);
2757
2780
  if (runtimeRequirements && runtimeRequirements.size > 0) {
2758
2781
  set = new Set(runtimeRequirements);
2759
2782
  } else if (additionalModuleRuntimeRequirements.isUsed()) {
@@ -2793,9 +2816,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2793
2816
  for (const treeEntry of chunkGraphEntries) {
2794
2817
  const set = new Set();
2795
2818
  for (const chunk of treeEntry.getAllReferencedChunks()) {
2796
- const runtimeRequirements = chunkGraph.getChunkRuntimeRequirements(
2797
- chunk
2798
- );
2819
+ const runtimeRequirements =
2820
+ chunkGraph.getChunkRuntimeRequirements(chunk);
2799
2821
  for (const r of runtimeRequirements) set.add(r);
2800
2822
  }
2801
2823
 
@@ -3193,9 +3215,9 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3193
3215
  runtime,
3194
3216
  runtimeTemplate
3195
3217
  });
3196
- const moduleHashDigest = /** @type {string} */ (moduleHash.digest(
3197
- hashDigest
3198
- ));
3218
+ const moduleHashDigest = /** @type {string} */ (
3219
+ moduleHash.digest(hashDigest)
3220
+ );
3199
3221
  chunkGraph.setModuleHashes(
3200
3222
  module,
3201
3223
  runtime,
@@ -3324,10 +3346,11 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3324
3346
  }
3325
3347
  }
3326
3348
  circularRuntimeChunkInfo.sort(compareSelect(i => i.chunk, byId));
3327
- const err = new WebpackError(`Circular dependency between chunks with runtime (${Array.from(
3328
- circularRuntimeChunkInfo,
3329
- c => c.chunk.name || c.chunk.id
3330
- ).join(", ")})
3349
+ const err =
3350
+ new WebpackError(`Circular dependency between chunks with runtime (${Array.from(
3351
+ circularRuntimeChunkInfo,
3352
+ c => c.chunk.name || c.chunk.id
3353
+ ).join(", ")})
3331
3354
  This prevents using hashes of each other and should be avoided.`);
3332
3355
  err.chunk = circularRuntimeChunkInfo[0].chunk;
3333
3356
  this.warnings.push(err);
@@ -3390,15 +3413,14 @@ This prevents using hashes of each other and should be avoided.`);
3390
3413
  moduleGraph: this.moduleGraph,
3391
3414
  runtimeTemplate: this.runtimeTemplate
3392
3415
  });
3393
- const chunkHashDigest = /** @type {string} */ (chunkHash.digest(
3394
- hashDigest
3395
- ));
3416
+ const chunkHashDigest = /** @type {string} */ (
3417
+ chunkHash.digest(hashDigest)
3418
+ );
3396
3419
  hash.update(chunkHashDigest);
3397
3420
  chunk.hash = chunkHashDigest;
3398
3421
  chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
3399
- const fullHashModules = chunkGraph.getChunkFullHashModulesIterable(
3400
- chunk
3401
- );
3422
+ const fullHashModules =
3423
+ chunkGraph.getChunkFullHashModulesIterable(chunk);
3402
3424
  if (fullHashModules) {
3403
3425
  fullHashChunks.add(chunk);
3404
3426
  } else {
@@ -3429,9 +3451,9 @@ This prevents using hashes of each other and should be avoided.`);
3429
3451
  runtime: chunk.runtime,
3430
3452
  runtimeTemplate
3431
3453
  });
3432
- const moduleHashDigest = /** @type {string} */ (moduleHash.digest(
3433
- hashDigest
3434
- ));
3454
+ const moduleHashDigest = /** @type {string} */ (
3455
+ moduleHash.digest(hashDigest)
3456
+ );
3435
3457
  const oldHash = chunkGraph.getModuleHash(module, chunk.runtime);
3436
3458
  chunkGraph.setModuleHashes(
3437
3459
  module,
@@ -3444,9 +3466,9 @@ This prevents using hashes of each other and should be avoided.`);
3444
3466
  const chunkHash = createHash(hashFunction);
3445
3467
  chunkHash.update(chunk.hash);
3446
3468
  chunkHash.update(this.hash);
3447
- const chunkHashDigest = /** @type {string} */ (chunkHash.digest(
3448
- hashDigest
3449
- ));
3469
+ const chunkHashDigest = /** @type {string} */ (
3470
+ chunkHash.digest(hashDigest)
3471
+ );
3450
3472
  chunk.hash = chunkHashDigest;
3451
3473
  chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
3452
3474
  this.hooks.contentHash.call(chunk);
@@ -3963,8 +3985,8 @@ This prevents using hashes of each other and should be avoided.`);
3963
3985
  * from parent (or top level compiler) and creates a child Compilation
3964
3986
  *
3965
3987
  * @param {string} name name of the child compiler
3966
- * @param {OutputOptions} outputOptions // Need to convert config schema to types for this
3967
- * @param {Array<WebpackPluginInstance | WebpackPluginFunction>} plugins webpack plugins that will be applied
3988
+ * @param {OutputOptions=} outputOptions // Need to convert config schema to types for this
3989
+ * @param {Array<WebpackPluginInstance | WebpackPluginFunction>=} plugins webpack plugins that will be applied
3968
3990
  * @returns {Compiler} creates a child Compiler instance
3969
3991
  */
3970
3992
  createChildCompiler(name, outputOptions, plugins) {
@@ -4021,11 +4043,8 @@ This prevents using hashes of each other and should be avoided.`);
4021
4043
  // Create new chunk graph, chunk and entrypoint for the build time execution
4022
4044
  const chunkGraph = new ChunkGraph(this.moduleGraph);
4023
4045
  const runtime = "build time";
4024
- const {
4025
- hashFunction,
4026
- hashDigest,
4027
- hashDigestLength
4028
- } = this.outputOptions;
4046
+ const { hashFunction, hashDigest, hashDigestLength } =
4047
+ this.outputOptions;
4029
4048
  const runtimeTemplate = this.runtimeTemplate;
4030
4049
 
4031
4050
  const chunk = new Chunk("build time chunk");
@@ -4121,9 +4140,8 @@ This prevents using hashes of each other and should be avoided.`);
4121
4140
  });
4122
4141
  this.chunkGraph = old;
4123
4142
 
4124
- const runtimeModules = chunkGraph.getChunkRuntimeModulesIterable(
4125
- chunk
4126
- );
4143
+ const runtimeModules =
4144
+ chunkGraph.getChunkRuntimeModulesIterable(chunk);
4127
4145
 
4128
4146
  // Hash runtime modules
4129
4147
  for (const module of runtimeModules) {
package/lib/Compiler.js CHANGED
@@ -263,6 +263,8 @@ class Compiler {
263
263
  this._assetEmittingSourceCache = new WeakMap();
264
264
  /** @private @type {Map<string, number>} */
265
265
  this._assetEmittingWrittenFiles = new Map();
266
+ /** @private @type {Set<string>} */
267
+ this._assetEmittingPreviousFiles = new Set();
266
268
  }
267
269
 
268
270
  /**
@@ -556,6 +558,8 @@ class Compiler {
556
558
  compilation.assets = { ...compilation.assets };
557
559
  /** @type {Map<string, { path: string, source: Source, size: number, waiting: { cacheEntry: any, file: string }[] }>} */
558
560
  const caseInsensitiveMap = new Map();
561
+ /** @type {Set<string>} */
562
+ const allTargetPaths = new Set();
559
563
  asyncLib.forEachLimit(
560
564
  assets,
561
565
  15,
@@ -583,11 +587,11 @@ class Compiler {
583
587
  outputPath,
584
588
  targetFile
585
589
  );
590
+ allTargetPaths.add(targetPath);
586
591
 
587
592
  // check if the target file has already been written by this Compiler
588
- const targetFileGeneration = this._assetEmittingWrittenFiles.get(
589
- targetPath
590
- );
593
+ const targetFileGeneration =
594
+ this._assetEmittingWrittenFiles.get(targetPath);
591
595
 
592
596
  // create an cache entry for this Source if not already existing
593
597
  let cacheEntry = this._assetEmittingSourceCache.get(source);
@@ -617,7 +621,8 @@ class Compiler {
617
621
  }
618
622
  alreadyWritten();
619
623
  } else {
620
- const err = new WebpackError(`Prevent writing to file that only differs in casing or query string from already written file.
624
+ const err =
625
+ new WebpackError(`Prevent writing to file that only differs in casing or query string from already written file.
621
626
  This will lead to a race-condition and corrupted files on case-insensitive file systems.
622
627
  ${targetPath}
623
628
  ${other}`);
@@ -775,18 +780,22 @@ ${other}`);
775
780
  // check if the Source has been written to this target file
776
781
  const writtenGeneration = cacheEntry.writtenTo.get(targetPath);
777
782
  if (writtenGeneration === targetFileGeneration) {
778
- // if yes, we skip writing the file
779
- // as it's already there
780
- // (we assume one doesn't remove files while the Compiler is running)
783
+ // if yes, we may skip writing the file
784
+ // if it's already there
785
+ // (we assume one doesn't modify files while the Compiler is running, other then removing them)
781
786
 
782
- compilation.updateAsset(file, cacheEntry.sizeOnlySource, {
783
- size: cacheEntry.sizeOnlySource.size()
784
- });
787
+ if (this._assetEmittingPreviousFiles.has(targetPath)) {
788
+ // We assume that assets from the last compilation say intact on disk (they are not removed)
789
+ compilation.updateAsset(file, cacheEntry.sizeOnlySource, {
790
+ size: cacheEntry.sizeOnlySource.size()
791
+ });
785
792
 
786
- return callback();
787
- }
788
-
789
- if (!immutable) {
793
+ return callback();
794
+ } else {
795
+ // Settings immutable will make it accept file content without comparing when file exist
796
+ immutable = true;
797
+ }
798
+ } else if (!immutable) {
790
799
  if (checkSimilarFile()) return;
791
800
  // We wrote to this file before which has very likely a different content
792
801
  // skip comparing and assume content is different for performance
@@ -822,7 +831,12 @@ ${other}`);
822
831
  err => {
823
832
  // Clear map to free up memory
824
833
  caseInsensitiveMap.clear();
825
- if (err) return callback(err);
834
+ if (err) {
835
+ this._assetEmittingPreviousFiles.clear();
836
+ return callback(err);
837
+ }
838
+
839
+ this._assetEmittingPreviousFiles = allTargetPaths;
826
840
 
827
841
  this.hooks.afterEmit.callAsync(compilation, err => {
828
842
  if (err) return callback(err);
@@ -917,8 +931,8 @@ ${other}`);
917
931
  * @param {Compilation} compilation the compilation
918
932
  * @param {string} compilerName the compiler's name
919
933
  * @param {number} compilerIndex the compiler's index
920
- * @param {OutputOptions} outputOptions the output options
921
- * @param {WebpackPluginInstance[]} plugins the plugins to apply
934
+ * @param {OutputOptions=} outputOptions the output options
935
+ * @param {WebpackPluginInstance[]=} plugins the plugins to apply
922
936
  * @returns {Compiler} a child compiler
923
937
  */
924
938
  createChildCompiler(