@atlaspack/bundler-default 2.14.5-canary.3 → 2.14.5-canary.300

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.
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.clearCaches = clearCaches;
7
+ exports.memoize = memoize;
8
+ const many_keys_map_1 = __importDefault(require("many-keys-map"));
9
+ let caches = [];
10
+ function clearCaches() {
11
+ for (let cache of caches) {
12
+ cache.clear();
13
+ }
14
+ }
15
+ function memoize(fn) {
16
+ let cache = new many_keys_map_1.default();
17
+ caches.push(cache);
18
+ return function (...args) {
19
+ // Navigate through the cache hierarchy
20
+ let cached = cache.get(args);
21
+ if (cached !== undefined) {
22
+ // If the result is cached, return it
23
+ return cached;
24
+ }
25
+ // Calculate the result and cache it
26
+ // @ts-expect-error TS2683
27
+ const result = fn.apply(this, args);
28
+ cache.set(args, result);
29
+ return result;
30
+ };
31
+ }
package/dist/stats.js ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Stats = void 0;
4
+ const path_1 = require("path");
5
+ const utils_1 = require("@atlaspack/utils");
6
+ class Stats {
7
+ constructor(projectRoot) {
8
+ this.merges = new utils_1.DefaultMap(() => []);
9
+ this.projectRoot = projectRoot;
10
+ }
11
+ trackMerge(bundleToKeep, bundleToRemove, reason) {
12
+ if (!utils_1.debugTools['bundle-stats']) {
13
+ return;
14
+ }
15
+ this.merges
16
+ .get(bundleToKeep)
17
+ .push(...this.merges.get(bundleToRemove), { id: bundleToRemove, reason });
18
+ this.merges.delete(bundleToRemove);
19
+ }
20
+ getBundleLabel(bundle) {
21
+ if (bundle.manualSharedBundle) {
22
+ return bundle.manualSharedBundle;
23
+ }
24
+ if (bundle.mainEntryAsset) {
25
+ let relativePath = (0, path_1.relative)(this.projectRoot, bundle.mainEntryAsset.filePath);
26
+ if (relativePath.length > 100) {
27
+ relativePath =
28
+ relativePath.slice(0, 50) + '...' + relativePath.slice(-50);
29
+ }
30
+ return relativePath;
31
+ }
32
+ return `shared`;
33
+ }
34
+ report(getBundle) {
35
+ if (!utils_1.debugTools['bundle-stats']) {
36
+ return;
37
+ }
38
+ let mergeResults = [];
39
+ let totals = {
40
+ label: 'Totals',
41
+ merges: 0,
42
+ };
43
+ for (let [bundleId, mergedBundles] of this.merges) {
44
+ let bundle = getBundle(bundleId);
45
+ if (!bundle) {
46
+ continue;
47
+ }
48
+ let result = {
49
+ label: this.getBundleLabel(bundle),
50
+ size: bundle.size,
51
+ merges: mergedBundles.length,
52
+ };
53
+ for (let merged of mergedBundles) {
54
+ result[merged.reason] = (result[merged.reason] || 0) + 1;
55
+ totals[merged.reason] = (totals[merged.reason] || 0) + 1;
56
+ }
57
+ totals.merges += mergedBundles.length;
58
+ mergeResults.push(result);
59
+ }
60
+ mergeResults.sort((a, b) => {
61
+ // Sort by bundle size descending
62
+ return b.size - a.size;
63
+ });
64
+ mergeResults.push(totals);
65
+ // eslint-disable-next-line no-console
66
+ console.table(mergeResults);
67
+ }
68
+ }
69
+ exports.Stats = Stats;
@@ -59,6 +59,7 @@ var _default = exports.default = new (_plugin().Bundler)({
59
59
  logger
60
60
  }) {
61
61
  let targetMap = getEntryByTarget(bundleGraph); // Organize entries by target output folder/ distDir
62
+ // @ts-expect-error TS2304
62
63
  let graphs = [];
63
64
  for (let entries of targetMap.values()) {
64
65
  let singleFileEntries = new Map();
@@ -94,7 +95,11 @@ function getEntryByTarget(bundleGraph) {
94
95
  // Find entries from assetGraph per target
95
96
  let targets = new (_utils().DefaultMap)(() => new Map());
96
97
  bundleGraph.traverse({
97
- enter(node, context, actions) {
98
+ enter(
99
+ // @ts-expect-error TS2304
100
+ node, context,
101
+ // @ts-expect-error TS2304
102
+ actions) {
98
103
  if (node.type !== 'asset') {
99
104
  return node;
100
105
  }
@@ -4,6 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.addJSMonolithBundle = addJSMonolithBundle;
7
+ function _featureFlags() {
8
+ const data = require("@atlaspack/feature-flags");
9
+ _featureFlags = function () {
10
+ return data;
11
+ };
12
+ return data;
13
+ }
7
14
  function _nullthrows() {
8
15
  const data = _interopRequireDefault(require("nullthrows"));
9
16
  _nullthrows = function () {
@@ -18,7 +25,8 @@ function addJSMonolithBundle(bundleGraph, entryAsset, entryDep) {
18
25
  // Create a single bundle to hold all JS assets
19
26
  let bundle = bundleGraph.createBundle({
20
27
  entryAsset,
21
- target
28
+ target,
29
+ needsStableName: (0, _featureFlags().getFeatureFlag)('singleFileOutputStableName')
22
30
  });
23
31
  bundleGraph.traverse((node, _, actions) => {
24
32
  // JS assets can be added to the bundle, but the rest are ignored
@@ -38,8 +46,8 @@ function addJSMonolithBundle(bundleGraph, entryAsset, entryDep) {
38
46
  }
39
47
  let assets = bundleGraph.getDependencyAssets(dependency);
40
48
  for (const asset of assets) {
41
- if (asset.bundleBehavior === 'isolated') {
42
- throw new Error('Isolated assets are not supported for single file output builds');
49
+ if (asset.bundleBehavior === 'isolated' || asset.bundleBehavior === 'inlineIsolated') {
50
+ throw new Error(`${asset.bundleBehavior === 'isolated' ? 'Isolated' : 'Inline isolated'} assets are not supported for single file output builds`);
43
51
  }
44
52
 
45
53
  // For assets marked as inline, we create new bundles and let other
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.findMergeCandidates = findMergeCandidates;
7
+ function _assert() {
8
+ const data = _interopRequireDefault(require("assert"));
9
+ _assert = function () {
10
+ return data;
11
+ };
12
+ return data;
13
+ }
14
+ function _nullthrows() {
15
+ const data = _interopRequireDefault(require("nullthrows"));
16
+ _nullthrows = function () {
17
+ return data;
18
+ };
19
+ return data;
20
+ }
21
+ function _graph() {
22
+ const data = require("@atlaspack/graph");
23
+ _graph = function () {
24
+ return data;
25
+ };
26
+ return data;
27
+ }
28
+ function _utils() {
29
+ const data = require("@atlaspack/utils");
30
+ _utils = function () {
31
+ return data;
32
+ };
33
+ return data;
34
+ }
35
+ var _memoize = require("./memoize");
36
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
37
+ function getBundlesForBundleGroup(bundleGraph, bundleGroupId) {
38
+ let count = 0;
39
+ bundleGraph.traverse(nodeId => {
40
+ const node = bundleGraph.getNode(nodeId);
41
+ if (node && (node === 'root' || node.bundleBehavior !== 'inline' && node.bundleBehavior !== 'inlineIsolated')) {
42
+ count++;
43
+ }
44
+ }, bundleGroupId);
45
+ return count;
46
+ }
47
+ let getBundleOverlap = (sourceBundlesA, sourceBundlesB) => {
48
+ let allSourceBundles = (0, _utils().setUnion)(sourceBundlesA, sourceBundlesB);
49
+ let sharedSourceBundles = (0, _utils().setIntersectStatic)(sourceBundlesA, sourceBundlesB);
50
+ return sharedSourceBundles.size / allSourceBundles.size;
51
+ };
52
+
53
+ // Returns a decimal showing the proportion source bundles are common to
54
+ // both bundles versus the total number of source bundles.
55
+ function checkBundleThreshold(bundleA, bundleB, threshold) {
56
+ return getBundleOverlap(bundleA.bundle.sourceBundles, bundleB.bundle.sourceBundles) >= threshold;
57
+ }
58
+ let checkSharedSourceBundles = (0, _memoize.memoize)((bundle, importantAncestorBundles) => {
59
+ return importantAncestorBundles.every(ancestorId => bundle.sourceBundles.has(ancestorId));
60
+ });
61
+ let hasSuitableBundleGroup = (0, _memoize.memoize)((bundleGraph, bundle, minBundlesInGroup) => {
62
+ for (let sourceBundle of bundle.sourceBundles) {
63
+ let bundlesInGroup = getBundlesForBundleGroup(bundleGraph, sourceBundle);
64
+ if (bundlesInGroup >= minBundlesInGroup) {
65
+ return true;
66
+ }
67
+ }
68
+ return false;
69
+ });
70
+ function validMerge(bundleGraph, config, bundleA, bundleB) {
71
+ if (config.maxBundleSize != null) {
72
+ if (bundleA.bundle.size > config.maxBundleSize || bundleB.bundle.size > config.maxBundleSize) {
73
+ return false;
74
+ }
75
+ }
76
+ if (config.overlapThreshold != null) {
77
+ if (!checkBundleThreshold(bundleA, bundleB, config.overlapThreshold)) {
78
+ return false;
79
+ }
80
+ }
81
+ if (config.sourceBundles != null) {
82
+ if (!checkSharedSourceBundles(bundleA.bundle, config.sourceBundles) || !checkSharedSourceBundles(bundleB.bundle, config.sourceBundles)) {
83
+ return false;
84
+ }
85
+ }
86
+ if (config.minBundlesInGroup != null) {
87
+ if (!hasSuitableBundleGroup(bundleGraph, bundleA.bundle, config.minBundlesInGroup) || !hasSuitableBundleGroup(bundleGraph, bundleB.bundle, config.minBundlesInGroup)) {
88
+ return false;
89
+ }
90
+ }
91
+ return true;
92
+ }
93
+ function getMergeClusters(graph, candidates) {
94
+ let clusters = [];
95
+ for (let [candidate, edgeType] of candidates.entries()) {
96
+ let cluster = [];
97
+ graph.traverse(nodeId => {
98
+ cluster.push((0, _nullthrows().default)(graph.getNode(nodeId)));
99
+ // Remove node from candidates as it has already been processed
100
+ candidates.delete(nodeId);
101
+ }, candidate, edgeType);
102
+ clusters.push(cluster);
103
+ }
104
+ return clusters;
105
+ }
106
+ function getPossibleMergeCandidates(bundleGraph, bundles) {
107
+ let mergeCandidates = bundles.map(bundleId => {
108
+ let bundle = bundleGraph.getNode(bundleId);
109
+ (0, _assert().default)(bundle && bundle !== 'root', 'Bundle should exist');
110
+ return {
111
+ id: bundleId,
112
+ bundle,
113
+ contentKey: bundleId.toString()
114
+ };
115
+ });
116
+ const uniquePairs = [];
117
+ for (let i = 0; i < mergeCandidates.length; i++) {
118
+ for (let j = i + 1; j < mergeCandidates.length; j++) {
119
+ let a = mergeCandidates[i];
120
+ let b = mergeCandidates[j];
121
+
122
+ // @ts-expect-error TS18048
123
+ if (a.bundle.internalizedAssets.equals(b.bundle.internalizedAssets)) {
124
+ uniquePairs.push([a, b]);
125
+ }
126
+ }
127
+ }
128
+ return uniquePairs;
129
+ }
130
+ function findMergeCandidates(bundleGraph, bundles, config) {
131
+ let graph = new (_graph().ContentGraph)();
132
+ let candidates = new Map();
133
+ let allPossibleMergeCandidates = getPossibleMergeCandidates(bundleGraph, bundles);
134
+
135
+ // Build graph of clustered merge candidates
136
+ for (let i = 0; i < config.length; i++) {
137
+ // Ensure edge type coresponds to config index
138
+ let edgeType = i + 1;
139
+ for (let group of allPossibleMergeCandidates) {
140
+ let candidateA = group[0];
141
+ let candidateB = group[1];
142
+ if (!validMerge(bundleGraph, config[i], candidateA, candidateB)) {
143
+ continue;
144
+ }
145
+ let bundleNode = graph.addNodeByContentKeyIfNeeded(candidateA.contentKey, candidateA.id);
146
+ let otherBundleNode = graph.addNodeByContentKeyIfNeeded(candidateB.contentKey, candidateB.id);
147
+
148
+ // Add edge in both directions
149
+ graph.addEdge(bundleNode, otherBundleNode, edgeType);
150
+ graph.addEdge(otherBundleNode, bundleNode, edgeType);
151
+ candidates.set(bundleNode, edgeType);
152
+ candidates.set(otherBundleNode, edgeType);
153
+ }
154
+
155
+ // Remove bundles that have been allocated to a higher priority merge
156
+ allPossibleMergeCandidates = allPossibleMergeCandidates.filter(group => !graph.hasContentKey(group[0].contentKey) && !graph.hasContentKey(group[1].contentKey));
157
+ }
158
+ (0, _memoize.clearCaches)();
159
+ return getMergeClusters(graph, candidates);
160
+ }
@@ -11,6 +11,13 @@ function _diagnostic() {
11
11
  };
12
12
  return data;
13
13
  }
14
+ function _featureFlags() {
15
+ const data = require("@atlaspack/feature-flags");
16
+ _featureFlags = function () {
17
+ return data;
18
+ };
19
+ return data;
20
+ }
14
21
  function _utils() {
15
22
  const data = require("@atlaspack/utils");
16
23
  _utils = function () {
@@ -32,14 +39,13 @@ function resolveModeConfig(config, mode) {
32
39
  for (const key of Object.keys(config)) {
33
40
  if (key === 'development' || key === 'production') {
34
41
  if (key === mode) {
42
+ // @ts-expect-error TS2322
35
43
  modeConfig = config[key];
36
44
  }
37
45
  } else {
38
46
  generalConfig[key] = config[key];
39
47
  }
40
48
  }
41
-
42
- // $FlowFixMe Not sure how to convince flow here...
43
49
  return {
44
50
  ...generalConfig,
45
51
  ...modeConfig
@@ -53,14 +59,16 @@ const HTTP_OPTIONS = {
53
59
  manualSharedBundles: [],
54
60
  minBundleSize: 30000,
55
61
  maxParallelRequests: 6,
56
- disableSharedBundles: false
62
+ disableSharedBundles: false,
63
+ sharedBundleMerge: []
57
64
  },
58
65
  '2': {
59
66
  minBundles: 1,
60
67
  manualSharedBundles: [],
61
68
  minBundleSize: 20000,
62
69
  maxParallelRequests: 25,
63
- disableSharedBundles: false
70
+ disableSharedBundles: false,
71
+ sharedBundleMerge: []
64
72
  }
65
73
  };
66
74
  const CONFIG_SCHEMA = {
@@ -101,6 +109,50 @@ const CONFIG_SCHEMA = {
101
109
  additionalProperties: false
102
110
  }
103
111
  },
112
+ sharedBundleMerge: {
113
+ type: 'array',
114
+ items: {
115
+ type: 'object',
116
+ properties: {
117
+ overlapThreshold: {
118
+ type: 'number'
119
+ },
120
+ maxBundleSize: {
121
+ type: 'number'
122
+ },
123
+ sourceBundles: {
124
+ type: 'array',
125
+ items: {
126
+ type: 'string'
127
+ }
128
+ },
129
+ minBundlesInGroup: {
130
+ type: 'number'
131
+ }
132
+ },
133
+ additionalProperties: false
134
+ }
135
+ },
136
+ asyncBundleMerge: {
137
+ type: 'object',
138
+ properties: {
139
+ bundleSize: {
140
+ type: 'number',
141
+ required: true
142
+ },
143
+ maxOverfetchSize: {
144
+ type: 'number',
145
+ required: true
146
+ },
147
+ ignore: {
148
+ type: 'array',
149
+ items: {
150
+ type: 'string'
151
+ }
152
+ }
153
+ },
154
+ additionalProperties: false
155
+ },
104
156
  minBundles: {
105
157
  type: 'number'
106
158
  },
@@ -115,22 +167,34 @@ const CONFIG_SCHEMA = {
115
167
  },
116
168
  loadConditionalBundlesInParallel: {
117
169
  type: 'boolean'
170
+ },
171
+ sharedBundleMergeThreshold: {
172
+ type: 'number'
118
173
  }
119
174
  },
120
175
  additionalProperties: false
121
176
  };
122
177
  async function loadBundlerConfig(config, options, logger) {
123
- let conf = await config.getConfig([], {
124
- packageKey: '@atlaspack/bundler-default'
125
- });
178
+ var _conf;
179
+ let conf;
180
+ if ((0, _featureFlags().getFeatureFlag)('resolveBundlerConfigFromCwd')) {
181
+ conf = await config.getConfigFrom(`${process.cwd()}/index`, [], {
182
+ packageKey: '@atlaspack/bundler-default'
183
+ });
184
+ } else {
185
+ conf = await config.getConfig([], {
186
+ packageKey: '@atlaspack/bundler-default'
187
+ });
188
+ }
126
189
  if (!conf) {
127
190
  const modDefault = {
128
191
  ...HTTP_OPTIONS['2'],
129
192
  projectRoot: options.projectRoot
130
193
  };
194
+ // @ts-expect-error TS2322
131
195
  return modDefault;
132
196
  }
133
- (0, _assert().default)((conf === null || conf === void 0 ? void 0 : conf.contents) != null);
197
+ (0, _assert().default)(((_conf = conf) === null || _conf === void 0 ? void 0 : _conf.contents) != null);
134
198
  let modeConfig = resolveModeConfig(conf.contents, options.mode);
135
199
 
136
200
  // minBundles will be ignored if shared bundles are disabled
@@ -163,15 +227,18 @@ async function loadBundlerConfig(config, options, logger) {
163
227
  }
164
228
  _utils().validateSchema.diagnostic(CONFIG_SCHEMA, {
165
229
  data: modeConfig,
166
- source: await options.inputFS.readFile(conf.filePath, 'utf8'),
230
+ source: () => options.inputFS.readFileSync(conf.filePath, 'utf8'),
167
231
  filePath: conf.filePath,
168
232
  prependKey: `/${(0, _diagnostic().encodeJSONKeyComponent)('@atlaspack/bundler-default')}`
169
233
  }, '@atlaspack/bundler-default', 'Invalid config for @atlaspack/bundler-default');
170
234
  let http = modeConfig.http ?? 2;
235
+ // @ts-expect-error TS7053
171
236
  let defaults = HTTP_OPTIONS[http];
172
237
  return {
173
238
  minBundles: modeConfig.minBundles ?? defaults.minBundles,
174
239
  minBundleSize: modeConfig.minBundleSize ?? defaults.minBundleSize,
240
+ sharedBundleMerge: modeConfig.sharedBundleMerge ?? defaults.sharedBundleMerge,
241
+ asyncBundleMerge: modeConfig.asyncBundleMerge,
175
242
  maxParallelRequests: modeConfig.maxParallelRequests ?? defaults.maxParallelRequests,
176
243
  projectRoot: options.projectRoot,
177
244
  disableSharedBundles: modeConfig.disableSharedBundles ?? defaults.disableSharedBundles,
@@ -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) {