@atlaspack/bundler-default 3.1.3-typescript-5b4d3ad41.0 → 3.2.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.
- package/CHANGELOG.md +25 -0
- package/lib/DefaultBundler.js +4 -7
- package/lib/bundleMerge.js +3 -4
- package/lib/bundlerConfig.js +2 -3
- package/lib/decorateLegacyGraph.js +20 -7
- package/lib/idealGraph.js +150 -43
- package/lib/memoize.js +2 -1
- package/package.json +13 -18
- package/src/{DefaultBundler.ts → DefaultBundler.js} +7 -21
- package/src/{MonolithicBundler.ts → MonolithicBundler.js} +1 -0
- package/src/{bundleMerge.ts → bundleMerge.js} +19 -16
- package/src/{bundlerConfig.ts → bundlerConfig.js} +44 -43
- package/src/{decorateLegacyGraph.ts → decorateLegacyGraph.js} +24 -7
- package/src/{idealGraph.ts → idealGraph.js} +302 -136
- package/src/{memoize.ts → memoize.js} +6 -3
- package/LICENSE +0 -201
- package/lib/DefaultBundler.d.ts +0 -18
- package/lib/MonolithicBundler.d.ts +0 -2
- package/lib/bundleMerge.d.ts +0 -9
- package/lib/bundlerConfig.d.ts +0 -27
- package/lib/decorateLegacyGraph.d.ts +0 -3
- package/lib/idealGraph.d.ts +0 -39
- package/lib/memoize.d.ts +0 -2
- package/tsconfig.json +0 -4
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// @flow strict-local
|
|
2
|
+
|
|
1
3
|
import path from 'path';
|
|
2
4
|
|
|
3
5
|
import {getFeatureFlag} from '@atlaspack/feature-flags';
|
|
@@ -6,7 +8,7 @@ import {
|
|
|
6
8
|
BitSet,
|
|
7
9
|
ContentGraph,
|
|
8
10
|
Graph,
|
|
9
|
-
NodeId,
|
|
11
|
+
type NodeId,
|
|
10
12
|
} from '@atlaspack/graph';
|
|
11
13
|
import type {
|
|
12
14
|
Asset,
|
|
@@ -21,37 +23,38 @@ import {DefaultMap, globToRegex} from '@atlaspack/utils';
|
|
|
21
23
|
import invariant from 'assert';
|
|
22
24
|
import nullthrows from 'nullthrows';
|
|
23
25
|
|
|
24
|
-
import {findMergeCandidates, MergeGroup} from './bundleMerge';
|
|
26
|
+
import {findMergeCandidates, type MergeGroup} from './bundleMerge';
|
|
25
27
|
import type {ResolvedBundlerConfig, MergeCandidates} from './bundlerConfig';
|
|
26
28
|
|
|
27
29
|
/* BundleRoot - An asset that is the main entry of a Bundle. */
|
|
28
30
|
type BundleRoot = Asset;
|
|
29
31
|
|
|
30
|
-
export type Bundle = {
|
|
31
|
-
uniqueKey: string
|
|
32
|
-
assets: Set<Asset
|
|
33
|
-
internalizedAssets?: BitSet
|
|
34
|
-
bundleBehavior?: BundleBehavior
|
|
35
|
-
needsStableName: boolean
|
|
36
|
-
mainEntryAsset: Asset
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
export type Bundle = {|
|
|
33
|
+
uniqueKey: ?string,
|
|
34
|
+
assets: Set<Asset>,
|
|
35
|
+
internalizedAssets?: BitSet,
|
|
36
|
+
bundleBehavior?: ?BundleBehavior,
|
|
37
|
+
needsStableName: boolean,
|
|
38
|
+
mainEntryAsset: ?Asset,
|
|
39
|
+
bundleRoots: Set<Asset>,
|
|
40
|
+
size: number,
|
|
41
|
+
sourceBundles: Set<NodeId>,
|
|
42
|
+
target: Target,
|
|
43
|
+
env: Environment,
|
|
44
|
+
type: string,
|
|
45
|
+
manualSharedBundle: ?string, // for naming purposes
|
|
46
|
+
|};
|
|
44
47
|
|
|
45
48
|
export type DependencyBundleGraph = ContentGraph<
|
|
46
|
-
| {
|
|
47
|
-
value: Bundle
|
|
48
|
-
type: 'bundle'
|
|
49
|
-
}
|
|
50
|
-
| {
|
|
51
|
-
value: Dependency
|
|
52
|
-
type: 'dependency'
|
|
53
|
-
},
|
|
54
|
-
number
|
|
49
|
+
| {|
|
|
50
|
+
value: Bundle,
|
|
51
|
+
type: 'bundle',
|
|
52
|
+
|}
|
|
53
|
+
| {|
|
|
54
|
+
value: Dependency,
|
|
55
|
+
type: 'dependency',
|
|
56
|
+
|},
|
|
57
|
+
number,
|
|
55
58
|
>;
|
|
56
59
|
|
|
57
60
|
const dependencyPriorityEdges = {
|
|
@@ -59,7 +62,7 @@ const dependencyPriorityEdges = {
|
|
|
59
62
|
parallel: 2,
|
|
60
63
|
lazy: 3,
|
|
61
64
|
conditional: 4,
|
|
62
|
-
}
|
|
65
|
+
};
|
|
63
66
|
|
|
64
67
|
export const idealBundleGraphEdges = Object.freeze({
|
|
65
68
|
default: 1,
|
|
@@ -68,20 +71,30 @@ export const idealBundleGraphEdges = Object.freeze({
|
|
|
68
71
|
|
|
69
72
|
export type IdealBundleGraph = Graph<
|
|
70
73
|
Bundle | 'root',
|
|
71
|
-
|
|
74
|
+
$Values<typeof idealBundleGraphEdges>,
|
|
72
75
|
>;
|
|
73
76
|
|
|
74
77
|
// IdealGraph is the structure we will pass to decorate,
|
|
75
78
|
// which mutates the assetGraph into the bundleGraph we would
|
|
76
79
|
// expect from default bundler
|
|
77
|
-
export type IdealGraph = {
|
|
78
|
-
assetReference: DefaultMap<Asset, Array<[Dependency, Bundle]
|
|
79
|
-
assets: Array<Asset
|
|
80
|
-
bundleGraph: IdealBundleGraph
|
|
81
|
-
bundleGroupBundleIds: Set<NodeId
|
|
82
|
-
dependencyBundleGraph: DependencyBundleGraph
|
|
83
|
-
manualAssetToBundle: Map<Asset, NodeId
|
|
84
|
-
};
|
|
80
|
+
export type IdealGraph = {|
|
|
81
|
+
assetReference: DefaultMap<Asset, Array<[Dependency, Bundle]>>,
|
|
82
|
+
assets: Array<Asset>,
|
|
83
|
+
bundleGraph: IdealBundleGraph,
|
|
84
|
+
bundleGroupBundleIds: Set<NodeId>,
|
|
85
|
+
dependencyBundleGraph: DependencyBundleGraph,
|
|
86
|
+
manualAssetToBundle: Map<Asset, NodeId>,
|
|
87
|
+
|};
|
|
88
|
+
|
|
89
|
+
function isNonRootBundle(
|
|
90
|
+
bundle?: Bundle | 'root' | null,
|
|
91
|
+
message?: string,
|
|
92
|
+
): Bundle {
|
|
93
|
+
let existingBundle = nullthrows(bundle, message);
|
|
94
|
+
invariant(existingBundle !== 'root', "Bundle cannot be 'root'");
|
|
95
|
+
|
|
96
|
+
return existingBundle;
|
|
97
|
+
}
|
|
85
98
|
|
|
86
99
|
export function createIdealGraph(
|
|
87
100
|
assetGraph: MutableBundleGraph,
|
|
@@ -95,7 +108,7 @@ export function createIdealGraph(
|
|
|
95
108
|
let dependencyBundleGraph: DependencyBundleGraph = new ContentGraph();
|
|
96
109
|
let assetReference: DefaultMap<
|
|
97
110
|
Asset,
|
|
98
|
-
Array<[Dependency, Bundle]
|
|
111
|
+
Array<[Dependency, Bundle]>,
|
|
99
112
|
> = new DefaultMap(() => []);
|
|
100
113
|
|
|
101
114
|
// A Graph of Bundles and a root node (dummy string), which models only Bundles, and connections to their
|
|
@@ -109,9 +122,8 @@ export function createIdealGraph(
|
|
|
109
122
|
};
|
|
110
123
|
// Graph that models bundleRoots, with parallel & async deps only to inform reachability
|
|
111
124
|
let bundleRootGraph: Graph<
|
|
112
|
-
// asset index
|
|
113
|
-
|
|
114
|
-
(typeof bundleRootEdgeTypes)[keyof typeof bundleRootEdgeTypes]
|
|
125
|
+
number, // asset index
|
|
126
|
+
$Values<typeof bundleRootEdgeTypes>,
|
|
115
127
|
> = new Graph();
|
|
116
128
|
let assetToBundleRootNodeId = new Map<BundleRoot, number>();
|
|
117
129
|
|
|
@@ -145,7 +157,7 @@ export function createIdealGraph(
|
|
|
145
157
|
bundleGroupBundleIds.add(nodeId);
|
|
146
158
|
}
|
|
147
159
|
|
|
148
|
-
let assets
|
|
160
|
+
let assets = [];
|
|
149
161
|
let assetToIndex = new Map<Asset, number>();
|
|
150
162
|
|
|
151
163
|
function makeManualAssetToConfigLookup() {
|
|
@@ -160,7 +172,6 @@ export function createIdealGraph(
|
|
|
160
172
|
|
|
161
173
|
for (let c of config.manualSharedBundles) {
|
|
162
174
|
if (c.root != null) {
|
|
163
|
-
// @ts-expect-error TS2345
|
|
164
175
|
parentsToConfig.get(path.join(config.projectRoot, c.root)).push(c);
|
|
165
176
|
}
|
|
166
177
|
}
|
|
@@ -208,7 +219,6 @@ export function createIdealGraph(
|
|
|
208
219
|
// We track all matching MSB's for constant modules as they are never duplicated
|
|
209
220
|
// and need to be assigned to all matching bundles
|
|
210
221
|
if (node.value.meta.isConstantModule === true) {
|
|
211
|
-
// @ts-expect-error TS2345
|
|
212
222
|
constantModuleToMSB.get(node.value).push(c);
|
|
213
223
|
}
|
|
214
224
|
|
|
@@ -242,14 +252,14 @@ export function createIdealGraph(
|
|
|
242
252
|
makeManualAssetToConfigLookup();
|
|
243
253
|
let manualBundleToInternalizedAsset: DefaultMap<
|
|
244
254
|
NodeId,
|
|
245
|
-
Array<Asset
|
|
255
|
+
Array<Asset>,
|
|
246
256
|
> = new DefaultMap(() => []);
|
|
247
257
|
|
|
248
258
|
let mergeSourceBundleLookup = new Map<string, NodeId>();
|
|
249
259
|
let mergeSourceBundleAssets = new Set(
|
|
250
260
|
config.sharedBundleMerge?.flatMap(
|
|
251
261
|
(c) =>
|
|
252
|
-
c.sourceBundles?.map((assetMatch
|
|
262
|
+
c.sourceBundles?.map((assetMatch) =>
|
|
253
263
|
path.join(config.projectRoot, assetMatch),
|
|
254
264
|
) ?? [],
|
|
255
265
|
),
|
|
@@ -262,27 +272,7 @@ export function createIdealGraph(
|
|
|
262
272
|
*/
|
|
263
273
|
assetGraph.traverse(
|
|
264
274
|
{
|
|
265
|
-
enter(
|
|
266
|
-
node: // @ts-expect-error TS2304
|
|
267
|
-
| BundleGraphTraversable
|
|
268
|
-
| {
|
|
269
|
-
readonly type: 'dependency';
|
|
270
|
-
value: Dependency;
|
|
271
|
-
},
|
|
272
|
-
context:
|
|
273
|
-
| {
|
|
274
|
-
readonly type: 'asset';
|
|
275
|
-
value: Asset;
|
|
276
|
-
}
|
|
277
|
-
| null
|
|
278
|
-
| undefined
|
|
279
|
-
| {
|
|
280
|
-
readonly type: 'dependency';
|
|
281
|
-
value: Dependency;
|
|
282
|
-
},
|
|
283
|
-
// @ts-expect-error TS2304
|
|
284
|
-
actions: TraversalActions,
|
|
285
|
-
) {
|
|
275
|
+
enter(node, context, actions) {
|
|
286
276
|
if (node.type === 'asset') {
|
|
287
277
|
if (
|
|
288
278
|
context?.type === 'dependency' &&
|
|
@@ -409,7 +399,6 @@ export function createIdealGraph(
|
|
|
409
399
|
type: 'bundle',
|
|
410
400
|
},
|
|
411
401
|
),
|
|
412
|
-
// @ts-expect-error TS7053
|
|
413
402
|
dependencyPriorityEdges[dependency.priority],
|
|
414
403
|
);
|
|
415
404
|
|
|
@@ -521,7 +510,6 @@ export function createIdealGraph(
|
|
|
521
510
|
|
|
522
511
|
assetReference.get(childAsset).push([dependency, bundle]);
|
|
523
512
|
} else {
|
|
524
|
-
// @ts-expect-error TS2322
|
|
525
513
|
bundleId = null;
|
|
526
514
|
}
|
|
527
515
|
if (manualSharedObject && bundleId != null) {
|
|
@@ -529,7 +517,6 @@ export function createIdealGraph(
|
|
|
529
517
|
// add the asset if it doesn't already have it and set key
|
|
530
518
|
|
|
531
519
|
invariant(
|
|
532
|
-
// @ts-expect-error TS2367
|
|
533
520
|
bundle !== 'root' && bundle != null && bundleId != null,
|
|
534
521
|
);
|
|
535
522
|
|
|
@@ -556,8 +543,7 @@ export function createIdealGraph(
|
|
|
556
543
|
}
|
|
557
544
|
return node;
|
|
558
545
|
},
|
|
559
|
-
|
|
560
|
-
exit(node: BundleGraphTraversable) {
|
|
546
|
+
exit(node) {
|
|
561
547
|
if (stack[stack.length - 1]?.[0] === node.value) {
|
|
562
548
|
stack.pop();
|
|
563
549
|
}
|
|
@@ -606,20 +592,20 @@ export function createIdealGraph(
|
|
|
606
592
|
|
|
607
593
|
// reachableRoots is an array of bit sets for each asset. Each bit set
|
|
608
594
|
// indicates which bundle roots are reachable from that asset synchronously.
|
|
609
|
-
let reachableRoots
|
|
595
|
+
let reachableRoots = [];
|
|
610
596
|
for (let i = 0; i < assets.length; i++) {
|
|
611
597
|
reachableRoots.push(new BitSet(bundleRootGraph.nodes.length));
|
|
612
598
|
}
|
|
613
599
|
|
|
614
600
|
// reachableAssets is the inverse mapping of reachableRoots. For each bundle root,
|
|
615
601
|
// it contains a bit set that indicates which assets are reachable from it.
|
|
616
|
-
let reachableAssets
|
|
602
|
+
let reachableAssets = [];
|
|
617
603
|
|
|
618
604
|
// ancestorAssets maps bundle roots to the set of all assets available to it at runtime,
|
|
619
605
|
// including in earlier parallel bundles. These are intersected through all paths to
|
|
620
606
|
// the bundle to ensure that the available assets are always present no matter in which
|
|
621
607
|
// order the bundles are loaded.
|
|
622
|
-
let ancestorAssets
|
|
608
|
+
let ancestorAssets = [];
|
|
623
609
|
|
|
624
610
|
let inlineConstantDeps = new DefaultMap(() => new Set());
|
|
625
611
|
|
|
@@ -848,11 +834,8 @@ export function createIdealGraph(
|
|
|
848
834
|
|
|
849
835
|
function assignInlineConstants(parentAsset: Asset, bundle: Bundle) {
|
|
850
836
|
for (let inlineConstant of inlineConstantDeps.get(parentAsset)) {
|
|
851
|
-
// @ts-expect-error TS2345
|
|
852
837
|
if (!bundle.assets.has(inlineConstant)) {
|
|
853
|
-
// @ts-expect-error TS2345
|
|
854
838
|
bundle.assets.add(inlineConstant);
|
|
855
|
-
// @ts-expect-error TS18046
|
|
856
839
|
bundle.size += inlineConstant.stats.size;
|
|
857
840
|
}
|
|
858
841
|
}
|
|
@@ -912,7 +895,7 @@ export function createIdealGraph(
|
|
|
912
895
|
let bundle;
|
|
913
896
|
let bundleId;
|
|
914
897
|
let manualSharedBundleKey = manualSharedObject.name + ',' + asset.type;
|
|
915
|
-
let sourceBundles
|
|
898
|
+
let sourceBundles = [];
|
|
916
899
|
reachable.forEach((id) => {
|
|
917
900
|
sourceBundles.push(nullthrows(bundleRoots.get(assets[id]))[0]);
|
|
918
901
|
});
|
|
@@ -1027,7 +1010,7 @@ export function createIdealGraph(
|
|
|
1027
1010
|
});
|
|
1028
1011
|
}
|
|
1029
1012
|
|
|
1030
|
-
let reachableArray
|
|
1013
|
+
let reachableArray = [];
|
|
1031
1014
|
reachable.forEach((id) => {
|
|
1032
1015
|
reachableArray.push(assets[id]);
|
|
1033
1016
|
});
|
|
@@ -1102,6 +1085,8 @@ export function createIdealGraph(
|
|
|
1102
1085
|
}
|
|
1103
1086
|
|
|
1104
1087
|
let manualSharedBundleIds = new Set([...manualSharedMap.values()]);
|
|
1088
|
+
let modifiedSourceBundles = new Set<Bundle>();
|
|
1089
|
+
|
|
1105
1090
|
// Step split manual shared bundles for those that have the "split" property set
|
|
1106
1091
|
let remainderMap = new DefaultMap(() => []);
|
|
1107
1092
|
for (let id of manualSharedMap.values()) {
|
|
@@ -1120,9 +1105,9 @@ export function createIdealGraph(
|
|
|
1120
1105
|
if (modNum != null) {
|
|
1121
1106
|
for (let a of [...manualBundle.assets]) {
|
|
1122
1107
|
let numRep = getBigIntFromContentKey(a.id);
|
|
1108
|
+
// $FlowFixMe Flow doesn't know about BigInt
|
|
1123
1109
|
let r = Number(numRep % BigInt(modNum));
|
|
1124
1110
|
|
|
1125
|
-
// @ts-expect-error TS2345
|
|
1126
1111
|
remainderMap.get(r).push(a);
|
|
1127
1112
|
}
|
|
1128
1113
|
|
|
@@ -1145,10 +1130,8 @@ export function createIdealGraph(
|
|
|
1145
1130
|
}
|
|
1146
1131
|
for (let sp of remainderMap.get(i)) {
|
|
1147
1132
|
bundle.assets.add(sp);
|
|
1148
|
-
// @ts-expect-error TS2339
|
|
1149
1133
|
bundle.size += sp.stats.size;
|
|
1150
1134
|
manualBundle.assets.delete(sp);
|
|
1151
|
-
// @ts-expect-error TS2339
|
|
1152
1135
|
manualBundle.size -= sp.stats.size;
|
|
1153
1136
|
}
|
|
1154
1137
|
}
|
|
@@ -1161,7 +1144,6 @@ export function createIdealGraph(
|
|
|
1161
1144
|
// match multiple MSB's
|
|
1162
1145
|
for (let [asset, msbs] of constantModuleToMSB.entries()) {
|
|
1163
1146
|
for (let manualSharedObject of msbs) {
|
|
1164
|
-
// @ts-expect-error TS2339
|
|
1165
1147
|
let bundleId = manualSharedMap.get(manualSharedObject.name + ',js');
|
|
1166
1148
|
if (bundleId == null) continue;
|
|
1167
1149
|
let bundle = nullthrows(bundleGraph.getNode(bundleId));
|
|
@@ -1170,16 +1152,86 @@ export function createIdealGraph(
|
|
|
1170
1152
|
'We tried to use the root incorrectly',
|
|
1171
1153
|
);
|
|
1172
1154
|
|
|
1173
|
-
// @ts-expect-error TS2345
|
|
1174
1155
|
if (!bundle.assets.has(asset)) {
|
|
1175
|
-
// @ts-expect-error TS2345
|
|
1176
1156
|
bundle.assets.add(asset);
|
|
1177
|
-
// @ts-expect-error TS18046
|
|
1178
1157
|
bundle.size += asset.stats.size;
|
|
1179
1158
|
}
|
|
1180
1159
|
}
|
|
1181
1160
|
}
|
|
1182
1161
|
|
|
1162
|
+
if (getFeatureFlag('supportWebpackChunkName')) {
|
|
1163
|
+
// Merge webpack chunk name bundles
|
|
1164
|
+
let chunkNameBundles = new DefaultMap(() => new Set());
|
|
1165
|
+
for (let [nodeId, node] of dependencyBundleGraph.nodes.entries()) {
|
|
1166
|
+
// meta.chunkName is set by the Rust transformer, so we just need to find
|
|
1167
|
+
// bundles that have a chunkName set.
|
|
1168
|
+
if (
|
|
1169
|
+
!node ||
|
|
1170
|
+
node.type !== 'dependency' ||
|
|
1171
|
+
node.value.meta.chunkName == null
|
|
1172
|
+
) {
|
|
1173
|
+
continue;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
let connectedBundles = dependencyBundleGraph.getNodeIdsConnectedFrom(
|
|
1177
|
+
nodeId,
|
|
1178
|
+
dependencyPriorityEdges[node.value.priority],
|
|
1179
|
+
);
|
|
1180
|
+
|
|
1181
|
+
if (connectedBundles.length === 0) {
|
|
1182
|
+
continue;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
invariant(
|
|
1186
|
+
connectedBundles.length === 1,
|
|
1187
|
+
'Expected webpackChunkName dependency to be connected to no more than one bundle',
|
|
1188
|
+
);
|
|
1189
|
+
|
|
1190
|
+
let bundleId = connectedBundles[0];
|
|
1191
|
+
let bundleNode = dependencyBundleGraph.getNode(bundleId);
|
|
1192
|
+
invariant(bundleNode != null && bundleNode.type === 'bundle');
|
|
1193
|
+
|
|
1194
|
+
// If a bundle does not have a main entry asset, it's somehow just a
|
|
1195
|
+
// shared bundle, and will be merged/deleted by other means.
|
|
1196
|
+
if (bundleNode.value.mainEntryAsset == null) {
|
|
1197
|
+
continue;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
let bundleNodeId = null;
|
|
1201
|
+
let mainEntryAssetId = bundleNode.value.mainEntryAsset?.id;
|
|
1202
|
+
|
|
1203
|
+
if (mainEntryAssetId != null) {
|
|
1204
|
+
bundleNodeId = bundles.get(mainEntryAssetId);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
if (bundleNodeId == null) {
|
|
1208
|
+
continue;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
chunkNameBundles
|
|
1212
|
+
.get(node.value.meta.chunkName)
|
|
1213
|
+
// DependencyBundleGraph uses content keys as node ids, so we can use that
|
|
1214
|
+
// to get the bundle id.
|
|
1215
|
+
.add(bundleNodeId);
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
for (let [chunkName, bundleIds] of chunkNameBundles.entries()) {
|
|
1219
|
+
// The `[request]` placeholder is not yet supported
|
|
1220
|
+
if (
|
|
1221
|
+
bundleIds.size <= 1 ||
|
|
1222
|
+
(typeof chunkName === 'string' && chunkName.includes('[request]'))
|
|
1223
|
+
) {
|
|
1224
|
+
continue; // Nothing to merge
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// Merge all bundles with the same chunk name into the first one.
|
|
1228
|
+
let [firstBundleId, ...rest] = Array.from(bundleIds);
|
|
1229
|
+
for (let bundleId of rest) {
|
|
1230
|
+
mergeBundles(firstBundleId, bundleId);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1183
1235
|
// Step merge shared bundles that meet the overlap threshold
|
|
1184
1236
|
// This step is skipped by default as the threshold defaults to 1
|
|
1185
1237
|
if (config.sharedBundleMerge && config.sharedBundleMerge.length > 0) {
|
|
@@ -1202,7 +1254,6 @@ export function createIdealGraph(
|
|
|
1202
1254
|
}
|
|
1203
1255
|
|
|
1204
1256
|
// Step Remove Shared Bundles: Remove shared bundles from bundle groups that hit the parallel request limit.
|
|
1205
|
-
let modifiedSourceBundles = new Set();
|
|
1206
1257
|
|
|
1207
1258
|
if (config.disableSharedBundles === false) {
|
|
1208
1259
|
for (let bundleGroupId of bundleGraph.getNodeIdsConnectedFrom(rootNodeId)) {
|
|
@@ -1216,7 +1267,6 @@ export function createIdealGraph(
|
|
|
1216
1267
|
let numBundlesContributingToPRL = bundleIdsInGroup.reduce((count, b) => {
|
|
1217
1268
|
let bundle = nullthrows(bundleGraph.getNode(b));
|
|
1218
1269
|
invariant(bundle !== 'root');
|
|
1219
|
-
// @ts-expect-error TS2365
|
|
1220
1270
|
return count + (bundle.bundleBehavior !== 'inline');
|
|
1221
1271
|
}, 0);
|
|
1222
1272
|
|
|
@@ -1252,9 +1302,7 @@ export function createIdealGraph(
|
|
|
1252
1302
|
numBundlesContributingToPRL > config.maxParallelRequests
|
|
1253
1303
|
) {
|
|
1254
1304
|
let bundleTuple = sharedBundlesInGroup.pop();
|
|
1255
|
-
// @ts-expect-error TS18048
|
|
1256
1305
|
let bundleToRemove = bundleTuple.bundle;
|
|
1257
|
-
// @ts-expect-error TS18048
|
|
1258
1306
|
let bundleIdToRemove = bundleTuple.id;
|
|
1259
1307
|
//TODO add integration test where bundles in bunlde group > max parallel request limit & only remove a couple shared bundles
|
|
1260
1308
|
// but total # bundles still exceeds limit due to non shared bundles
|
|
@@ -1310,36 +1358,49 @@ export function createIdealGraph(
|
|
|
1310
1358
|
}
|
|
1311
1359
|
}
|
|
1312
1360
|
|
|
1313
|
-
function mergeBundles(
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1361
|
+
function mergeBundles(bundleToKeepId: NodeId, bundleToRemoveId: NodeId) {
|
|
1362
|
+
let bundleToKeep = isNonRootBundle(
|
|
1363
|
+
bundleGraph.getNode(bundleToKeepId),
|
|
1364
|
+
`Bundle ${bundleToKeepId} not found`,
|
|
1365
|
+
);
|
|
1366
|
+
let bundleToRemove = isNonRootBundle(
|
|
1367
|
+
bundleGraph.getNode(bundleToRemoveId),
|
|
1368
|
+
`Bundle ${bundleToRemoveId} not found`,
|
|
1369
|
+
);
|
|
1370
|
+
modifiedSourceBundles.add(bundleToKeep);
|
|
1322
1371
|
for (let asset of bundleToRemove.assets) {
|
|
1323
1372
|
bundleToKeep.assets.add(asset);
|
|
1324
1373
|
bundleToKeep.size += asset.stats.size;
|
|
1325
1374
|
|
|
1326
1375
|
let newAssetReference = assetReference
|
|
1327
1376
|
.get(asset)
|
|
1328
|
-
.map(([dep, bundle]
|
|
1377
|
+
.map(([dep, bundle]) =>
|
|
1329
1378
|
bundle === bundleToRemove ? [dep, bundleToKeep] : [dep, bundle],
|
|
1330
1379
|
);
|
|
1331
1380
|
|
|
1332
|
-
// @ts-expect-error TS2345
|
|
1333
1381
|
assetReference.set(asset, newAssetReference);
|
|
1334
1382
|
}
|
|
1335
1383
|
|
|
1336
1384
|
// Merge any internalized assets
|
|
1337
|
-
|
|
1338
|
-
bundleToKeep.internalizedAssets
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1385
|
+
if (getFeatureFlag('supportWebpackChunkName')) {
|
|
1386
|
+
if (bundleToKeep.internalizedAssets != null) {
|
|
1387
|
+
if (bundleToRemove.internalizedAssets != null) {
|
|
1388
|
+
bundleToKeep.internalizedAssets.intersect(
|
|
1389
|
+
bundleToRemove.internalizedAssets,
|
|
1390
|
+
);
|
|
1391
|
+
} else {
|
|
1392
|
+
bundleToKeep.internalizedAssets.clear();
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
} else {
|
|
1396
|
+
invariant(
|
|
1397
|
+
bundleToKeep.internalizedAssets && bundleToRemove.internalizedAssets,
|
|
1398
|
+
'All shared bundles should have internalized assets',
|
|
1399
|
+
);
|
|
1400
|
+
bundleToKeep.internalizedAssets.union(bundleToRemove.internalizedAssets);
|
|
1401
|
+
}
|
|
1342
1402
|
|
|
1403
|
+
// Merge and clean up source bundles
|
|
1343
1404
|
for (let sourceBundleId of bundleToRemove.sourceBundles) {
|
|
1344
1405
|
if (bundleToKeep.sourceBundles.has(sourceBundleId)) {
|
|
1345
1406
|
continue;
|
|
@@ -1349,6 +1410,104 @@ export function createIdealGraph(
|
|
|
1349
1410
|
bundleGraph.addEdge(sourceBundleId, bundleToKeepId);
|
|
1350
1411
|
}
|
|
1351
1412
|
|
|
1413
|
+
if (getFeatureFlag('supportWebpackChunkName')) {
|
|
1414
|
+
bundleToKeep.sourceBundles.delete(bundleToRemoveId);
|
|
1415
|
+
|
|
1416
|
+
for (let bundle of bundleGraph.getNodeIdsConnectedFrom(
|
|
1417
|
+
bundleToRemoveId,
|
|
1418
|
+
)) {
|
|
1419
|
+
let bundleNode = nullthrows(bundleGraph.getNode(bundle));
|
|
1420
|
+
if (bundleNode === 'root') {
|
|
1421
|
+
continue;
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
// If the bundle is a source bundle, add it to the bundle to keep
|
|
1425
|
+
if (bundleNode.sourceBundles.has(bundleToRemoveId)) {
|
|
1426
|
+
bundleNode.sourceBundles.add(bundleToKeepId);
|
|
1427
|
+
bundleNode.sourceBundles.delete(bundleToRemoveId);
|
|
1428
|
+
bundleGraph.addEdge(bundleToKeepId, bundle);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
// Merge bundle roots
|
|
1433
|
+
for (let bundleRoot of bundleToRemove.bundleRoots) {
|
|
1434
|
+
bundleToKeep.bundleRoots.add(bundleRoot);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
if (bundleToRemove.mainEntryAsset != null) {
|
|
1438
|
+
invariant(bundleToKeep.mainEntryAsset != null);
|
|
1439
|
+
|
|
1440
|
+
// Merge the bundles in bundle group
|
|
1441
|
+
let bundlesInRemoveBundleGroup =
|
|
1442
|
+
getBundlesForBundleGroup(bundleToRemoveId);
|
|
1443
|
+
|
|
1444
|
+
for (let bundleIdInGroup of bundlesInRemoveBundleGroup) {
|
|
1445
|
+
if (bundleIdInGroup === bundleToRemoveId) {
|
|
1446
|
+
continue;
|
|
1447
|
+
}
|
|
1448
|
+
bundleGraph.addEdge(bundleToKeepId, bundleIdInGroup);
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// Remove old bundle group
|
|
1452
|
+
bundleGroupBundleIds.delete(bundleToRemoveId);
|
|
1453
|
+
|
|
1454
|
+
// Clean up bundle roots
|
|
1455
|
+
let bundleRootToRemoveNodeId = nullthrows(
|
|
1456
|
+
assetToBundleRootNodeId.get(
|
|
1457
|
+
nullthrows(bundleToRemove.mainEntryAsset),
|
|
1458
|
+
),
|
|
1459
|
+
);
|
|
1460
|
+
let bundleRootToKeepNodeId = nullthrows(
|
|
1461
|
+
assetToBundleRootNodeId.get(nullthrows(bundleToKeep.mainEntryAsset)),
|
|
1462
|
+
);
|
|
1463
|
+
|
|
1464
|
+
for (let nodeId of bundleRootGraph.getNodeIdsConnectedTo(
|
|
1465
|
+
bundleRootToRemoveNodeId,
|
|
1466
|
+
)) {
|
|
1467
|
+
bundleRootGraph.addEdge(nodeId, bundleRootToKeepNodeId);
|
|
1468
|
+
bundleRootGraph.removeEdge(nodeId, bundleRootToRemoveNodeId);
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
for (let nodeId of bundleRootGraph.getNodeIdsConnectedFrom(
|
|
1472
|
+
bundleRootToRemoveNodeId,
|
|
1473
|
+
)) {
|
|
1474
|
+
bundleRootGraph.addEdge(bundleRootToKeepNodeId, nodeId);
|
|
1475
|
+
bundleRootGraph.removeEdge(bundleRootToRemoveNodeId, nodeId);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
bundleRoots.set(nullthrows(bundleToRemove.mainEntryAsset), [
|
|
1479
|
+
bundleToKeepId,
|
|
1480
|
+
bundleToKeepId,
|
|
1481
|
+
]);
|
|
1482
|
+
|
|
1483
|
+
// Merge dependency bundle graph
|
|
1484
|
+
for (let dependencyNodeId of dependencyBundleGraph.getNodeIdsConnectedTo(
|
|
1485
|
+
dependencyBundleGraph.getNodeIdByContentKey(String(bundleToRemoveId)),
|
|
1486
|
+
ALL_EDGE_TYPES,
|
|
1487
|
+
)) {
|
|
1488
|
+
let dependencyNode = nullthrows(
|
|
1489
|
+
dependencyBundleGraph.getNode(dependencyNodeId),
|
|
1490
|
+
);
|
|
1491
|
+
invariant(dependencyNode.type === 'dependency');
|
|
1492
|
+
|
|
1493
|
+
// Add dependency to the bundle to keep
|
|
1494
|
+
dependencyBundleGraph.addEdge(
|
|
1495
|
+
dependencyNodeId,
|
|
1496
|
+
dependencyBundleGraph.getNodeIdByContentKey(String(bundleToKeepId)),
|
|
1497
|
+
dependencyPriorityEdges[dependencyNode.value.priority],
|
|
1498
|
+
);
|
|
1499
|
+
// Remove dependency from the bundle to remove
|
|
1500
|
+
dependencyBundleGraph.removeEdge(
|
|
1501
|
+
dependencyNodeId,
|
|
1502
|
+
dependencyBundleGraph.getNodeIdByContentKey(
|
|
1503
|
+
String(bundleToRemoveId),
|
|
1504
|
+
),
|
|
1505
|
+
dependencyPriorityEdges[dependencyNode.value.priority],
|
|
1506
|
+
);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1352
1511
|
bundleGraph.removeNode(bundleToRemoveId);
|
|
1353
1512
|
}
|
|
1354
1513
|
|
|
@@ -1382,36 +1541,43 @@ export function createIdealGraph(
|
|
|
1382
1541
|
let clusters = findMergeCandidates(
|
|
1383
1542
|
bundleGraph,
|
|
1384
1543
|
Array.from(sharedBundles),
|
|
1385
|
-
mergeConfig.map(
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
}
|
|
1544
|
+
mergeConfig.map((config): MergeGroup => ({
|
|
1545
|
+
...config,
|
|
1546
|
+
sourceBundles: config.sourceBundles?.map((assetMatch) => {
|
|
1547
|
+
let sourceBundleNodeId = mergeSourceBundleLookup.get(assetMatch);
|
|
1548
|
+
|
|
1549
|
+
if (sourceBundleNodeId == null) {
|
|
1550
|
+
throw new Error(
|
|
1551
|
+
`Source bundle ${assetMatch} not found in merge source bundle lookup`,
|
|
1552
|
+
);
|
|
1553
|
+
}
|
|
1396
1554
|
|
|
1397
|
-
|
|
1398
|
-
}),
|
|
1555
|
+
return sourceBundleNodeId;
|
|
1399
1556
|
}),
|
|
1400
|
-
),
|
|
1557
|
+
})),
|
|
1401
1558
|
);
|
|
1402
1559
|
|
|
1560
|
+
let mergedBundles = new Set();
|
|
1561
|
+
|
|
1403
1562
|
for (let cluster of clusters) {
|
|
1404
1563
|
let [mergeTarget, ...rest] = cluster;
|
|
1405
1564
|
|
|
1406
1565
|
for (let bundleIdToMerge of rest) {
|
|
1407
|
-
mergeBundles(
|
|
1566
|
+
mergeBundles(mergeTarget, bundleIdToMerge);
|
|
1408
1567
|
}
|
|
1568
|
+
|
|
1569
|
+
mergedBundles.add(mergeTarget);
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
if (getFeatureFlag('supportWebpackChunkName')) {
|
|
1573
|
+
return mergedBundles;
|
|
1409
1574
|
}
|
|
1410
1575
|
}
|
|
1411
1576
|
|
|
1412
|
-
function getBigIntFromContentKey(contentKey
|
|
1577
|
+
function getBigIntFromContentKey(contentKey) {
|
|
1413
1578
|
let b = Buffer.alloc(64);
|
|
1414
1579
|
b.write(contentKey);
|
|
1580
|
+
// $FlowFixMe Flow doesn't have BigInt types in this version
|
|
1415
1581
|
return b.readBigInt64BE();
|
|
1416
1582
|
}
|
|
1417
1583
|
// Fix asset order in source bundles as they are likely now incorrect after shared bundle deletion
|
|
@@ -1419,9 +1585,7 @@ export function createIdealGraph(
|
|
|
1419
1585
|
let assetOrderMap = new Map(assets.map((a, index) => [a, index]));
|
|
1420
1586
|
|
|
1421
1587
|
for (let bundle of modifiedSourceBundles) {
|
|
1422
|
-
// @ts-expect-error TS18046
|
|
1423
1588
|
bundle.assets = new Set(
|
|
1424
|
-
// @ts-expect-error TS18046
|
|
1425
1589
|
[...bundle.assets].sort((a, b) => {
|
|
1426
1590
|
let aIndex = nullthrows(assetOrderMap.get(a));
|
|
1427
1591
|
let bIndex = nullthrows(assetOrderMap.get(b));
|
|
@@ -1440,8 +1604,8 @@ export function createIdealGraph(
|
|
|
1440
1604
|
bundleRootGraph.removeNode(bundleRootId);
|
|
1441
1605
|
}
|
|
1442
1606
|
}
|
|
1443
|
-
function getBundlesForBundleGroup(bundleGroupId
|
|
1444
|
-
let bundlesInABundleGroup
|
|
1607
|
+
function getBundlesForBundleGroup(bundleGroupId) {
|
|
1608
|
+
let bundlesInABundleGroup = [];
|
|
1445
1609
|
bundleGraph.traverse((nodeId) => {
|
|
1446
1610
|
bundlesInABundleGroup.push(nodeId);
|
|
1447
1611
|
}, bundleGroupId);
|
|
@@ -1522,23 +1686,24 @@ export function createIdealGraph(
|
|
|
1522
1686
|
};
|
|
1523
1687
|
}
|
|
1524
1688
|
|
|
1525
|
-
function createBundle(opts: {
|
|
1526
|
-
asset?: Asset
|
|
1527
|
-
bundleBehavior?: BundleBehavior
|
|
1528
|
-
env?: Environment
|
|
1529
|
-
manualSharedBundle?: string
|
|
1530
|
-
needsStableName?: boolean
|
|
1531
|
-
sourceBundles?: Set<NodeId
|
|
1532
|
-
target: Target
|
|
1533
|
-
type?: string
|
|
1534
|
-
uniqueKey?: string
|
|
1535
|
-
}): Bundle {
|
|
1689
|
+
function createBundle(opts: {|
|
|
1690
|
+
asset?: Asset,
|
|
1691
|
+
bundleBehavior?: ?BundleBehavior,
|
|
1692
|
+
env?: Environment,
|
|
1693
|
+
manualSharedBundle?: ?string,
|
|
1694
|
+
needsStableName?: boolean,
|
|
1695
|
+
sourceBundles?: Set<NodeId>,
|
|
1696
|
+
target: Target,
|
|
1697
|
+
type?: string,
|
|
1698
|
+
uniqueKey?: string,
|
|
1699
|
+
|}): Bundle {
|
|
1536
1700
|
if (opts.asset == null) {
|
|
1537
1701
|
return {
|
|
1538
1702
|
assets: new Set(),
|
|
1539
1703
|
bundleBehavior: opts.bundleBehavior,
|
|
1540
1704
|
env: nullthrows(opts.env),
|
|
1541
1705
|
mainEntryAsset: null,
|
|
1706
|
+
bundleRoots: new Set(),
|
|
1542
1707
|
manualSharedBundle: opts.manualSharedBundle,
|
|
1543
1708
|
needsStableName: Boolean(opts.needsStableName),
|
|
1544
1709
|
size: 0,
|
|
@@ -1555,6 +1720,7 @@ function createBundle(opts: {
|
|
|
1555
1720
|
bundleBehavior: opts.bundleBehavior ?? asset.bundleBehavior,
|
|
1556
1721
|
env: opts.env ?? asset.env,
|
|
1557
1722
|
mainEntryAsset: asset,
|
|
1723
|
+
bundleRoots: new Set([asset]),
|
|
1558
1724
|
manualSharedBundle: opts.manualSharedBundle,
|
|
1559
1725
|
needsStableName: Boolean(opts.needsStableName),
|
|
1560
1726
|
size: asset.stats.size,
|