@atlaspack/bundler-default 2.14.5-canary.17 → 2.14.5-canary.170

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.
@@ -42,11 +42,13 @@ function decorateLegacyGraph(idealGraph, bundleGraph) {
42
42
  bundleGroupBundleIds,
43
43
  manualAssetToBundle
44
44
  } = idealGraph;
45
+ // This line can be deleted once supportWebpackChunkName feature flag is removed.
45
46
  let entryBundleToBundleGroup = new Map();
46
47
  // Step Create Bundles: Create bundle groups, bundles, and shared bundles and add assets to them
47
48
  for (let [bundleNodeId, idealBundle] of idealBundleGraph.nodes.entries()) {
48
49
  if (!idealBundle || idealBundle === 'root') continue;
49
50
  let entryAsset = idealBundle.mainEntryAsset;
51
+ // This line can be deleted once supportWebpackChunkName feature flag is removed.
50
52
  let bundleGroup;
51
53
  let bundle;
52
54
  if (bundleGroupBundleIds.has(bundleNodeId)) {
@@ -57,19 +59,33 @@ function decorateLegacyGraph(idealGraph, bundleGraph) {
57
59
  return dependency.value;
58
60
  });
59
61
  (0, _assert().default)(entryAsset != null, 'Processing a bundleGroup with no entry asset');
62
+ let bundleGroups = new Map();
60
63
  for (let dependency of dependencies) {
61
64
  bundleGroup = bundleGraph.createBundleGroup(dependency, idealBundle.target);
65
+ bundleGroups.set(bundleGroup.entryAssetId, bundleGroup);
66
+ }
67
+ if ((0, _featureFlags().getFeatureFlag)('supportWebpackChunkName')) {
68
+ (0, _assert().default)(bundleGroups.size > 0, 'No bundle groups created');
69
+ } else {
70
+ (0, _assert().default)(bundleGroup);
71
+ entryBundleToBundleGroup.set(bundleNodeId, bundleGroup);
62
72
  }
63
- (0, _assert().default)(bundleGroup);
64
- entryBundleToBundleGroup.set(bundleNodeId, bundleGroup);
65
73
  bundle = (0, _nullthrows().default)(bundleGraph.createBundle({
66
74
  entryAsset: (0, _nullthrows().default)(entryAsset),
75
+ bundleRoots: Array.from(idealBundle.bundleRoots),
67
76
  needsStableName: idealBundle.needsStableName,
68
77
  bundleBehavior: idealBundle.bundleBehavior,
69
78
  target: idealBundle.target,
70
79
  manualSharedBundle: idealBundle.manualSharedBundle
71
80
  }));
72
- bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
81
+ if ((0, _featureFlags().getFeatureFlag)('supportWebpackChunkName')) {
82
+ for (let bundleGroup of bundleGroups.values()) {
83
+ bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
84
+ }
85
+ } else {
86
+ (0, _assert().default)(bundleGroup);
87
+ bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
88
+ }
73
89
  } else if (idealBundle.sourceBundles.size > 0 && !idealBundle.mainEntryAsset) {
74
90
  let uniqueKey = idealBundle.uniqueKey != null ? idealBundle.uniqueKey : [...idealBundle.assets].map(asset => asset.id).join(',');
75
91
  bundle = (0, _nullthrows().default)(bundleGraph.createBundle({
@@ -95,6 +111,7 @@ function decorateLegacyGraph(idealGraph, bundleGraph) {
95
111
  (0, _assert().default)(entryAsset != null);
96
112
  bundle = (0, _nullthrows().default)(bundleGraph.createBundle({
97
113
  entryAsset,
114
+ bundleRoots: Array.from(idealBundle.bundleRoots),
98
115
  needsStableName: idealBundle.needsStableName,
99
116
  bundleBehavior: idealBundle.bundleBehavior,
100
117
  target: idealBundle.target,
@@ -162,6 +179,8 @@ function decorateLegacyGraph(idealGraph, bundleGraph) {
162
179
  bundleGraph.createAssetReference(dependency, asset, legacyBundle);
163
180
  }
164
181
  }
182
+
183
+ // @ts-expect-error TS2488
165
184
  for (let {
166
185
  type,
167
186
  from,
@@ -171,12 +190,14 @@ function decorateLegacyGraph(idealGraph, bundleGraph) {
171
190
  if (sourceBundle === 'root') {
172
191
  continue;
173
192
  }
193
+ // @ts-expect-error TS2367
174
194
  (0, _assert().default)(sourceBundle !== 'root');
175
195
  let legacySourceBundle = (0, _nullthrows().default)(idealBundleToLegacyBundle.get(sourceBundle));
176
196
  let targetBundle = (0, _nullthrows().default)(idealBundleGraph.getNode(to));
177
197
  if (targetBundle === 'root') {
178
198
  continue;
179
199
  }
200
+ // @ts-expect-error TS2367
180
201
  (0, _assert().default)(targetBundle !== 'root');
181
202
  let legacyTargetBundle = (0, _nullthrows().default)(idealBundleToLegacyBundle.get(targetBundle));
182
203
  if ((0, _featureFlags().getFeatureFlag)('conditionalBundlingApi') && type === _idealGraph.idealBundleGraphEdges.conditional) {
package/lib/idealGraph.js CHANGED
@@ -50,6 +50,7 @@ function _nullthrows() {
50
50
  var _bundleMerge = require("./bundleMerge");
51
51
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
52
52
  /* BundleRoot - An asset that is the main entry of a Bundle. */
53
+
53
54
  const dependencyPriorityEdges = {
54
55
  sync: 1,
55
56
  parallel: 2,
@@ -65,7 +66,13 @@ const idealBundleGraphEdges = exports.idealBundleGraphEdges = Object.freeze({
65
66
  // which mutates the assetGraph into the bundleGraph we would
66
67
  // expect from default bundler
67
68
 
69
+ function isNonRootBundle(bundle, message) {
70
+ let existingBundle = (0, _nullthrows().default)(bundle, message);
71
+ (0, _assert().default)(existingBundle !== 'root', "Bundle cannot be 'root'");
72
+ return existingBundle;
73
+ }
68
74
  function createIdealGraph(assetGraph, config, entries, logger) {
75
+ var _config$sharedBundleM;
69
76
  // Asset to the bundle and group it's an entry of
70
77
  let bundleRoots = new Map();
71
78
  let bundles = new Map();
@@ -108,15 +115,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
108
115
  }
109
116
  let assets = [];
110
117
  let assetToIndex = new Map();
111
- //Manual is a map of the user-given name to the bundle node Id that corresponds to ALL the assets that match any glob in that user-specified array
112
- let manualSharedMap = new Map();
113
- // May need a map to be able to look up NON- bundle root assets which need special case instructions
114
- // Use this when placing assets into bundles, to avoid duplication
115
- let manualAssetToBundle = new Map();
116
- let {
117
- manualAssetToConfig,
118
- constantModuleToMSB
119
- } = function makeManualAssetToConfigLookup() {
118
+ function makeManualAssetToConfigLookup() {
120
119
  let manualAssetToConfig = new Map();
121
120
  let constantModuleToMSB = new (_utils().DefaultMap)(() => []);
122
121
  if (config.manualSharedBundles.length === 0) {
@@ -128,6 +127,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
128
127
  let parentsToConfig = new (_utils().DefaultMap)(() => []);
129
128
  for (let c of config.manualSharedBundles) {
130
129
  if (c.root != null) {
130
+ // @ts-expect-error TS2345
131
131
  parentsToConfig.get(_path().default.join(config.projectRoot, c.root)).push(c);
132
132
  }
133
133
  }
@@ -160,17 +160,16 @@ function createIdealGraph(assetGraph, config, entries, logger) {
160
160
  assetGraph.traverse((node, _, actions) => {
161
161
  if (node.type === 'asset' && (!Array.isArray(c.types) || c.types.includes(node.value.type))) {
162
162
  let projectRelativePath = _path().default.relative(config.projectRoot, node.value.filePath);
163
- if (!assetRegexes.some(regex => regex.test(projectRelativePath))) {
164
- return;
165
- }
166
163
 
167
164
  // We track all matching MSB's for constant modules as they are never duplicated
168
165
  // and need to be assigned to all matching bundles
169
166
  if (node.value.meta.isConstantModule === true) {
167
+ // @ts-expect-error TS2345
170
168
  constantModuleToMSB.get(node.value).push(c);
171
169
  }
172
- manualAssetToConfig.set(node.value, c);
173
- return;
170
+ if (assetRegexes.some(regex => regex.test(projectRelativePath))) {
171
+ manualAssetToConfig.set(node.value, c);
172
+ }
174
173
  }
175
174
  if (node.type === 'dependency' && (node.value.priority === 'lazy' || (0, _featureFlags().getFeatureFlag)('conditionalBundlingApi') && node.value.priority === 'conditional') && parentAsset) {
176
175
  // Don't walk past the bundle group assets
@@ -182,8 +181,23 @@ function createIdealGraph(assetGraph, config, entries, logger) {
182
181
  manualAssetToConfig,
183
182
  constantModuleToMSB
184
183
  };
185
- }();
184
+ }
185
+
186
+ //Manual is a map of the user-given name to the bundle node Id that corresponds to ALL the assets that match any glob in that user-specified array
187
+ let manualSharedMap = new Map();
188
+ // May need a map to be able to look up NON- bundle root assets which need special case instructions
189
+ // Use this when placing assets into bundles, to avoid duplication
190
+ let manualAssetToBundle = new Map();
191
+ let {
192
+ manualAssetToConfig,
193
+ constantModuleToMSB
194
+ } = makeManualAssetToConfigLookup();
186
195
  let manualBundleToInternalizedAsset = new (_utils().DefaultMap)(() => []);
196
+ let mergeSourceBundleLookup = new Map();
197
+ let mergeSourceBundleAssets = new Set((_config$sharedBundleM = config.sharedBundleMerge) === null || _config$sharedBundleM === void 0 ? void 0 : _config$sharedBundleM.flatMap(c => {
198
+ var _c$sourceBundles;
199
+ return ((_c$sourceBundles = c.sourceBundles) === null || _c$sourceBundles === void 0 ? void 0 : _c$sourceBundles.map(assetMatch => _path().default.join(config.projectRoot, assetMatch))) ?? [];
200
+ }));
187
201
 
188
202
  /**
189
203
  * Step Create Bundles: Traverse the assetGraph (aka MutableBundleGraph) and create bundles
@@ -191,7 +205,9 @@ function createIdealGraph(assetGraph, config, entries, logger) {
191
205
  * adding only that asset to each bundle, not its entire subgraph.
192
206
  */
193
207
  assetGraph.traverse({
194
- enter(node, context, actions) {
208
+ enter(node, context,
209
+ // @ts-expect-error TS2304
210
+ actions) {
195
211
  if (node.type === 'asset') {
196
212
  if ((context === null || context === void 0 ? void 0 : context.type) === 'dependency' && context !== null && context !== void 0 && context.value.isEntry && !entries.has(node.value)) {
197
213
  // Skip whole subtrees of other targets by skipping those entries
@@ -234,15 +250,16 @@ function createIdealGraph(assetGraph, config, entries, logger) {
234
250
  manualSharedBundleKey != null && manualSharedMap.has(manualSharedBundleKey)) {
235
251
  bundleId = (0, _nullthrows().default)(manualSharedMap.get(manualSharedBundleKey));
236
252
  }
237
- if (dependency.priority === 'lazy' || (0, _featureFlags().getFeatureFlag)('conditionalBundlingApi') && node.value.priority === 'conditional' || childAsset.bundleBehavior === 'isolated' // An isolated Dependency, or Bundle must contain all assets it needs to load.
238
- ) {
253
+ if (dependency.priority === 'lazy' || (0, _featureFlags().getFeatureFlag)('conditionalBundlingApi') && node.value.priority === 'conditional' || childAsset.bundleBehavior === 'isolated' ||
254
+ // An isolated Dependency, or Bundle must contain all assets it needs to load.
255
+ childAsset.bundleBehavior === 'inlineIsolated') {
239
256
  if (bundleId == null) {
240
257
  let firstBundleGroup = (0, _nullthrows().default)(bundleGraph.getNode(stack[0][1]));
241
258
  (0, _assert().default)(firstBundleGroup !== 'root');
242
259
  bundle = createBundle({
243
260
  asset: childAsset,
244
261
  bundleBehavior: dependency.bundleBehavior ?? childAsset.bundleBehavior,
245
- needsStableName: dependency.bundleBehavior === 'inline' || childAsset.bundleBehavior === 'inline' ? false : dependency.isEntry || dependency.needsStableName,
262
+ needsStableName: dependency.bundleBehavior === 'inline' || childAsset.bundleBehavior === 'inline' || dependency.bundleBehavior === 'inlineIsolated' || childAsset.bundleBehavior === 'inlineIsolated' ? false : dependency.isEntry || dependency.needsStableName,
246
263
  target: firstBundleGroup.target
247
264
  });
248
265
  bundleId = bundleGraph.addNode(bundle);
@@ -250,6 +267,11 @@ function createIdealGraph(assetGraph, config, entries, logger) {
250
267
  bundleRoots.set(childAsset, [bundleId, bundleId]);
251
268
  bundleGroupBundleIds.add(bundleId);
252
269
  bundleGraph.addEdge(bundleGraphRootNodeId, bundleId);
270
+ // If this asset is relevant for merging then track it's source
271
+ // bundle id for later
272
+ if (mergeSourceBundleAssets.has(childAsset.filePath)) {
273
+ mergeSourceBundleLookup.set(_path().default.relative(config.projectRoot, childAsset.filePath), bundleId);
274
+ }
253
275
  if (manualSharedObject) {
254
276
  // MSB Step 4: If this was the first instance of a match, mark mainAsset for internalization
255
277
  // since MSBs should not have main entry assets
@@ -261,7 +283,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
261
283
  if (
262
284
  // If this dependency requests isolated, but the bundle is not,
263
285
  // make the bundle isolated for all uses.
264
- dependency.bundleBehavior === 'isolated' && bundle.bundleBehavior == null) {
286
+ (dependency.bundleBehavior === 'isolated' || dependency.bundleBehavior === 'inlineIsolated') && bundle.bundleBehavior == null) {
265
287
  bundle.bundleBehavior = dependency.bundleBehavior;
266
288
  }
267
289
  }
@@ -271,7 +293,9 @@ function createIdealGraph(assetGraph, config, entries, logger) {
271
293
  }), dependencyBundleGraph.addNodeByContentKeyIfNeeded(String(bundleId), {
272
294
  value: bundle,
273
295
  type: 'bundle'
274
- }), dependencyPriorityEdges[dependency.priority]);
296
+ }),
297
+ // @ts-expect-error TS7053
298
+ dependencyPriorityEdges[dependency.priority]);
275
299
  if ((0, _featureFlags().getFeatureFlag)('conditionalBundlingApi') && dependency.priority === 'conditional') {
276
300
  let [referencingBundleRoot, bundleGroupNodeId] = (0, _nullthrows().default)(stack[stack.length - 1]);
277
301
  let referencingBundleId = (0, _nullthrows().default)(bundleRoots.get(referencingBundleRoot))[0];
@@ -300,7 +324,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
300
324
  env: childAsset.env,
301
325
  bundleBehavior: dependency.bundleBehavior ?? childAsset.bundleBehavior,
302
326
  target: referencingBundle.target,
303
- needsStableName: childAsset.bundleBehavior === 'inline' || dependency.bundleBehavior === 'inline' || dependency.priority === 'parallel' && !dependency.needsStableName ? false : referencingBundle.needsStableName
327
+ needsStableName: childAsset.bundleBehavior === 'inline' || dependency.bundleBehavior === 'inline' || dependency.bundleBehavior === 'inlineIsolated' || dependency.priority === 'parallel' && !dependency.needsStableName ? false : referencingBundle.needsStableName
304
328
  });
305
329
  bundleId = bundleGraph.addNode(bundle);
306
330
  } else {
@@ -309,7 +333,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
309
333
  if (
310
334
  // If this dependency requests isolated, but the bundle is not,
311
335
  // make the bundle isolated for all uses.
312
- dependency.bundleBehavior === 'isolated' && bundle.bundleBehavior == null) {
336
+ (dependency.bundleBehavior === 'isolated' || dependency.bundleBehavior === 'inlineIsolated') && bundle.bundleBehavior == null) {
313
337
  bundle.bundleBehavior = dependency.bundleBehavior;
314
338
  }
315
339
  }
@@ -331,13 +355,16 @@ function createIdealGraph(assetGraph, config, entries, logger) {
331
355
  }
332
356
  assetReference.get(childAsset).push([dependency, bundle]);
333
357
  } else {
358
+ // @ts-expect-error TS2322
334
359
  bundleId = null;
335
360
  }
336
361
  if (manualSharedObject && bundleId != null) {
337
362
  // MSB Step 5: At this point we've either created or found an existing MSB bundle
338
363
  // add the asset if it doesn't already have it and set key
339
364
 
340
- (0, _assert().default)(bundle !== 'root' && bundle != null && bundleId != null);
365
+ (0, _assert().default)(
366
+ // @ts-expect-error TS2367
367
+ bundle !== 'root' && bundle != null && bundleId != null);
341
368
  manualAssetToBundle.set(childAsset, bundleId);
342
369
  if (!bundle.assets.has(childAsset)) {
343
370
  // Add asset to bundle
@@ -358,6 +385,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
358
385
  }
359
386
  return node;
360
387
  },
388
+ // @ts-expect-error TS2322
361
389
  exit(node) {
362
390
  var _stack;
363
391
  if (((_stack = stack[stack.length - 1]) === null || _stack === void 0 ? void 0 : _stack[0]) === node.value) {
@@ -495,7 +523,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
495
523
  // not true that a bundle's available assets = all assets of all the bundleGroups
496
524
  // it belongs to. It's the intersection of those sets.
497
525
  let available;
498
- if (bundleRoot.bundleBehavior === 'isolated') {
526
+ if (bundleRoot.bundleBehavior === 'isolated' || bundleRoot.bundleBehavior === 'inlineIsolated') {
499
527
  available = new (_graph().BitSet)(assets.length);
500
528
  } else {
501
529
  available = (0, _nullthrows().default)(ancestorAssets[nodeId]).clone();
@@ -558,7 +586,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
558
586
  continue;
559
587
  }
560
588
  let parentRoots = bundleRootGraph.getNodeIdsConnectedTo(id, _graph().ALL_EDGE_TYPES);
561
- let canDelete = getBundleFromBundleRoot(bundleRoot).bundleBehavior !== 'isolated';
589
+ let canDelete = getBundleFromBundleRoot(bundleRoot).bundleBehavior !== 'isolated' && getBundleFromBundleRoot(bundleRoot).bundleBehavior !== 'inlineIsolated';
562
590
  if (parentRoots.length === 0) continue;
563
591
  for (let parentId of parentRoots) {
564
592
  var _ancestorAssets$paren;
@@ -586,8 +614,11 @@ function createIdealGraph(assetGraph, config, entries, logger) {
586
614
  }
587
615
  function assignInlineConstants(parentAsset, bundle) {
588
616
  for (let inlineConstant of inlineConstantDeps.get(parentAsset)) {
617
+ // @ts-expect-error TS2345
589
618
  if (!bundle.assets.has(inlineConstant)) {
619
+ // @ts-expect-error TS2345
590
620
  bundle.assets.add(inlineConstant);
621
+ // @ts-expect-error TS18046
591
622
  bundle.size += inlineConstant.stats.size;
592
623
  }
593
624
  }
@@ -623,7 +654,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
623
654
  let assetId = bundleRootGraph.getNode(nodeId);
624
655
  if (assetId == null) return; // deleted
625
656
  let a = assets[assetId];
626
- if (entries.has(a) || !a.isBundleSplittable || bundleRoots.get(a) && (getBundleFromBundleRoot(a).needsStableName || getBundleFromBundleRoot(a).bundleBehavior === 'isolated')) {
657
+ if (entries.has(a) || !a.isBundleSplittable || bundleRoots.get(a) && (getBundleFromBundleRoot(a).needsStableName || getBundleFromBundleRoot(a).bundleBehavior === 'isolated' || getBundleFromBundleRoot(a).bundleBehavior === 'inlineIsolated')) {
627
658
  // Add asset to non-splittable bundles.
628
659
  addAssetToBundleRoot(asset, a);
629
660
  } else if (!((_ancestorAssets$nodeI = ancestorAssets[nodeId]) !== null && _ancestorAssets$nodeI !== void 0 && _ancestorAssets$nodeI.has(i))) {
@@ -785,6 +816,8 @@ function createIdealGraph(assetGraph, config, entries, logger) {
785
816
  }
786
817
  }
787
818
  let manualSharedBundleIds = new Set([...manualSharedMap.values()]);
819
+ let modifiedSourceBundles = new Set();
820
+
788
821
  // Step split manual shared bundles for those that have the "split" property set
789
822
  let remainderMap = new (_utils().DefaultMap)(() => []);
790
823
  for (let id of manualSharedMap.values()) {
@@ -801,8 +834,9 @@ function createIdealGraph(assetGraph, config, entries, logger) {
801
834
  if (modNum != null) {
802
835
  for (let a of [...manualBundle.assets]) {
803
836
  let numRep = getBigIntFromContentKey(a.id);
804
- // $FlowFixMe Flow doesn't know about BigInt
805
837
  let r = Number(numRep % BigInt(modNum));
838
+
839
+ // @ts-expect-error TS2345
806
840
  remainderMap.get(r).push(a);
807
841
  }
808
842
  for (let i = 1; i < [...remainderMap.keys()].length; i++) {
@@ -824,8 +858,10 @@ function createIdealGraph(assetGraph, config, entries, logger) {
824
858
  }
825
859
  for (let sp of remainderMap.get(i)) {
826
860
  bundle.assets.add(sp);
861
+ // @ts-expect-error TS2339
827
862
  bundle.size += sp.stats.size;
828
863
  manualBundle.assets.delete(sp);
864
+ // @ts-expect-error TS2339
829
865
  manualBundle.size -= sp.stats.size;
830
866
  }
831
867
  }
@@ -838,21 +874,77 @@ function createIdealGraph(assetGraph, config, entries, logger) {
838
874
  // match multiple MSB's
839
875
  for (let [asset, msbs] of constantModuleToMSB.entries()) {
840
876
  for (let manualSharedObject of msbs) {
877
+ // @ts-expect-error TS2339
841
878
  let bundleId = manualSharedMap.get(manualSharedObject.name + ',js');
842
879
  if (bundleId == null) continue;
843
880
  let bundle = (0, _nullthrows().default)(bundleGraph.getNode(bundleId));
844
881
  (0, _assert().default)(bundle != null && bundle !== 'root', 'We tried to use the root incorrectly');
882
+
883
+ // @ts-expect-error TS2345
845
884
  if (!bundle.assets.has(asset)) {
885
+ // @ts-expect-error TS2345
846
886
  bundle.assets.add(asset);
887
+ // @ts-expect-error TS18046
847
888
  bundle.size += asset.stats.size;
848
889
  }
849
890
  }
850
891
  }
892
+ if ((0, _featureFlags().getFeatureFlag)('supportWebpackChunkName')) {
893
+ // Merge webpack chunk name bundles
894
+ let chunkNameBundles = new (_utils().DefaultMap)(() => new Set());
895
+ for (let [nodeId, node] of dependencyBundleGraph.nodes.entries()) {
896
+ var _bundleNode$value$mai;
897
+ // meta.chunkName is set by the Rust transformer, so we just need to find
898
+ // bundles that have a chunkName set.
899
+ if (!node || node.type !== 'dependency' || node.value.meta.chunkName == null) {
900
+ continue;
901
+ }
902
+ let connectedBundles = dependencyBundleGraph.getNodeIdsConnectedFrom(nodeId, dependencyPriorityEdges[node.value.priority]);
903
+ if (connectedBundles.length === 0) {
904
+ continue;
905
+ }
906
+ (0, _assert().default)(connectedBundles.length === 1, 'Expected webpackChunkName dependency to be connected to no more than one bundle');
907
+ let bundleId = connectedBundles[0];
908
+ let bundleNode = dependencyBundleGraph.getNode(bundleId);
909
+ (0, _assert().default)(bundleNode != null && bundleNode.type === 'bundle');
910
+
911
+ // If a bundle does not have a main entry asset, it's somehow just a
912
+ // shared bundle, and will be merged/deleted by other means.
913
+ if (bundleNode.value.mainEntryAsset == null) {
914
+ continue;
915
+ }
916
+ let bundleNodeId = null;
917
+ let mainEntryAssetId = (_bundleNode$value$mai = bundleNode.value.mainEntryAsset) === null || _bundleNode$value$mai === void 0 ? void 0 : _bundleNode$value$mai.id;
918
+ if (mainEntryAssetId != null) {
919
+ bundleNodeId = bundles.get(mainEntryAssetId);
920
+ }
921
+ if (bundleNodeId == null) {
922
+ continue;
923
+ }
924
+ chunkNameBundles.get(node.value.meta.chunkName)
925
+ // DependencyBundleGraph uses content keys as node ids, so we can use that
926
+ // to get the bundle id.
927
+ .add(bundleNodeId);
928
+ }
929
+ for (let [chunkName, bundleIds] of chunkNameBundles.entries()) {
930
+ // The `[request]` placeholder is not yet supported
931
+ if (bundleIds.size <= 1 || typeof chunkName === 'string' && chunkName.includes('[request]')) {
932
+ continue; // Nothing to merge
933
+ }
934
+
935
+ // Merge all bundles with the same chunk name into the first one.
936
+ let [firstBundleId, ...rest] = Array.from(bundleIds);
937
+ for (let bundleId of rest) {
938
+ // @ts-expect-error TS2345
939
+ mergeBundles(firstBundleId, bundleId);
940
+ }
941
+ }
942
+ }
851
943
 
852
944
  // Step merge shared bundles that meet the overlap threshold
853
945
  // This step is skipped by default as the threshold defaults to 1
854
- if (config.sharedBundleMergeThreshold < 1) {
855
- mergeOverlapBundles();
946
+ if (config.sharedBundleMerge && config.sharedBundleMerge.length > 0) {
947
+ mergeOverlapBundles(config.sharedBundleMerge);
856
948
  }
857
949
 
858
950
  // Step Merge Share Bundles: Merge any shared bundles under the minimum bundle size back into
@@ -866,7 +958,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
866
958
  }
867
959
 
868
960
  // Step Remove Shared Bundles: Remove shared bundles from bundle groups that hit the parallel request limit.
869
- let modifiedSourceBundles = new Set();
961
+
870
962
  if (config.disableSharedBundles === false) {
871
963
  for (let bundleGroupId of bundleGraph.getNodeIdsConnectedFrom(rootNodeId)) {
872
964
  // Find shared bundles in this bundle group.
@@ -879,7 +971,7 @@ function createIdealGraph(assetGraph, config, entries, logger) {
879
971
  let numBundlesContributingToPRL = bundleIdsInGroup.reduce((count, b) => {
880
972
  let bundle = (0, _nullthrows().default)(bundleGraph.getNode(b));
881
973
  (0, _assert().default)(bundle !== 'root');
882
- return count + (bundle.bundleBehavior !== 'inline');
974
+ return count + Number(bundle.bundleBehavior !== 'inline' && bundle.bundleBehavior !== 'inlineIsolated');
883
975
  }, 0);
884
976
  if (numBundlesContributingToPRL > config.maxParallelRequests) {
885
977
  let sharedBundleIdsInBundleGroup = bundleIdsInGroup.filter(b => {
@@ -908,7 +1000,9 @@ function createIdealGraph(assetGraph, config, entries, logger) {
908
1000
  // Remove bundles until the bundle group is within the parallel request limit.
909
1001
  while (sharedBundlesInGroup.length > 0 && numBundlesContributingToPRL > config.maxParallelRequests) {
910
1002
  let bundleTuple = sharedBundlesInGroup.pop();
1003
+ // @ts-expect-error TS18048
911
1004
  let bundleToRemove = bundleTuple.bundle;
1005
+ // @ts-expect-error TS18048
912
1006
  let bundleIdToRemove = bundleTuple.id;
913
1007
  //TODO add integration test where bundles in bunlde group > max parallel request limit & only remove a couple shared bundles
914
1008
  // but total # bundles still exceeds limit due to non shared bundles
@@ -951,16 +1045,34 @@ function createIdealGraph(assetGraph, config, entries, logger) {
951
1045
  }
952
1046
  }
953
1047
  }
954
- function mergeBundles(bundleGraph, bundleToKeepId, bundleToRemoveId, assetReference) {
955
- let bundleToKeep = (0, _nullthrows().default)(bundleGraph.getNode(bundleToKeepId));
956
- let bundleToRemove = (0, _nullthrows().default)(bundleGraph.getNode(bundleToRemoveId));
957
- (0, _assert().default)(bundleToKeep !== 'root' && bundleToRemove !== 'root');
1048
+ function mergeBundles(bundleToKeepId, bundleToRemoveId) {
1049
+ let bundleToKeep = isNonRootBundle(bundleGraph.getNode(bundleToKeepId), `Bundle ${bundleToKeepId} not found`);
1050
+ let bundleToRemove = isNonRootBundle(bundleGraph.getNode(bundleToRemoveId), `Bundle ${bundleToRemoveId} not found`);
1051
+ modifiedSourceBundles.add(bundleToKeep);
958
1052
  for (let asset of bundleToRemove.assets) {
959
1053
  bundleToKeep.assets.add(asset);
960
1054
  bundleToKeep.size += asset.stats.size;
961
1055
  let newAssetReference = assetReference.get(asset).map(([dep, bundle]) => bundle === bundleToRemove ? [dep, bundleToKeep] : [dep, bundle]);
1056
+
1057
+ // @ts-expect-error TS2345
962
1058
  assetReference.set(asset, newAssetReference);
963
1059
  }
1060
+
1061
+ // Merge any internalized assets
1062
+ if ((0, _featureFlags().getFeatureFlag)('supportWebpackChunkName')) {
1063
+ if (bundleToKeep.internalizedAssets != null) {
1064
+ if (bundleToRemove.internalizedAssets != null) {
1065
+ bundleToKeep.internalizedAssets.intersect(bundleToRemove.internalizedAssets);
1066
+ } else {
1067
+ bundleToKeep.internalizedAssets.clear();
1068
+ }
1069
+ }
1070
+ } else {
1071
+ (0, _assert().default)(bundleToKeep.internalizedAssets && bundleToRemove.internalizedAssets, 'All shared bundles should have internalized assets');
1072
+ bundleToKeep.internalizedAssets.union(bundleToRemove.internalizedAssets);
1073
+ }
1074
+
1075
+ // Merge and clean up source bundles
964
1076
  for (let sourceBundleId of bundleToRemove.sourceBundles) {
965
1077
  if (bundleToKeep.sourceBundles.has(sourceBundleId)) {
966
1078
  continue;
@@ -968,18 +1080,69 @@ function createIdealGraph(assetGraph, config, entries, logger) {
968
1080
  bundleToKeep.sourceBundles.add(sourceBundleId);
969
1081
  bundleGraph.addEdge(sourceBundleId, bundleToKeepId);
970
1082
  }
1083
+ if ((0, _featureFlags().getFeatureFlag)('supportWebpackChunkName')) {
1084
+ bundleToKeep.sourceBundles.delete(bundleToRemoveId);
1085
+ for (let bundle of bundleGraph.getNodeIdsConnectedFrom(bundleToRemoveId)) {
1086
+ let bundleNode = (0, _nullthrows().default)(bundleGraph.getNode(bundle));
1087
+ if (bundleNode === 'root') {
1088
+ continue;
1089
+ }
971
1090
 
972
- // Merge any internalized assets
973
- if (bundleToRemove.internalizedAssets) {
974
- if (bundleToKeep.internalizedAssets) {
975
- bundleToKeep.internalizedAssets.union(bundleToRemove.internalizedAssets);
976
- } else {
977
- bundleToKeep.internalizedAssets = bundleToRemove.internalizedAssets;
1091
+ // If the bundle is a source bundle, add it to the bundle to keep
1092
+ if (bundleNode.sourceBundles.has(bundleToRemoveId)) {
1093
+ bundleNode.sourceBundles.add(bundleToKeepId);
1094
+ bundleNode.sourceBundles.delete(bundleToRemoveId);
1095
+ bundleGraph.addEdge(bundleToKeepId, bundle);
1096
+ }
1097
+ }
1098
+
1099
+ // Merge bundle roots
1100
+ for (let bundleRoot of bundleToRemove.bundleRoots) {
1101
+ bundleToKeep.bundleRoots.add(bundleRoot);
1102
+ }
1103
+ if (bundleToRemove.mainEntryAsset != null) {
1104
+ (0, _assert().default)(bundleToKeep.mainEntryAsset != null);
1105
+
1106
+ // Merge the bundles in bundle group
1107
+ let bundlesInRemoveBundleGroup = getBundlesForBundleGroup(bundleToRemoveId);
1108
+ for (let bundleIdInGroup of bundlesInRemoveBundleGroup) {
1109
+ if (bundleIdInGroup === bundleToRemoveId) {
1110
+ continue;
1111
+ }
1112
+ bundleGraph.addEdge(bundleToKeepId, bundleIdInGroup);
1113
+ }
1114
+
1115
+ // Remove old bundle group
1116
+ bundleGroupBundleIds.delete(bundleToRemoveId);
1117
+
1118
+ // Clean up bundle roots
1119
+ let bundleRootToRemoveNodeId = (0, _nullthrows().default)(assetToBundleRootNodeId.get((0, _nullthrows().default)(bundleToRemove.mainEntryAsset)));
1120
+ let bundleRootToKeepNodeId = (0, _nullthrows().default)(assetToBundleRootNodeId.get((0, _nullthrows().default)(bundleToKeep.mainEntryAsset)));
1121
+ for (let nodeId of bundleRootGraph.getNodeIdsConnectedTo(bundleRootToRemoveNodeId)) {
1122
+ bundleRootGraph.addEdge(nodeId, bundleRootToKeepNodeId);
1123
+ bundleRootGraph.removeEdge(nodeId, bundleRootToRemoveNodeId);
1124
+ }
1125
+ for (let nodeId of bundleRootGraph.getNodeIdsConnectedFrom(bundleRootToRemoveNodeId)) {
1126
+ bundleRootGraph.addEdge(bundleRootToKeepNodeId, nodeId);
1127
+ bundleRootGraph.removeEdge(bundleRootToRemoveNodeId, nodeId);
1128
+ }
1129
+ bundleRoots.set((0, _nullthrows().default)(bundleToRemove.mainEntryAsset), [bundleToKeepId, bundleToKeepId]);
1130
+
1131
+ // Merge dependency bundle graph
1132
+ for (let dependencyNodeId of dependencyBundleGraph.getNodeIdsConnectedTo(dependencyBundleGraph.getNodeIdByContentKey(String(bundleToRemoveId)), _graph().ALL_EDGE_TYPES)) {
1133
+ let dependencyNode = (0, _nullthrows().default)(dependencyBundleGraph.getNode(dependencyNodeId));
1134
+ (0, _assert().default)(dependencyNode.type === 'dependency');
1135
+
1136
+ // Add dependency to the bundle to keep
1137
+ dependencyBundleGraph.addEdge(dependencyNodeId, dependencyBundleGraph.getNodeIdByContentKey(String(bundleToKeepId)), dependencyPriorityEdges[dependencyNode.value.priority]);
1138
+ // Remove dependency from the bundle to remove
1139
+ dependencyBundleGraph.removeEdge(dependencyNodeId, dependencyBundleGraph.getNodeIdByContentKey(String(bundleToRemoveId)), dependencyPriorityEdges[dependencyNode.value.priority]);
1140
+ }
978
1141
  }
979
1142
  }
980
1143
  bundleGraph.removeNode(bundleToRemoveId);
981
1144
  }
982
- function mergeOverlapBundles() {
1145
+ function mergeOverlapBundles(mergeConfig) {
983
1146
  // Find all shared bundles
984
1147
  let sharedBundles = new Set();
985
1148
  bundleGraph.traverse(nodeId => {
@@ -998,18 +1161,34 @@ function createIdealGraph(assetGraph, config, entries, logger) {
998
1161
  sharedBundles.add(nodeId);
999
1162
  }
1000
1163
  });
1001
- let clusters = (0, _bundleMerge.findMergeCandidates)(bundleGraph, Array.from(sharedBundles), config.sharedBundleMergeThreshold);
1164
+ let clusters = (0, _bundleMerge.findMergeCandidates)(bundleGraph, Array.from(sharedBundles), mergeConfig.map(config => {
1165
+ var _config$sourceBundles;
1166
+ return {
1167
+ ...config,
1168
+ sourceBundles: (_config$sourceBundles = config.sourceBundles) === null || _config$sourceBundles === void 0 ? void 0 : _config$sourceBundles.map(assetMatch => {
1169
+ let sourceBundleNodeId = mergeSourceBundleLookup.get(assetMatch);
1170
+ if (sourceBundleNodeId == null) {
1171
+ throw new Error(`Source bundle ${assetMatch} not found in merge source bundle lookup`);
1172
+ }
1173
+ return sourceBundleNodeId;
1174
+ })
1175
+ };
1176
+ }));
1177
+ let mergedBundles = new Set();
1002
1178
  for (let cluster of clusters) {
1003
1179
  let [mergeTarget, ...rest] = cluster;
1004
1180
  for (let bundleIdToMerge of rest) {
1005
- mergeBundles(bundleGraph, mergeTarget, bundleIdToMerge, assetReference);
1181
+ mergeBundles(mergeTarget, bundleIdToMerge);
1006
1182
  }
1183
+ mergedBundles.add(mergeTarget);
1184
+ }
1185
+ if ((0, _featureFlags().getFeatureFlag)('supportWebpackChunkName')) {
1186
+ return mergedBundles;
1007
1187
  }
1008
1188
  }
1009
1189
  function getBigIntFromContentKey(contentKey) {
1010
1190
  let b = Buffer.alloc(64);
1011
1191
  b.write(contentKey);
1012
- // $FlowFixMe Flow doesn't have BigInt types in this version
1013
1192
  return b.readBigInt64BE();
1014
1193
  }
1015
1194
  // Fix asset order in source bundles as they are likely now incorrect after shared bundle deletion
@@ -1104,6 +1283,7 @@ function createBundle(opts) {
1104
1283
  bundleBehavior: opts.bundleBehavior,
1105
1284
  env: (0, _nullthrows().default)(opts.env),
1106
1285
  mainEntryAsset: null,
1286
+ bundleRoots: new Set(),
1107
1287
  manualSharedBundle: opts.manualSharedBundle,
1108
1288
  needsStableName: Boolean(opts.needsStableName),
1109
1289
  size: 0,
@@ -1119,6 +1299,7 @@ function createBundle(opts) {
1119
1299
  bundleBehavior: opts.bundleBehavior ?? asset.bundleBehavior,
1120
1300
  env: opts.env ?? asset.env,
1121
1301
  mainEntryAsset: asset,
1302
+ bundleRoots: new Set([asset]),
1122
1303
  manualSharedBundle: opts.manualSharedBundle,
1123
1304
  needsStableName: Boolean(opts.needsStableName),
1124
1305
  size: asset.stats.size,
package/lib/memoize.js ADDED
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.clearCaches = clearCaches;
7
+ exports.memoize = memoize;
8
+ function _manyKeysMap() {
9
+ const data = _interopRequireDefault(require("many-keys-map"));
10
+ _manyKeysMap = function () {
11
+ return data;
12
+ };
13
+ return data;
14
+ }
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ let caches = [];
17
+ function clearCaches() {
18
+ for (let cache of caches) {
19
+ cache.clear();
20
+ }
21
+ }
22
+ function memoize(fn) {
23
+ let cache = new (_manyKeysMap().default)();
24
+ caches.push(cache);
25
+ return function (...args) {
26
+ // Navigate through the cache hierarchy
27
+ let cached = cache.get(args);
28
+ if (cached !== undefined) {
29
+ // If the result is cached, return it
30
+ return cached;
31
+ }
32
+
33
+ // Calculate the result and cache it
34
+ // @ts-expect-error TS2683
35
+ const result = fn.apply(this, args);
36
+ cache.set(args, result);
37
+ return result;
38
+ };
39
+ }