webpack 5.66.0 → 5.67.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 (72) hide show
  1. package/README.md +1 -1
  2. package/lib/Cache.js +1 -1
  3. package/lib/CacheFacade.js +2 -2
  4. package/lib/CleanPlugin.js +1 -1
  5. package/lib/Compilation.js +12 -9
  6. package/lib/Compiler.js +57 -3
  7. package/lib/ContextModule.js +21 -17
  8. package/lib/DelegatedModule.js +1 -1
  9. package/lib/DependencyTemplates.js +1 -1
  10. package/lib/DllModule.js +1 -1
  11. package/lib/EvalDevToolModulePlugin.js +16 -1
  12. package/lib/EvalSourceMapDevToolPlugin.js +18 -1
  13. package/lib/ExternalModule.js +1 -1
  14. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  15. package/lib/FileSystemInfo.js +29 -25
  16. package/lib/HookWebpackError.js +1 -1
  17. package/lib/Module.js +1 -1
  18. package/lib/MultiCompiler.js +1 -1
  19. package/lib/MultiWatching.js +1 -1
  20. package/lib/NormalModule.js +6 -4
  21. package/lib/RawModule.js +1 -1
  22. package/lib/RuntimeGlobals.js +18 -0
  23. package/lib/RuntimeModule.js +1 -1
  24. package/lib/RuntimePlugin.js +28 -3
  25. package/lib/RuntimeTemplate.js +1 -1
  26. package/lib/Watching.js +1 -1
  27. package/lib/WebpackOptionsApply.js +1 -1
  28. package/lib/asset/AssetGenerator.js +62 -24
  29. package/lib/asset/AssetModulesPlugin.js +3 -0
  30. package/lib/asset/RawDataUrlModule.js +8 -5
  31. package/lib/cache/ResolverCachePlugin.js +1 -1
  32. package/lib/cli.js +44 -3
  33. package/lib/config/defaults.js +22 -5
  34. package/lib/config/normalization.js +5 -0
  35. package/lib/container/ContainerEntryModule.js +4 -2
  36. package/lib/container/FallbackModule.js +4 -4
  37. package/lib/container/RemoteModule.js +4 -2
  38. package/lib/css/CssExportsGenerator.js +139 -0
  39. package/lib/css/CssGenerator.js +3 -0
  40. package/lib/css/CssLoadingRuntimeModule.js +139 -85
  41. package/lib/css/CssModulesPlugin.js +20 -3
  42. package/lib/debug/ProfilingPlugin.js +12 -10
  43. package/lib/dependencies/CreateScriptUrlDependency.js +12 -0
  44. package/lib/dependencies/LoaderPlugin.js +2 -2
  45. package/lib/hmr/LazyCompilationPlugin.js +45 -21
  46. package/lib/hmr/lazyCompilationBackend.js +1 -1
  47. package/lib/ids/DeterministicModuleIdsPlugin.js +55 -35
  48. package/lib/ids/HashedModuleIdsPlugin.js +9 -12
  49. package/lib/ids/IdHelpers.js +24 -10
  50. package/lib/ids/NamedModuleIdsPlugin.js +6 -9
  51. package/lib/ids/NaturalModuleIdsPlugin.js +10 -13
  52. package/lib/ids/OccurrenceModuleIdsPlugin.js +13 -10
  53. package/lib/ids/SyncModuleIdsPlugin.js +140 -0
  54. package/lib/index.js +5 -0
  55. package/lib/optimize/ConcatenatedModule.js +1 -1
  56. package/lib/runtime/CreateScriptRuntimeModule.js +36 -0
  57. package/lib/runtime/CreateScriptUrlRuntimeModule.js +9 -34
  58. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +76 -0
  59. package/lib/schemes/HttpUriPlugin.js +8 -8
  60. package/lib/sharing/ConsumeSharedModule.js +4 -2
  61. package/lib/sharing/ProvideSharedModule.js +4 -2
  62. package/lib/sharing/utils.js +1 -1
  63. package/lib/stats/DefaultStatsFactoryPlugin.js +112 -67
  64. package/lib/stats/DefaultStatsPrinterPlugin.js +88 -23
  65. package/lib/util/AsyncQueue.js +1 -1
  66. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +3 -11
  67. package/package.json +3 -10
  68. package/schemas/WebpackOptions.check.js +1 -1
  69. package/schemas/WebpackOptions.json +43 -6
  70. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  71. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  72. package/types.d.ts +163 -42
@@ -0,0 +1,36 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const RuntimeGlobals = require("../RuntimeGlobals");
8
+ const Template = require("../Template");
9
+ const HelperRuntimeModule = require("./HelperRuntimeModule");
10
+
11
+ class CreateScriptRuntimeModule extends HelperRuntimeModule {
12
+ constructor() {
13
+ super("trusted types script");
14
+ }
15
+
16
+ /**
17
+ * @returns {string} runtime code
18
+ */
19
+ generate() {
20
+ const { compilation } = this;
21
+ const { runtimeTemplate, outputOptions } = compilation;
22
+ const { trustedTypes } = outputOptions;
23
+ const fn = RuntimeGlobals.createScript;
24
+
25
+ return Template.asString(
26
+ `${fn} = ${runtimeTemplate.returningFunction(
27
+ trustedTypes
28
+ ? `${RuntimeGlobals.getTrustedTypesPolicy}().createScript(script)`
29
+ : "script",
30
+ "script"
31
+ )};`
32
+ );
33
+ }
34
+ }
35
+
36
+ module.exports = CreateScriptRuntimeModule;
@@ -10,7 +10,7 @@ const HelperRuntimeModule = require("./HelperRuntimeModule");
10
10
 
11
11
  class CreateScriptUrlRuntimeModule extends HelperRuntimeModule {
12
12
  constructor() {
13
- super("trusted types");
13
+ super("trusted types script url");
14
14
  }
15
15
 
16
16
  /**
@@ -22,39 +22,14 @@ class CreateScriptUrlRuntimeModule extends HelperRuntimeModule {
22
22
  const { trustedTypes } = outputOptions;
23
23
  const fn = RuntimeGlobals.createScriptUrl;
24
24
 
25
- if (!trustedTypes) {
26
- // Skip Trusted Types logic.
27
- return Template.asString([
28
- `${fn} = ${runtimeTemplate.returningFunction("url", "url")};`
29
- ]);
30
- }
31
-
32
- return Template.asString([
33
- "var policy;",
34
- `${fn} = ${runtimeTemplate.basicFunction("url", [
35
- "// Create Trusted Type policy if Trusted Types are available and the policy doesn't exist yet.",
36
- "if (policy === undefined) {",
37
- Template.indent([
38
- "policy = {",
39
- Template.indent([
40
- `createScriptURL: ${runtimeTemplate.returningFunction(
41
- "url",
42
- "url"
43
- )}`
44
- ]),
45
- "};",
46
- 'if (typeof trustedTypes !== "undefined" && trustedTypes.createPolicy) {',
47
- Template.indent([
48
- `policy = trustedTypes.createPolicy(${JSON.stringify(
49
- trustedTypes.policyName
50
- )}, policy);`
51
- ]),
52
- "}"
53
- ]),
54
- "}",
55
- "return policy.createScriptURL(url);"
56
- ])};`
57
- ]);
25
+ return Template.asString(
26
+ `${fn} = ${runtimeTemplate.returningFunction(
27
+ trustedTypes
28
+ ? `${RuntimeGlobals.getTrustedTypesPolicy}().createScriptURL(url)`
29
+ : "url",
30
+ "url"
31
+ )};`
32
+ );
58
33
  }
59
34
  }
60
35
 
@@ -0,0 +1,76 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const RuntimeGlobals = require("../RuntimeGlobals");
8
+ const Template = require("../Template");
9
+ const HelperRuntimeModule = require("./HelperRuntimeModule");
10
+
11
+ class GetTrustedTypesPolicyRuntimeModule extends HelperRuntimeModule {
12
+ /**
13
+ * @param {Set<string>} runtimeRequirements runtime requirements
14
+ */
15
+ constructor(runtimeRequirements) {
16
+ super("trusted types policy");
17
+ this.runtimeRequirements = runtimeRequirements;
18
+ }
19
+
20
+ /**
21
+ * @returns {string} runtime code
22
+ */
23
+ generate() {
24
+ const { compilation } = this;
25
+ const { runtimeTemplate, outputOptions } = compilation;
26
+ const { trustedTypes } = outputOptions;
27
+ const fn = RuntimeGlobals.getTrustedTypesPolicy;
28
+
29
+ return Template.asString([
30
+ "var policy;",
31
+ `${fn} = ${runtimeTemplate.basicFunction("", [
32
+ "// Create Trusted Type policy if Trusted Types are available and the policy doesn't exist yet.",
33
+ "if (policy === undefined) {",
34
+ Template.indent([
35
+ "policy = {",
36
+ Template.indent(
37
+ [
38
+ ...(this.runtimeRequirements.has(RuntimeGlobals.createScript)
39
+ ? [
40
+ `createScript: ${runtimeTemplate.returningFunction(
41
+ "script",
42
+ "script"
43
+ )}`
44
+ ]
45
+ : []),
46
+ ...(this.runtimeRequirements.has(RuntimeGlobals.createScriptUrl)
47
+ ? [
48
+ `createScriptURL: ${runtimeTemplate.returningFunction(
49
+ "url",
50
+ "url"
51
+ )}`
52
+ ]
53
+ : [])
54
+ ].join(",\n")
55
+ ),
56
+ "};",
57
+ ...(trustedTypes
58
+ ? [
59
+ 'if (typeof trustedTypes !== "undefined" && trustedTypes.createPolicy) {',
60
+ Template.indent([
61
+ `policy = trustedTypes.createPolicy(${JSON.stringify(
62
+ trustedTypes.policyName
63
+ )}, policy);`
64
+ ]),
65
+ "}"
66
+ ]
67
+ : [])
68
+ ]),
69
+ "}",
70
+ "return policy;"
71
+ ])};`
72
+ ]);
73
+ }
74
+ }
75
+
76
+ module.exports = GetTrustedTypesPolicyRuntimeModule;
@@ -166,7 +166,7 @@ class Lockfile {
166
166
  /**
167
167
  * @template R
168
168
  * @param {function(function(Error=, R=): void): void} fn function
169
- * @returns {function(function(Error=, R=): void): void} cached function
169
+ * @returns {function(function((Error | null)=, R=): void): void} cached function
170
170
  */
171
171
  const cachedWithoutKey = fn => {
172
172
  let inFlight = false;
@@ -201,10 +201,10 @@ const cachedWithoutKey = fn => {
201
201
  * @template R
202
202
  * @param {function(T, function(Error=, R=): void): void} fn function
203
203
  * @param {function(T, function(Error=, R=): void): void=} forceFn function for the second try
204
- * @returns {(function(T, function(Error=, R=): void): void) & { force: function(T, function(Error=, R=): void): void }} cached function
204
+ * @returns {(function(T, function((Error | null)=, R=): void): void) & { force: function(T, function((Error | null)=, R=): void): void }} cached function
205
205
  */
206
206
  const cachedWithKey = (fn, forceFn = fn) => {
207
- /** @typedef {{ result?: R, error?: Error, callbacks?: (function(Error=, R=): void)[], force?: true }} CacheEntry */
207
+ /** @typedef {{ result?: R, error?: Error, callbacks?: (function((Error | null)=, R=): void)[], force?: true }} CacheEntry */
208
208
  /** @type {Map<T, CacheEntry>} */
209
209
  const cache = new Map();
210
210
  const resultFn = (arg, callback) => {
@@ -358,7 +358,7 @@ class HttpUriPlugin {
358
358
 
359
359
  const getLockfile = cachedWithoutKey(
360
360
  /**
361
- * @param {function(Error=, Lockfile=): void} callback callback
361
+ * @param {function((Error | null)=, Lockfile=): void} callback callback
362
362
  * @returns {void}
363
363
  */
364
364
  callback => {
@@ -465,7 +465,7 @@ class HttpUriPlugin {
465
465
  *
466
466
  * @param {string} url URL
467
467
  * @param {string} integrity integrity
468
- * @param {function(Error=, { entry: LockfileEntry, content: Buffer, storeLock: boolean }=): void} callback callback
468
+ * @param {function((Error | null)=, { entry: LockfileEntry, content: Buffer, storeLock: boolean }=): void} callback callback
469
469
  */
470
470
  const resolveContent = (url, integrity, callback) => {
471
471
  const handleResult = (err, result) => {
@@ -510,7 +510,7 @@ class HttpUriPlugin {
510
510
  /**
511
511
  * @param {string} url URL
512
512
  * @param {FetchResult} cachedResult result from cache
513
- * @param {function(Error=, FetchResult=): void} callback callback
513
+ * @param {function((Error | null)=, FetchResult=): void} callback callback
514
514
  * @returns {void}
515
515
  */
516
516
  const fetchContentRaw = (url, cachedResult, callback) => {
@@ -662,7 +662,7 @@ class HttpUriPlugin {
662
662
  const fetchContent = cachedWithKey(
663
663
  /**
664
664
  * @param {string} url URL
665
- * @param {function(Error=, { validUntil: number, etag?: string, entry: LockfileEntry, content: Buffer, fresh: boolean } | { validUntil: number, etag?: string, location: string, fresh: boolean }=): void} callback callback
665
+ * @param {function((Error | null)=, { validUntil: number, etag?: string, entry: LockfileEntry, content: Buffer, fresh: boolean } | { validUntil: number, etag?: string, location: string, fresh: boolean }=): void} callback callback
666
666
  * @returns {void}
667
667
  */ (url, callback) => {
668
668
  cache.get(url, null, (err, cachedResult) => {
@@ -693,7 +693,7 @@ class HttpUriPlugin {
693
693
  const getInfo = cachedWithKey(
694
694
  /**
695
695
  * @param {string} url the url
696
- * @param {function(Error=, { entry: LockfileEntry, content: Buffer }=): void} callback callback
696
+ * @param {function((Error | null)=, { entry: LockfileEntry, content: Buffer }=): void} callback callback
697
697
  * @returns {void}
698
698
  */
699
699
  (url, callback) => {
@@ -101,14 +101,16 @@ class ConsumeSharedModule extends Module {
101
101
  */
102
102
  libIdent(options) {
103
103
  const { shareKey, shareScope, import: request } = this.options;
104
- return `webpack/sharing/consume/${shareScope}/${shareKey}${
104
+ return `${
105
+ this.layer ? `(${this.layer})/` : ""
106
+ }webpack/sharing/consume/${shareScope}/${shareKey}${
105
107
  request ? `/${request}` : ""
106
108
  }`;
107
109
  }
108
110
 
109
111
  /**
110
112
  * @param {NeedBuildContext} context context info
111
- * @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
113
+ * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
112
114
  * @returns {void}
113
115
  */
114
116
  needBuild(context, callback) {
@@ -67,12 +67,14 @@ class ProvideSharedModule extends Module {
67
67
  * @returns {string | null} an identifier for library inclusion
68
68
  */
69
69
  libIdent(options) {
70
- return `webpack/sharing/provide/${this._shareScope}/${this._name}`;
70
+ return `${this.layer ? `(${this.layer})/` : ""}webpack/sharing/provide/${
71
+ this._shareScope
72
+ }/${this._name}`;
71
73
  }
72
74
 
73
75
  /**
74
76
  * @param {NeedBuildContext} context context info
75
- * @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
77
+ * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
76
78
  * @returns {void}
77
79
  */
78
80
  needBuild(context, callback) {
@@ -22,7 +22,7 @@ exports.isRequiredVersion = str => {
22
22
  * @param {InputFileSystem} fs file system
23
23
  * @param {string} directory directory to start looking into
24
24
  * @param {string[]} descriptionFiles possible description filenames
25
- * @param {function(Error=, {data: object, path: string}=): void} callback callback
25
+ * @param {function((Error | null)=, {data: object, path: string}=): void} callback callback
26
26
  */
27
27
  const getDescriptionFile = (fs, directory, descriptionFiles, callback) => {
28
28
  let i = 0;
@@ -1658,84 +1658,121 @@ const collapse = children => {
1658
1658
  return newChildren;
1659
1659
  };
1660
1660
 
1661
- const spaceLimited = (itemsAndGroups, max) => {
1661
+ const spaceLimited = (
1662
+ itemsAndGroups,
1663
+ max,
1664
+ filteredChildrenLineReserved = false
1665
+ ) => {
1666
+ if (max < 1) {
1667
+ return {
1668
+ children: undefined,
1669
+ filteredChildren: getTotalItems(itemsAndGroups)
1670
+ };
1671
+ }
1662
1672
  /** @type {any[] | undefined} */
1663
1673
  let children = undefined;
1664
1674
  /** @type {number | undefined} */
1665
1675
  let filteredChildren = undefined;
1666
1676
  // This are the groups, which take 1+ lines each
1667
- const groups = itemsAndGroups.filter(c => c.children || c.filteredChildren);
1677
+ const groups = [];
1668
1678
  // The sizes of the groups are stored in groupSizes
1669
- const groupSizes = groups.map(g => getItemSize(g));
1679
+ const groupSizes = [];
1670
1680
  // This are the items, which take 1 line each
1671
- const items = itemsAndGroups.filter(c => !c.children && !c.filteredChildren);
1681
+ const items = [];
1672
1682
  // The total of group sizes
1673
- let groupsSize = groupSizes.reduce((a, b) => a + b, 0);
1683
+ let groupsSize = 0;
1684
+
1685
+ for (const itemOrGroup of itemsAndGroups) {
1686
+ // is item
1687
+ if (!itemOrGroup.children && !itemOrGroup.filteredChildren) {
1688
+ items.push(itemOrGroup);
1689
+ } else {
1690
+ groups.push(itemOrGroup);
1691
+ const size = getItemSize(itemOrGroup);
1692
+ groupSizes.push(size);
1693
+ groupsSize += size;
1694
+ }
1695
+ }
1696
+
1674
1697
  if (groupsSize + items.length <= max) {
1675
1698
  // The total size in the current state fits into the max
1676
1699
  // keep all
1677
- children = groups.concat(items);
1678
- } else if (
1679
- groups.length > 0 &&
1680
- groups.length + Math.min(1, items.length) < max
1681
- ) {
1682
- // If each group would take 1 line the total would be below the maximum
1683
- // collapse some groups, keep items
1684
- while (groupsSize + items.length + (filteredChildren ? 1 : 0) > max) {
1700
+ children = groups.length > 0 ? groups.concat(items) : items;
1701
+ } else if (groups.length === 0) {
1702
+ // slice items to max
1703
+ // inner space marks that lines for filteredChildren already reserved
1704
+ const limit = max - (filteredChildrenLineReserved ? 0 : 1);
1705
+ filteredChildren = items.length - limit;
1706
+ items.length = limit;
1707
+ children = items;
1708
+ } else {
1709
+ // limit is the size when all groups are collapsed
1710
+ const limit =
1711
+ groups.length +
1712
+ (filteredChildrenLineReserved || items.length === 0 ? 0 : 1);
1713
+ if (limit < max) {
1685
1714
  // calculate how much we are over the size limit
1686
1715
  // this allows to approach the limit faster
1687
- // it's always > 1
1688
- const oversize =
1689
- items.length + groupsSize + (filteredChildren ? 1 : 0) - max;
1690
- // Find the maximum group and process only this one
1691
- const maxGroupSize = Math.max(...groupSizes);
1692
- if (maxGroupSize < items.length) {
1693
- filteredChildren = items.length;
1694
- items.length = 0;
1695
- continue;
1696
- }
1697
- for (let i = 0; i < groups.length; i++) {
1698
- if (groupSizes[i] === maxGroupSize) {
1699
- const group = groups[i];
1700
- // run this algorithm recursively and limit the size of the children to
1701
- // current size - oversize / number of groups
1702
- // So it should always end up being smaller
1703
- const headerSize = !group.children
1704
- ? 0
1705
- : group.filteredChildren
1706
- ? 2
1707
- : 1;
1708
- const limited = spaceLimited(
1709
- group.children,
1710
- groupSizes[i] - headerSize - oversize / groups.length
1711
- );
1712
- groups[i] = {
1713
- ...group,
1714
- children: limited.children,
1715
- filteredChildren:
1716
- (group.filteredChildren || 0) + limited.filteredChildren
1717
- };
1718
- const newSize = getItemSize(groups[i]);
1719
- groupsSize -= groupSizes[i] - newSize;
1720
- groupSizes[i] = newSize;
1721
- break;
1716
+ let oversize;
1717
+ // If each group would take 1 line the total would be below the maximum
1718
+ // collapse some groups, keep items
1719
+ while (
1720
+ (oversize =
1721
+ groupsSize +
1722
+ items.length +
1723
+ (filteredChildren && !filteredChildrenLineReserved ? 1 : 0) -
1724
+ max) > 0
1725
+ ) {
1726
+ // Find the maximum group and process only this one
1727
+ const maxGroupSize = Math.max(...groupSizes);
1728
+ if (maxGroupSize < items.length) {
1729
+ filteredChildren = items.length;
1730
+ items.length = 0;
1731
+ continue;
1732
+ }
1733
+ for (let i = 0; i < groups.length; i++) {
1734
+ if (groupSizes[i] === maxGroupSize) {
1735
+ const group = groups[i];
1736
+ // run this algorithm recursively and limit the size of the children to
1737
+ // current size - oversize / number of groups
1738
+ // So it should always end up being smaller
1739
+ const headerSize = group.filteredChildren ? 2 : 1;
1740
+ const limited = spaceLimited(
1741
+ group.children,
1742
+ maxGroupSize -
1743
+ // we should use ceil to always feet in max
1744
+ Math.ceil(oversize / groups.length) -
1745
+ // we substitute size of group head
1746
+ headerSize,
1747
+ headerSize === 2
1748
+ );
1749
+ groups[i] = {
1750
+ ...group,
1751
+ children: limited.children,
1752
+ filteredChildren: limited.filteredChildren
1753
+ ? (group.filteredChildren || 0) + limited.filteredChildren
1754
+ : group.filteredChildren
1755
+ };
1756
+ const newSize = getItemSize(groups[i]);
1757
+ groupsSize -= maxGroupSize - newSize;
1758
+ groupSizes[i] = newSize;
1759
+ break;
1760
+ }
1722
1761
  }
1723
1762
  }
1763
+ children = groups.concat(items);
1764
+ } else if (limit === max) {
1765
+ // If we have only enough space to show one line per group and one line for the filtered items
1766
+ // collapse all groups and items
1767
+ children = collapse(groups);
1768
+ filteredChildren = items.length;
1769
+ } else {
1770
+ // If we have no space
1771
+ // collapse complete group
1772
+ filteredChildren = getTotalItems(itemsAndGroups);
1724
1773
  }
1725
- children = groups.concat(items);
1726
- } else if (
1727
- groups.length > 0 &&
1728
- groups.length + Math.min(1, items.length) <= max
1729
- ) {
1730
- // If we have only enough space to show one line per group and one line for the filtered items
1731
- // collapse all groups and items
1732
- children = groups.length ? collapse(groups) : undefined;
1733
- filteredChildren = items.length;
1734
- } else {
1735
- // If we have no space
1736
- // collapse complete group
1737
- filteredChildren = getTotalItems(itemsAndGroups);
1738
1774
  }
1775
+
1739
1776
  return {
1740
1777
  children,
1741
1778
  filteredChildren
@@ -1777,6 +1814,9 @@ const reasonGroup = (children, reasons) => {
1777
1814
  };
1778
1815
  };
1779
1816
 
1817
+ const GROUP_EXTENSION_REGEXP = /(\.[^.]+?)(?:\?|(?: \+ \d+ modules?)?$)/;
1818
+ const GROUP_PATH_REGEXP = /(.+)[/\\][^/\\]+?(?:\?|(?: \+ \d+ modules?)?$)/;
1819
+
1780
1820
  /** @type {Record<string, (groupConfigs: GroupConfig[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>} */
1781
1821
  const ASSETS_GROUPERS = {
1782
1822
  _: (groupConfigs, context, options) => {
@@ -1825,10 +1865,10 @@ const ASSETS_GROUPERS = {
1825
1865
  groupConfigs.push({
1826
1866
  getKeys: asset => {
1827
1867
  const extensionMatch =
1828
- groupAssetsByExtension && /(\.[^.]+)(?:\?.*|$)/.exec(asset.name);
1868
+ groupAssetsByExtension && GROUP_EXTENSION_REGEXP.exec(asset.name);
1829
1869
  const extension = extensionMatch ? extensionMatch[1] : "";
1830
1870
  const pathMatch =
1831
- groupAssetsByPath && /(.+)[/\\][^/\\]+(?:\?.*|$)/.exec(asset.name);
1871
+ groupAssetsByPath && GROUP_PATH_REGEXP.exec(asset.name);
1832
1872
  const path = pathMatch ? pathMatch[1].split(/[/\\]/) : [];
1833
1873
  const keys = [];
1834
1874
  if (groupAssetsByPath) {
@@ -2022,11 +2062,13 @@ const MODULES_GROUPERS = type => ({
2022
2062
  getKeys: module => {
2023
2063
  if (!module.name) return;
2024
2064
  const resource = parseResource(module.name.split("!").pop()).path;
2065
+ const dataUrl = /^data:[^,;]+/.exec(resource);
2066
+ if (dataUrl) return [dataUrl[0]];
2025
2067
  const extensionMatch =
2026
- groupModulesByExtension && /(\.[^.]+)(?:\?.*|$)/.exec(resource);
2068
+ groupModulesByExtension && GROUP_EXTENSION_REGEXP.exec(resource);
2027
2069
  const extension = extensionMatch ? extensionMatch[1] : "";
2028
2070
  const pathMatch =
2029
- groupModulesByPath && /(.+)[/\\][^/\\]+(?:\?.*|$)/.exec(resource);
2071
+ groupModulesByPath && GROUP_PATH_REGEXP.exec(resource);
2030
2072
  const path = pathMatch ? pathMatch[1].split(/[/\\]/) : [];
2031
2073
  const keys = [];
2032
2074
  if (groupModulesByPath) {
@@ -2046,11 +2088,14 @@ const MODULES_GROUPERS = type => ({
2046
2088
  return keys;
2047
2089
  },
2048
2090
  createGroup: (key, children, modules) => {
2091
+ const isDataUrl = key.startsWith("data:");
2049
2092
  return {
2050
- type: groupModulesByPath
2093
+ type: isDataUrl
2094
+ ? "modules by mime type"
2095
+ : groupModulesByPath
2051
2096
  ? "modules by path"
2052
2097
  : "modules by extension",
2053
- name: key,
2098
+ name: isDataUrl ? key.slice(/* 'data:'.length */ 5) : key,
2054
2099
  children,
2055
2100
  ...moduleGroup(children, modules)
2056
2101
  };