webpack 5.36.0 → 5.36.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.

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);
@@ -1375,84 +1375,114 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1375
1375
  * @returns {void}
1376
1376
  */
1377
1377
  _processModuleDependencies(module, callback) {
1378
- const dependencies = new Map();
1379
-
1380
1378
  /**
1381
1379
  * @type {Array<{factory: ModuleFactory, dependencies: Dependency[], originModule: Module|null}>}
1382
1380
  */
1383
1381
  const sortedDependencies = [];
1384
1382
 
1385
- let currentBlock = module;
1383
+ /** @type {DependenciesBlock} */
1384
+ let currentBlock;
1386
1385
 
1386
+ /** @type {Map<ModuleFactory, Map<string, Dependency[]>>} */
1387
+ let dependencies;
1388
+ /** @type {DepConstructor} */
1387
1389
  let factoryCacheKey;
1390
+ /** @type {ModuleFactory} */
1391
+ let factoryCacheKey2;
1392
+ /** @type {Map<string, Dependency[]>} */
1388
1393
  let factoryCacheValue;
1389
- let factoryCacheValue2;
1390
- let listCacheKey;
1394
+ /** @type {string} */
1395
+ let listCacheKey1;
1396
+ /** @type {string} */
1397
+ let listCacheKey2;
1398
+ /** @type {Dependency[]} */
1391
1399
  let listCacheValue;
1392
1400
 
1401
+ /**
1402
+ * @param {Dependency} dep dependency
1403
+ * @returns {void}
1404
+ */
1393
1405
  const processDependency = dep => {
1394
1406
  this.moduleGraph.setParents(dep, currentBlock, module);
1395
1407
  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
1408
+ if (resourceIdent !== undefined && resourceIdent !== null) {
1400
1409
  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;
1410
+ const constructor = /** @type {DepConstructor} */ (dep.constructor);
1408
1411
  if (factoryCacheKey === constructor) {
1409
- innerMap = factoryCacheValue;
1410
- if (listCacheKey === cacheKey) {
1412
+ // Fast path 1: same constructor as prev item
1413
+ if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
1414
+ // Super fast path 1: also same resource
1411
1415
  listCacheValue.push(dep);
1412
1416
  return;
1413
1417
  }
1414
1418
  } else {
1415
- factory = this.dependencyFactories.get(dep.constructor);
1419
+ const factory = this.dependencyFactories.get(constructor);
1416
1420
  if (factory === undefined) {
1417
1421
  throw new Error(
1418
- `No module factory available for dependency type: ${dep.constructor.name}`
1422
+ `No module factory available for dependency type: ${constructor.name}`
1419
1423
  );
1420
1424
  }
1421
- innerMap = dependencies.get(factory);
1422
- if (innerMap === undefined) {
1423
- dependencies.set(factory, (innerMap = new Map()));
1425
+ if (factoryCacheKey2 === factory) {
1426
+ // Fast path 2: same factory as prev item
1427
+ factoryCacheKey = constructor;
1428
+ if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
1429
+ // Super fast path 2: also same resource
1430
+ listCacheValue.push(dep);
1431
+ return;
1432
+ }
1433
+ } else {
1434
+ // Slow path
1435
+ if (factoryCacheKey2 !== undefined) {
1436
+ // Archive last cache entry
1437
+ if (dependencies === undefined) dependencies = new Map();
1438
+ dependencies.set(factoryCacheKey2, factoryCacheValue);
1439
+ factoryCacheValue = dependencies.get(factory);
1440
+ if (factoryCacheValue === undefined) {
1441
+ factoryCacheValue = new Map();
1442
+ }
1443
+ } else {
1444
+ factoryCacheValue = new Map();
1445
+ }
1446
+ factoryCacheKey = constructor;
1447
+ factoryCacheKey2 = factory;
1424
1448
  }
1425
- factoryCacheKey = constructor;
1426
- factoryCacheValue = innerMap;
1427
- factoryCacheValue2 = factory;
1428
1449
  }
1429
- let list = innerMap.get(cacheKey);
1450
+ // Here webpack is using heuristic that assumes
1451
+ // mostly esm dependencies would be used
1452
+ // so we don't allocate extra string for them
1453
+ const cacheKey =
1454
+ category === esmDependencyCategory
1455
+ ? resourceIdent
1456
+ : `${category}${resourceIdent}`;
1457
+ let list = factoryCacheValue.get(cacheKey);
1430
1458
  if (list === undefined) {
1431
- innerMap.set(cacheKey, (list = []));
1459
+ factoryCacheValue.set(cacheKey, (list = []));
1432
1460
  sortedDependencies.push({
1433
- factory: factoryCacheValue2,
1461
+ factory: factoryCacheKey2,
1434
1462
  dependencies: list,
1435
1463
  originModule: module
1436
1464
  });
1437
1465
  }
1438
1466
  list.push(dep);
1439
- listCacheKey = cacheKey;
1467
+ listCacheKey1 = category;
1468
+ listCacheKey2 = resourceIdent;
1440
1469
  listCacheValue = list;
1441
1470
  }
1442
1471
  };
1443
1472
 
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
1473
  try {
1455
- processDependenciesBlock(module);
1474
+ /** @type {DependenciesBlock[]} */
1475
+ const queue = [module];
1476
+ do {
1477
+ const block = queue.pop();
1478
+ if (block.dependencies) {
1479
+ currentBlock = block;
1480
+ for (const dep of block.dependencies) processDependency(dep);
1481
+ }
1482
+ if (block.blocks) {
1483
+ for (const b of block.blocks) queue.push(b);
1484
+ }
1485
+ } while (queue.length !== 0);
1456
1486
  } catch (e) {
1457
1487
  return callback(e);
1458
1488
  }
@@ -73,13 +73,25 @@ class InitFragment {
73
73
  // Deduplicate fragments. If a fragment has no key, it is always included.
74
74
  const keyedFragments = new Map();
75
75
  for (const [fragment] of sortedFragments) {
76
- if (typeof fragment.merge === "function") {
76
+ if (typeof fragment.mergeAll === "function") {
77
+ if (!fragment.key) {
78
+ throw new Error(
79
+ `InitFragment with mergeAll function must have a valid key: ${fragment.constructor.name}`
80
+ );
81
+ }
82
+ const oldValue = keyedFragments.get(fragment.key);
83
+ if (oldValue === undefined) {
84
+ keyedFragments.set(fragment.key, fragment);
85
+ } else if (Array.isArray(oldValue)) {
86
+ oldValue.push(fragment);
87
+ } else {
88
+ keyedFragments.set(fragment.key, [oldValue, fragment]);
89
+ }
90
+ continue;
91
+ } else if (typeof fragment.merge === "function") {
77
92
  const oldValue = keyedFragments.get(fragment.key);
78
93
  if (oldValue !== undefined) {
79
- keyedFragments.set(
80
- fragment.key || Symbol(),
81
- fragment.merge(oldValue)
82
- );
94
+ keyedFragments.set(fragment.key, fragment.merge(oldValue));
83
95
  continue;
84
96
  }
85
97
  }
@@ -88,7 +100,10 @@ class InitFragment {
88
100
 
89
101
  const concatSource = new ConcatSource();
90
102
  const endContents = [];
91
- for (const fragment of keyedFragments.values()) {
103
+ for (let fragment of keyedFragments.values()) {
104
+ if (Array.isArray(fragment)) {
105
+ fragment = fragment[0].mergeAll(fragment);
106
+ }
92
107
  concatSource.add(fragment.getContent(generateContext));
93
108
  const endContent = fragment.getEndContent(generateContext);
94
109
  if (endContent) {
@@ -25,7 +25,7 @@ const WeakTupleMap = require("./util/WeakTupleMap");
25
25
  * @returns {string}
26
26
  */
27
27
 
28
- const EMPTY_ARRAY = [];
28
+ const EMPTY_SET = new Set();
29
29
 
30
30
  /**
31
31
  * @param {SortableSet<ModuleGraphConnection>} set input
@@ -396,7 +396,7 @@ class ModuleGraph {
396
396
  */
397
397
  getOutgoingConnections(module) {
398
398
  const connections = this._getModuleGraphModule(module).outgoingConnections;
399
- return connections === undefined ? EMPTY_ARRAY : connections;
399
+ return connections === undefined ? EMPTY_SET : connections;
400
400
  }
401
401
 
402
402
  /**
@@ -569,6 +569,7 @@ class WebpackOptionsApply extends OptionsApply {
569
569
  ),
570
570
  snapshot: options.snapshot,
571
571
  maxAge: cacheOptions.maxAge,
572
+ profile: cacheOptions.profile,
572
573
  allowCollectingMemory: cacheOptions.allowCollectingMemory
573
574
  }),
574
575
  cacheOptions.idleTimeout,
@@ -561,7 +561,40 @@ class PackContentItems {
561
561
  this.map = map;
562
562
  }
563
563
 
564
- serialize({ write, snapshot, rollback, logger }) {
564
+ serialize({ write, snapshot, rollback, logger, profile }) {
565
+ if (profile) {
566
+ write(false);
567
+ for (const [key, value] of this.map) {
568
+ const s = snapshot();
569
+ try {
570
+ write(key);
571
+ const start = process.hrtime();
572
+ write(value);
573
+ const durationHr = process.hrtime(start);
574
+ const duration = durationHr[0] * 1000 + durationHr[1] / 1e6;
575
+ if (duration > 1) {
576
+ if (duration > 500)
577
+ logger.error(`Serialization of '${key}': ${duration} ms`);
578
+ else if (duration > 50)
579
+ logger.warn(`Serialization of '${key}': ${duration} ms`);
580
+ else if (duration > 10)
581
+ logger.info(`Serialization of '${key}': ${duration} ms`);
582
+ else if (duration > 5)
583
+ logger.log(`Serialization of '${key}': ${duration} ms`);
584
+ else logger.debug(`Serialization of '${key}': ${duration} ms`);
585
+ }
586
+ } catch (e) {
587
+ rollback(s);
588
+ if (e === NOT_SERIALIZABLE) continue;
589
+ logger.warn(
590
+ `Skipped not serializable cache item '${key}': ${e.message}`
591
+ );
592
+ logger.debug(e.stack);
593
+ }
594
+ }
595
+ write(null);
596
+ return;
597
+ }
565
598
  // Try to serialize all at once
566
599
  const s = snapshot();
567
600
  try {
@@ -590,9 +623,32 @@ class PackContentItems {
590
623
  }
591
624
  }
592
625
 
593
- deserialize({ read }) {
626
+ deserialize({ read, logger, profile }) {
594
627
  if (read()) {
595
628
  this.map = read();
629
+ } else if (profile) {
630
+ const map = new Map();
631
+ let key = read();
632
+ while (key !== null) {
633
+ const start = process.hrtime();
634
+ const value = read();
635
+ const durationHr = process.hrtime(start);
636
+ const duration = durationHr[0] * 1000 + durationHr[1] / 1e6;
637
+ if (duration > 1) {
638
+ if (duration > 100)
639
+ logger.error(`Deserialization of '${key}': ${duration} ms`);
640
+ else if (duration > 20)
641
+ logger.warn(`Deserialization of '${key}': ${duration} ms`);
642
+ else if (duration > 5)
643
+ logger.info(`Deserialization of '${key}': ${duration} ms`);
644
+ else if (duration > 2)
645
+ logger.log(`Deserialization of '${key}': ${duration} ms`);
646
+ else logger.debug(`Deserialization of '${key}': ${duration} ms`);
647
+ }
648
+ map.set(key, value);
649
+ key = read();
650
+ }
651
+ this.map = map;
596
652
  } else {
597
653
  const map = new Map();
598
654
  let key = read();
@@ -787,6 +843,7 @@ class PackFileCacheStrategy {
787
843
  * @param {Logger} options.logger a logger
788
844
  * @param {SnapshotOptions} options.snapshot options regarding snapshotting
789
845
  * @param {number} options.maxAge max age of cache items
846
+ * @param {boolean} options.profile track and log detailed timing information for individual cache items
790
847
  * @param {boolean} options.allowCollectingMemory allow to collect unused memory created during deserialization
791
848
  */
792
849
  constructor({
@@ -798,6 +855,7 @@ class PackFileCacheStrategy {
798
855
  logger,
799
856
  snapshot,
800
857
  maxAge,
858
+ profile,
801
859
  allowCollectingMemory
802
860
  }) {
803
861
  this.fileSerializer = createFileSerializer(fs);
@@ -812,6 +870,7 @@ class PackFileCacheStrategy {
812
870
  this.version = version;
813
871
  this.logger = logger;
814
872
  this.maxAge = maxAge;
873
+ this.profile = profile;
815
874
  this.allowCollectingMemory = allowCollectingMemory;
816
875
  this.snapshot = snapshot;
817
876
  /** @type {Set<string>} */
@@ -840,7 +899,7 @@ class PackFileCacheStrategy {
840
899
  * @returns {Promise<Pack>} the pack
841
900
  */
842
901
  _openPack() {
843
- const { logger, cacheLocation, version } = this;
902
+ const { logger, profile, cacheLocation, version } = this;
844
903
  /** @type {Snapshot} */
845
904
  let buildSnapshot;
846
905
  /** @type {Set<string>} */
@@ -857,6 +916,7 @@ class PackFileCacheStrategy {
857
916
  filename: `${cacheLocation}/index.pack`,
858
917
  extension: ".pack",
859
918
  logger,
919
+ profile,
860
920
  retainedBuffer: this.allowCollectingMemory
861
921
  ? allowCollectingMemory
862
922
  : undefined
@@ -1172,7 +1232,8 @@ class PackFileCacheStrategy {
1172
1232
  .serialize(content, {
1173
1233
  filename: `${this.cacheLocation}/index.pack`,
1174
1234
  extension: ".pack",
1175
- logger: this.logger
1235
+ logger: this.logger,
1236
+ profile: this.profile
1176
1237
  })
1177
1238
  .then(() => {
1178
1239
  for (const dep of newBuildDependencies) {
@@ -293,6 +293,7 @@ const applyCacheDefaults = (cache, { name, mode, development }) => {
293
293
  );
294
294
  D(cache, "hashAlgorithm", "md4");
295
295
  D(cache, "store", "pack");
296
+ D(cache, "profile", false);
296
297
  D(cache, "idleTimeout", 60000);
297
298
  D(cache, "idleTimeoutForInitialStore", 0);
298
299
  D(cache, "maxMemoryGenerations", development ? 5 : Infinity);
@@ -948,7 +949,7 @@ const applyOptimizationDefaults = (
948
949
  A(splitChunks, "defaultSizeTypes", () => ["javascript", "unknown"]);
949
950
  D(splitChunks, "hidePathInfo", production);
950
951
  D(splitChunks, "chunks", "async");
951
- D(splitChunks, "usedExports", true);
952
+ D(splitChunks, "usedExports", optimization.usedExports === true);
952
953
  D(splitChunks, "minChunks", 1);
953
954
  F(splitChunks, "minSize", () => (production ? 20000 : 10000));
954
955
  F(splitChunks, "minRemainingSize", () => (development ? 0 : undefined));
@@ -131,6 +131,7 @@ const getNormalizedWebpackOptions = config => {
131
131
  type: "filesystem",
132
132
  maxMemoryGenerations: cache.maxMemoryGenerations,
133
133
  maxAge: cache.maxAge,
134
+ profile: cache.profile,
134
135
  buildDependencies: cloneObject(cache.buildDependencies),
135
136
  cacheDirectory: cache.cacheDirectory,
136
137
  cacheLocation: cache.cacheLocation,
@@ -48,6 +48,53 @@ class HarmonyExportInitFragment extends InitFragment {
48
48
  this.unusedExports = unusedExports;
49
49
  }
50
50
 
51
+ /**
52
+ * @param {HarmonyExportInitFragment[]} fragments all fragments to merge
53
+ * @returns {HarmonyExportInitFragment} merged fragment
54
+ */
55
+ mergeAll(fragments) {
56
+ let exportMap;
57
+ let exportMapOwned = false;
58
+ let unusedExports;
59
+ let unusedExportsOwned = false;
60
+
61
+ for (const fragment of fragments) {
62
+ if (fragment.exportMap.size !== 0) {
63
+ if (exportMap === undefined) {
64
+ exportMap = fragment.exportMap;
65
+ exportMapOwned = false;
66
+ } else {
67
+ if (!exportMapOwned) {
68
+ exportMap = new Map(exportMap);
69
+ exportMapOwned = true;
70
+ }
71
+ for (const [key, value] of fragment.exportMap) {
72
+ if (!exportMap.has(key)) exportMap.set(key, value);
73
+ }
74
+ }
75
+ }
76
+ if (fragment.unusedExports.size !== 0) {
77
+ if (unusedExports === undefined) {
78
+ unusedExports = fragment.unusedExports;
79
+ unusedExportsOwned = false;
80
+ } else {
81
+ if (!unusedExportsOwned) {
82
+ unusedExports = new Set(unusedExports);
83
+ unusedExportsOwned = true;
84
+ }
85
+ for (const value of fragment.unusedExports) {
86
+ unusedExports.add(value);
87
+ }
88
+ }
89
+ }
90
+ }
91
+ return new HarmonyExportInitFragment(
92
+ this.exportsArgument,
93
+ exportMap,
94
+ unusedExports
95
+ );
96
+ }
97
+
51
98
  merge(other) {
52
99
  let exportMap;
53
100
  if (this.exportMap.size === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpack",
3
- "version": "5.36.0",
3
+ "version": "5.36.1",
4
4
  "author": "Tobias Koppers @sokra",
5
5
  "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
6
6
  "license": "MIT",
@@ -39,7 +39,7 @@
39
39
  "@babel/preset-react": "^7.10.4",
40
40
  "@types/es-module-lexer": "^0.3.0",
41
41
  "@types/jest": "^26.0.15",
42
- "@types/node": "^14.14.10",
42
+ "@types/node": "^15.0.1",
43
43
  "babel-loader": "^8.1.0",
44
44
  "benchmark": "^2.1.4",
45
45
  "bundle-loader": "^0.5.6",
@@ -92,7 +92,7 @@
92
92
  "style-loader": "^2.0.0",
93
93
  "terser": "^5.5.0",
94
94
  "toml": "^3.0.0",
95
- "tooling": "webpack/tooling#v1.17.0",
95
+ "tooling": "webpack/tooling#v1.18.0",
96
96
  "ts-loader": "^8.0.2",
97
97
  "typescript": "^4.2.0-beta",
98
98
  "url-loader": "^4.1.0",