@atlaspack/bundler-default 2.12.1-dev.3478 → 2.12.1-dev.3520

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.
@@ -1,126 +1,14 @@
1
1
  // @flow strict-local
2
- import type {
3
- Asset,
4
- Bundle as LegacyBundle,
5
- BundleBehavior,
6
- BundleGroup,
7
- Dependency,
8
- Environment,
9
- Config,
10
- MutableBundleGraph,
11
- PluginOptions,
12
- Target,
13
- BuildMode,
14
- PluginLogger,
15
- } from '@atlaspack/types';
16
- import type {NodeId} from '@atlaspack/graph';
17
- import type {SchemaEntity} from '@atlaspack/utils';
18
- import {ContentGraph, Graph, BitSet, ALL_EDGE_TYPES} from '@atlaspack/graph';
19
2
 
20
- import invariant from 'assert';
21
3
  import {Bundler} from '@atlaspack/plugin';
22
- import {validateSchema, DefaultMap, globToRegex} from '@atlaspack/utils';
23
- import nullthrows from 'nullthrows';
24
- import path from 'path';
25
- import {encodeJSONKeyComponent} from '@atlaspack/diagnostic';
26
- import {getFeatureFlag} from '@atlaspack/feature-flags';
27
-
28
- type Glob = string;
29
-
30
- type ManualSharedBundles = Array<{|
31
- name: string,
32
- assets: Array<Glob>,
33
- types?: Array<string>,
34
- root?: string,
35
- split?: number,
36
- |}>;
37
-
38
- type BaseBundlerConfig = {|
39
- http?: number,
40
- minBundles?: number,
41
- minBundleSize?: number,
42
- maxParallelRequests?: number,
43
- disableSharedBundles?: boolean,
44
- manualSharedBundles?: ManualSharedBundles,
45
- |};
46
-
47
- type BundlerConfig = {|
48
- [mode: BuildMode]: BaseBundlerConfig,
49
- |} & BaseBundlerConfig;
50
-
51
- type ResolvedBundlerConfig = {|
52
- minBundles: number,
53
- minBundleSize: number,
54
- maxParallelRequests: number,
55
- projectRoot: string,
56
- disableSharedBundles: boolean,
57
- manualSharedBundles: ManualSharedBundles,
58
- |};
59
-
60
- // Default options by http version.
61
- const HTTP_OPTIONS = {
62
- '1': {
63
- minBundles: 1,
64
- manualSharedBundles: [],
65
- minBundleSize: 30000,
66
- maxParallelRequests: 6,
67
- disableSharedBundles: false,
68
- },
69
- '2': {
70
- minBundles: 1,
71
- manualSharedBundles: [],
72
- minBundleSize: 20000,
73
- maxParallelRequests: 25,
74
- disableSharedBundles: false,
75
- },
76
- };
77
-
78
- /* BundleRoot - An asset that is the main entry of a Bundle. */
79
- type BundleRoot = Asset;
80
- export type Bundle = {|
81
- uniqueKey: ?string,
82
- assets: Set<Asset>,
83
- internalizedAssets?: BitSet,
84
- bundleBehavior?: ?BundleBehavior,
85
- needsStableName: boolean,
86
- mainEntryAsset: ?Asset,
87
- size: number,
88
- sourceBundles: Set<NodeId>,
89
- target: Target,
90
- env: Environment,
91
- type: string,
92
- manualSharedBundle: ?string, // for naming purposes
93
- |};
94
-
95
- const dependencyPriorityEdges = {
96
- sync: 1,
97
- parallel: 2,
98
- lazy: 3,
99
- conditional: 4,
100
- };
4
+ import type {Asset, Dependency, MutableBundleGraph} from '@atlaspack/types';
5
+ import {DefaultMap} from '@atlaspack/utils';
6
+ import invariant from 'assert';
101
7
 
102
- type DependencyBundleGraph = ContentGraph<
103
- | {|
104
- value: Bundle,
105
- type: 'bundle',
106
- |}
107
- | {|
108
- value: Dependency,
109
- type: 'dependency',
110
- |},
111
- number,
112
- >;
113
- // IdealGraph is the structure we will pass to decorate,
114
- // which mutates the assetGraph into the bundleGraph we would
115
- // expect from default bundler
116
- type IdealGraph = {|
117
- assets: Array<Asset>,
118
- dependencyBundleGraph: DependencyBundleGraph,
119
- bundleGraph: Graph<Bundle | 'root'>,
120
- bundleGroupBundleIds: Set<NodeId>,
121
- assetReference: DefaultMap<Asset, Array<[Dependency, Bundle]>>,
122
- manualAssetToBundle: Map<Asset, NodeId>,
123
- |};
8
+ import {loadBundlerConfig} from './bundlerConfig';
9
+ import {decorateLegacyGraph} from './decorateLegacyGraph';
10
+ import {createIdealGraph} from './idealGraph';
11
+ import {addJSMonolithBundle} from './MonolithicBundler';
124
12
 
125
13
  /**
126
14
  *
@@ -145,1677 +33,38 @@ export default (new Bundler({
145
33
  bundle({bundleGraph, config, logger}) {
146
34
  let targetMap = getEntryByTarget(bundleGraph); // Organize entries by target output folder/ distDir
147
35
  let graphs = [];
148
- for (let entries of targetMap.values()) {
149
- // Create separate bundleGraphs per distDir
150
- graphs.push(createIdealGraph(bundleGraph, config, entries, logger));
151
- }
152
- for (let g of graphs) {
153
- decorateLegacyGraph(g, bundleGraph); //mutate original graph
154
- }
155
- },
156
- optimize() {},
157
- }): Bundler);
158
-
159
- function decorateLegacyGraph(
160
- idealGraph: IdealGraph,
161
- bundleGraph: MutableBundleGraph,
162
- ): void {
163
- let idealBundleToLegacyBundle: Map<Bundle, LegacyBundle> = new Map();
164
-
165
- let {
166
- bundleGraph: idealBundleGraph,
167
- dependencyBundleGraph,
168
- bundleGroupBundleIds,
169
- manualAssetToBundle,
170
- } = idealGraph;
171
- let entryBundleToBundleGroup: Map<NodeId, BundleGroup> = new Map();
172
- // Step Create Bundles: Create bundle groups, bundles, and shared bundles and add assets to them
173
- for (let [bundleNodeId, idealBundle] of idealBundleGraph.nodes.entries()) {
174
- if (!idealBundle || idealBundle === 'root') continue;
175
- let entryAsset = idealBundle.mainEntryAsset;
176
- let bundleGroups = [];
177
- let bundleGroup;
178
- let bundle;
179
-
180
- if (bundleGroupBundleIds.has(bundleNodeId)) {
181
- invariant(
182
- idealBundle.manualSharedBundle == null,
183
- 'Unstable Manual Shared Bundle feature is processing a manualSharedBundle as a BundleGroup',
184
- );
185
- let dependencies = dependencyBundleGraph
186
- .getNodeIdsConnectedTo(
187
- dependencyBundleGraph.getNodeIdByContentKey(String(bundleNodeId)),
188
- ALL_EDGE_TYPES,
189
- )
190
- .map((nodeId) => {
191
- let dependency = nullthrows(dependencyBundleGraph.getNode(nodeId));
192
- invariant(dependency.type === 'dependency');
193
- return dependency.value;
194
- });
195
- invariant(
196
- entryAsset != null,
197
- 'Processing a bundleGroup with no entry asset',
198
- );
199
- for (let dependency of dependencies) {
200
- bundleGroup = bundleGraph.createBundleGroup(
201
- dependency,
202
- idealBundle.target,
203
- );
204
- bundleGroups.push(bundleGroup);
205
- }
206
- invariant(bundleGroup);
207
- entryBundleToBundleGroup.set(bundleNodeId, bundleGroup);
208
-
209
- bundle = nullthrows(
210
- bundleGraph.createBundle({
211
- entryAsset: nullthrows(entryAsset),
212
- needsStableName: idealBundle.needsStableName,
213
- bundleBehavior: idealBundle.bundleBehavior,
214
- target: idealBundle.target,
215
- manualSharedBundle: idealBundle.manualSharedBundle,
216
- }),
217
- );
218
-
219
- bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
220
- } else if (
221
- idealBundle.sourceBundles.size > 0 &&
222
- !idealBundle.mainEntryAsset
223
- ) {
224
- let uniqueKey =
225
- idealBundle.uniqueKey != null
226
- ? idealBundle.uniqueKey
227
- : [...idealBundle.assets].map((asset) => asset.id).join(',');
228
-
229
- bundle = nullthrows(
230
- bundleGraph.createBundle({
231
- uniqueKey,
232
- needsStableName: idealBundle.needsStableName,
233
- bundleBehavior: idealBundle.bundleBehavior,
234
- type: idealBundle.type,
235
- target: idealBundle.target,
236
- env: idealBundle.env,
237
- manualSharedBundle: idealBundle.manualSharedBundle,
238
- }),
239
- );
240
- } else if (idealBundle.uniqueKey != null) {
241
- bundle = nullthrows(
242
- bundleGraph.createBundle({
243
- uniqueKey: idealBundle.uniqueKey,
244
- needsStableName: idealBundle.needsStableName,
245
- bundleBehavior: idealBundle.bundleBehavior,
246
- type: idealBundle.type,
247
- target: idealBundle.target,
248
- env: idealBundle.env,
249
- manualSharedBundle: idealBundle.manualSharedBundle,
250
- }),
251
- );
252
- } else {
253
- invariant(entryAsset != null);
254
- bundle = nullthrows(
255
- bundleGraph.createBundle({
256
- entryAsset,
257
- needsStableName: idealBundle.needsStableName,
258
- bundleBehavior: idealBundle.bundleBehavior,
259
- target: idealBundle.target,
260
- manualSharedBundle: idealBundle.manualSharedBundle,
261
- }),
262
- );
263
- }
264
-
265
- idealBundleToLegacyBundle.set(idealBundle, bundle);
266
-
267
- for (let asset of idealBundle.assets) {
268
- bundleGraph.addAssetToBundle(asset, bundle);
269
- }
270
- }
271
- // Step Internalization: Internalize dependencies for bundles
272
- for (let idealBundle of idealBundleGraph.nodes) {
273
- if (!idealBundle || idealBundle === 'root') continue;
274
- let bundle = nullthrows(idealBundleToLegacyBundle.get(idealBundle));
275
- if (idealBundle.internalizedAssets) {
276
- idealBundle.internalizedAssets.forEach((internalized) => {
277
- let incomingDeps = bundleGraph.getIncomingDependencies(
278
- idealGraph.assets[internalized],
279
- );
280
- for (let incomingDep of incomingDeps) {
281
- if (
282
- incomingDep.priority === 'lazy' &&
283
- incomingDep.specifierType !== 'url' &&
284
- bundle.hasDependency(incomingDep)
285
- ) {
286
- bundleGraph.internalizeAsyncDependency(bundle, incomingDep);
287
- }
288
- }
289
- });
290
- }
291
- }
292
- // Unstable Manual Shared Bundles
293
- // NOTE: This only works under the assumption that manual shared bundles would have
294
- // always already been loaded before the bundle that requires internalization.
295
- for (let manualSharedAsset of manualAssetToBundle.keys()) {
296
- let incomingDeps = bundleGraph.getIncomingDependencies(manualSharedAsset);
297
- for (let incomingDep of incomingDeps) {
298
- if (
299
- incomingDep.priority === 'lazy' &&
300
- incomingDep.specifierType !== 'url'
301
- ) {
302
- let bundles = bundleGraph.getBundlesWithDependency(incomingDep);
303
- for (let bundle of bundles) {
304
- bundleGraph.internalizeAsyncDependency(bundle, incomingDep);
305
- }
306
- }
307
- }
308
- }
309
-
310
- // Step Add to BundleGroups: Add bundles to their bundle groups
311
- idealBundleGraph.traverse((nodeId, _, actions) => {
312
- let node = idealBundleGraph.getNode(nodeId);
313
- if (node === 'root') {
314
- return;
315
- }
316
- actions.skipChildren();
317
-
318
- let outboundNodeIds = idealBundleGraph.getNodeIdsConnectedFrom(nodeId);
319
- let entryBundle = nullthrows(idealBundleGraph.getNode(nodeId));
320
- invariant(entryBundle !== 'root');
321
- let legacyEntryBundle = nullthrows(
322
- idealBundleToLegacyBundle.get(entryBundle),
323
- );
324
-
325
- for (let id of outboundNodeIds) {
326
- let siblingBundle = nullthrows(idealBundleGraph.getNode(id));
327
- invariant(siblingBundle !== 'root');
328
- let legacySiblingBundle = nullthrows(
329
- idealBundleToLegacyBundle.get(siblingBundle),
330
- );
331
- bundleGraph.createBundleReference(legacyEntryBundle, legacySiblingBundle);
332
- }
333
- });
334
-
335
- // Step References: Add references to all bundles
336
- for (let [asset, references] of idealGraph.assetReference) {
337
- for (let [dependency, bundle] of references) {
338
- let legacyBundle = nullthrows(idealBundleToLegacyBundle.get(bundle));
339
- bundleGraph.createAssetReference(dependency, asset, legacyBundle);
340
- }
341
- }
342
-
343
- for (let {from, to} of idealBundleGraph.getAllEdges()) {
344
- let sourceBundle = nullthrows(idealBundleGraph.getNode(from));
345
- if (sourceBundle === 'root') {
346
- continue;
347
- }
348
- invariant(sourceBundle !== 'root');
349
-
350
- let legacySourceBundle = nullthrows(
351
- idealBundleToLegacyBundle.get(sourceBundle),
352
- );
353
-
354
- let targetBundle = nullthrows(idealBundleGraph.getNode(to));
355
- if (targetBundle === 'root') {
356
- continue;
357
- }
358
- invariant(targetBundle !== 'root');
359
- let legacyTargetBundle = nullthrows(
360
- idealBundleToLegacyBundle.get(targetBundle),
361
- );
362
- bundleGraph.createBundleReference(legacySourceBundle, legacyTargetBundle);
363
- }
364
- }
365
-
366
- function createIdealGraph(
367
- assetGraph: MutableBundleGraph,
368
- config: ResolvedBundlerConfig,
369
- entries: Map<Asset, Dependency>,
370
- logger: PluginLogger,
371
- ): IdealGraph {
372
- // Asset to the bundle and group it's an entry of
373
- let bundleRoots: Map<BundleRoot, [NodeId, NodeId]> = new Map();
374
- let bundles: Map<string, NodeId> = new Map();
375
- let dependencyBundleGraph: DependencyBundleGraph = new ContentGraph();
376
- let assetReference: DefaultMap<
377
- Asset,
378
- Array<[Dependency, Bundle]>,
379
- > = new DefaultMap(() => []);
380
-
381
- // A Graph of Bundles and a root node (dummy string), which models only Bundles, and connections to their
382
- // referencing Bundle. There are no actual BundleGroup nodes, just bundles that take on that role.
383
- let bundleGraph: Graph<Bundle | 'root'> = new Graph();
384
- let stack: Array<[BundleRoot, NodeId]> = [];
385
-
386
- let bundleRootEdgeTypes = {
387
- parallel: 1,
388
- lazy: 2,
389
- };
390
- // Graph that models bundleRoots, with parallel & async deps only to inform reachability
391
- let bundleRootGraph: Graph<
392
- number, // asset index
393
- $Values<typeof bundleRootEdgeTypes>,
394
- > = new Graph();
395
- let assetToBundleRootNodeId = new Map<BundleRoot, number>();
396
-
397
- let bundleGroupBundleIds: Set<NodeId> = new Set();
398
-
399
- let bundleGraphRootNodeId = nullthrows(bundleGraph.addNode('root'));
400
- bundleGraph.setRootNodeId(bundleGraphRootNodeId);
401
- // Step Create Entry Bundles
402
- for (let [asset, dependency] of entries) {
403
- let bundle = createBundle({
404
- asset,
405
- target: nullthrows(dependency.target),
406
- needsStableName: dependency.isEntry,
407
- });
408
- let nodeId = bundleGraph.addNode(bundle);
409
- bundles.set(asset.id, nodeId);
410
- bundleRoots.set(asset, [nodeId, nodeId]);
411
- bundleGraph.addEdge(bundleGraphRootNodeId, nodeId);
412
-
413
- dependencyBundleGraph.addEdge(
414
- dependencyBundleGraph.addNodeByContentKeyIfNeeded(dependency.id, {
415
- value: dependency,
416
- type: 'dependency',
417
- }),
418
- dependencyBundleGraph.addNodeByContentKeyIfNeeded(String(nodeId), {
419
- value: bundle,
420
- type: 'bundle',
421
- }),
422
- dependencyPriorityEdges[dependency.priority],
423
- );
424
- bundleGroupBundleIds.add(nodeId);
425
- }
426
-
427
- let assets = [];
428
- let assetToIndex = new Map<Asset, number>();
429
-
430
- function makeManualAssetToConfigLookup() {
431
- let manualAssetToConfig = new Map();
432
- let constantModuleToMSB = new DefaultMap(() => []);
433
-
434
- if (config.manualSharedBundles.length === 0) {
435
- return {manualAssetToConfig, constantModuleToMSB};
436
- }
437
-
438
- let parentsToConfig = new DefaultMap(() => []);
439
-
440
- for (let c of config.manualSharedBundles) {
441
- if (c.root != null) {
442
- parentsToConfig.get(path.join(config.projectRoot, c.root)).push(c);
443
- }
444
- }
445
- let numParentsToFind = parentsToConfig.size;
446
- let configToParentAsset = new Map();
447
-
448
- assetGraph.traverse((node, _, actions) => {
449
- if (node.type === 'asset' && parentsToConfig.has(node.value.filePath)) {
450
- for (let c of parentsToConfig.get(node.value.filePath)) {
451
- configToParentAsset.set(c, node.value);
452
- }
453
-
454
- numParentsToFind--;
455
-
456
- if (numParentsToFind === 0) {
457
- // If we've found all parents we can stop traversal
458
- actions.stop();
459
- }
460
- }
461
- });
462
-
463
- // Process in reverse order so earlier configs take precedence
464
- for (let c of config.manualSharedBundles.reverse()) {
465
- if (c.root != null && !configToParentAsset.has(c)) {
466
- logger.warn({
467
- origin: '@atlaspack/bundler-default',
468
- message: `Manual shared bundle "${c.name}" skipped, no root asset found`,
469
- });
470
- continue;
471
- }
472
-
473
- let parentAsset = configToParentAsset.get(c);
474
- let assetRegexes = c.assets.map((glob) => globToRegex(glob));
475
-
476
- assetGraph.traverse((node, _, actions) => {
477
- if (
478
- node.type === 'asset' &&
479
- (!Array.isArray(c.types) || c.types.includes(node.value.type))
480
- ) {
481
- let projectRelativePath = path.relative(
482
- config.projectRoot,
483
- node.value.filePath,
484
- );
485
- if (!assetRegexes.some((regex) => regex.test(projectRelativePath))) {
486
- return;
487
- }
488
-
489
- // We track all matching MSB's for constant modules as they are never duplicated
490
- // and need to be assigned to all matching bundles
491
- if (node.value.meta.isConstantModule === true) {
492
- constantModuleToMSB.get(node.value).push(c);
493
- }
494
- manualAssetToConfig.set(node.value, c);
495
- return;
496
- }
497
-
498
- if (
499
- node.type === 'dependency' &&
500
- (node.value.priority === 'lazy' ||
501
- (getFeatureFlag('conditionalBundlingApi') &&
502
- node.value.priority === 'conditional')) &&
503
- parentAsset
504
- ) {
505
- // Don't walk past the bundle group assets
506
- actions.skipChildren();
507
- }
508
- }, parentAsset);
509
- }
510
-
511
- return {manualAssetToConfig, constantModuleToMSB};
512
- }
513
-
514
- //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
515
- let manualSharedMap: Map<string, NodeId> = new Map();
516
- // May need a map to be able to look up NON- bundle root assets which need special case instructions
517
- // Use this when placing assets into bundles, to avoid duplication
518
- let manualAssetToBundle: Map<Asset, NodeId> = new Map();
519
- let {manualAssetToConfig, constantModuleToMSB} =
520
- makeManualAssetToConfigLookup();
521
- let manualBundleToInternalizedAsset: DefaultMap<
522
- NodeId,
523
- Array<Asset>,
524
- > = new DefaultMap(() => []);
525
-
526
- /**
527
- * Step Create Bundles: Traverse the assetGraph (aka MutableBundleGraph) and create bundles
528
- * for asset type changes, parallel, inline, and async or lazy dependencies,
529
- * adding only that asset to each bundle, not its entire subgraph.
530
- */
531
- assetGraph.traverse(
532
- {
533
- enter(node, context, actions) {
534
- if (node.type === 'asset') {
535
- if (
536
- context?.type === 'dependency' &&
537
- context?.value.isEntry &&
538
- !entries.has(node.value)
539
- ) {
540
- // Skip whole subtrees of other targets by skipping those entries
541
- actions.skipChildren();
542
- return node;
543
- }
544
- assetToIndex.set(node.value, assets.length);
545
- assets.push(node.value);
546
-
547
- let bundleIdTuple = bundleRoots.get(node.value);
548
- if (bundleIdTuple && bundleIdTuple[0] === bundleIdTuple[1]) {
549
- // Push to the stack (only) when a new bundle is created
550
- stack.push([node.value, bundleIdTuple[0]]);
551
- } else if (bundleIdTuple) {
552
- // Otherwise, push on the last bundle that marks the start of a BundleGroup
553
- stack.push([node.value, stack[stack.length - 1][1]]);
554
- }
555
- } else if (node.type === 'dependency') {
556
- if (context == null) {
557
- return node;
558
- }
559
- let dependency = node.value;
560
-
561
- invariant(context?.type === 'asset');
562
-
563
- let assets = assetGraph.getDependencyAssets(dependency);
564
- if (assets.length === 0) {
565
- return node;
566
- }
567
-
568
- for (let childAsset of assets) {
569
- let bundleId = bundles.get(childAsset.id);
570
- let bundle;
571
-
572
- // MSB Step 1: Match glob on filepath and type for any asset
573
- let manualSharedBundleKey;
574
- let manualSharedObject = manualAssetToConfig.get(childAsset);
575
-
576
- if (manualSharedObject) {
577
- // MSB Step 2: Generate a key for which to look up this manual bundle with
578
- manualSharedBundleKey =
579
- manualSharedObject.name + ',' + childAsset.type;
580
- }
581
-
582
- if (
583
- // MSB Step 3: If a bundle for these globs already exists, use it
584
- manualSharedBundleKey != null &&
585
- manualSharedMap.has(manualSharedBundleKey)
586
- ) {
587
- bundleId = nullthrows(manualSharedMap.get(manualSharedBundleKey));
588
- }
589
- if (
590
- dependency.priority === 'lazy' ||
591
- (getFeatureFlag('conditionalBundlingApi') &&
592
- node.value.priority === 'conditional') ||
593
- childAsset.bundleBehavior === 'isolated' // An isolated Dependency, or Bundle must contain all assets it needs to load.
594
- ) {
595
- if (bundleId == null) {
596
- let firstBundleGroup = nullthrows(
597
- bundleGraph.getNode(stack[0][1]),
598
- );
599
- invariant(firstBundleGroup !== 'root');
600
- bundle = createBundle({
601
- asset: childAsset,
602
- target: firstBundleGroup.target,
603
- needsStableName:
604
- dependency.bundleBehavior === 'inline' ||
605
- childAsset.bundleBehavior === 'inline'
606
- ? false
607
- : dependency.isEntry || dependency.needsStableName,
608
- bundleBehavior:
609
- dependency.bundleBehavior ?? childAsset.bundleBehavior,
610
- });
611
- bundleId = bundleGraph.addNode(bundle);
612
- bundles.set(childAsset.id, bundleId);
613
- bundleRoots.set(childAsset, [bundleId, bundleId]);
614
- bundleGroupBundleIds.add(bundleId);
615
- bundleGraph.addEdge(bundleGraphRootNodeId, bundleId);
616
- if (manualSharedObject) {
617
- // MSB Step 4: If this was the first instance of a match, mark mainAsset for internalization
618
- // since MSBs should not have main entry assets
619
- manualBundleToInternalizedAsset
620
- .get(bundleId)
621
- .push(childAsset);
622
- }
623
- } else {
624
- bundle = nullthrows(bundleGraph.getNode(bundleId));
625
- invariant(bundle !== 'root');
626
-
627
- if (
628
- // If this dependency requests isolated, but the bundle is not,
629
- // make the bundle isolated for all uses.
630
- dependency.bundleBehavior === 'isolated' &&
631
- bundle.bundleBehavior == null
632
- ) {
633
- bundle.bundleBehavior = dependency.bundleBehavior;
634
- }
635
- }
636
-
637
- dependencyBundleGraph.addEdge(
638
- dependencyBundleGraph.addNodeByContentKeyIfNeeded(
639
- dependency.id,
640
- {
641
- value: dependency,
642
- type: 'dependency',
643
- },
644
- ),
645
- dependencyBundleGraph.addNodeByContentKeyIfNeeded(
646
- String(bundleId),
647
- {
648
- value: bundle,
649
- type: 'bundle',
650
- },
651
- ),
652
- dependencyPriorityEdges[dependency.priority],
653
- );
654
- } else if (
655
- dependency.priority === 'parallel' ||
656
- childAsset.bundleBehavior === 'inline'
657
- ) {
658
- // The referencing bundleRoot is the root of a Bundle that first brings in another bundle (essentially the FIRST parent of a bundle, this may or may not be a bundleGroup)
659
- let [referencingBundleRoot, bundleGroupNodeId] = nullthrows(
660
- stack[stack.length - 1],
661
- );
662
- let bundleGroup = nullthrows(
663
- bundleGraph.getNode(bundleGroupNodeId),
664
- );
665
- invariant(bundleGroup !== 'root');
666
-
667
- let referencingBundleId = nullthrows(
668
- bundleRoots.get(referencingBundleRoot),
669
- )[0];
670
- let referencingBundle = nullthrows(
671
- bundleGraph.getNode(referencingBundleId),
672
- );
673
- invariant(referencingBundle !== 'root');
674
-
675
- if (bundleId == null) {
676
- bundle = createBundle({
677
- // Bundles created from type changes shouldn't have an entry asset.
678
- asset: childAsset,
679
- type: childAsset.type,
680
- env: childAsset.env,
681
- bundleBehavior:
682
- dependency.bundleBehavior ?? childAsset.bundleBehavior,
683
- target: referencingBundle.target,
684
- needsStableName:
685
- childAsset.bundleBehavior === 'inline' ||
686
- dependency.bundleBehavior === 'inline' ||
687
- (dependency.priority === 'parallel' &&
688
- !dependency.needsStableName)
689
- ? false
690
- : referencingBundle.needsStableName,
691
- });
692
- bundleId = bundleGraph.addNode(bundle);
693
- } else {
694
- bundle = bundleGraph.getNode(bundleId);
695
- invariant(bundle != null && bundle !== 'root');
696
-
697
- if (
698
- // If this dependency requests isolated, but the bundle is not,
699
- // make the bundle isolated for all uses.
700
- dependency.bundleBehavior === 'isolated' &&
701
- bundle.bundleBehavior == null
702
- ) {
703
- bundle.bundleBehavior = dependency.bundleBehavior;
704
- }
705
- }
706
-
707
- bundles.set(childAsset.id, bundleId);
708
-
709
- // A bundle can belong to multiple bundlegroups, all the bundle groups of it's
710
- // ancestors, and all async and entry bundles before it are "bundle groups"
711
- // TODO: We may need to track bundles to all bundleGroups it belongs to in the future.
712
- bundleRoots.set(childAsset, [bundleId, bundleGroupNodeId]);
713
- bundleGraph.addEdge(referencingBundleId, bundleId);
714
-
715
- if (bundleId != bundleGroupNodeId) {
716
- dependencyBundleGraph.addEdge(
717
- dependencyBundleGraph.addNodeByContentKeyIfNeeded(
718
- dependency.id,
719
- {
720
- value: dependency,
721
- type: 'dependency',
722
- },
723
- ),
724
- dependencyBundleGraph.addNodeByContentKeyIfNeeded(
725
- String(bundleId),
726
- {
727
- value: bundle,
728
- type: 'bundle',
729
- },
730
- ),
731
- dependencyPriorityEdges.parallel,
732
- );
733
- }
734
-
735
- assetReference.get(childAsset).push([dependency, bundle]);
736
- } else {
737
- bundleId = null;
738
- }
739
- if (manualSharedObject && bundleId != null) {
740
- // MSB Step 5: At this point we've either created or found an existing MSB bundle
741
- // add the asset if it doesn't already have it and set key
742
-
743
- invariant(
744
- bundle !== 'root' && bundle != null && bundleId != null,
745
- );
746
-
747
- manualAssetToBundle.set(childAsset, bundleId);
748
-
749
- if (!bundle.assets.has(childAsset)) {
750
- // Add asset to bundle
751
- bundle.assets.add(childAsset);
752
- bundle.size += childAsset.stats.size;
753
- }
754
-
755
- bundles.set(childAsset.id, bundleId);
756
- bundleRoots.set(childAsset, [bundleId, bundleId]);
757
-
758
- invariant(manualSharedBundleKey != null);
759
- // Ensure we set key to BundleId so the next glob match uses the appropriate bundle
760
- if (!manualSharedMap.has(manualSharedBundleKey)) {
761
- manualSharedMap.set(manualSharedBundleKey, bundleId);
762
- }
763
- bundle.manualSharedBundle = manualSharedObject.name;
764
- bundle.uniqueKey = manualSharedObject.name + childAsset.type;
765
- }
766
- }
767
- }
768
- return node;
769
- },
770
- exit(node) {
771
- if (stack[stack.length - 1]?.[0] === node.value) {
772
- stack.pop();
773
- }
774
- },
775
- },
776
- null,
777
- {skipUnusedDependencies: true},
778
- );
779
-
780
- // Strip MSBs of entries
781
- for (let [
782
- nodeId,
783
- internalizedAssets,
784
- ] of manualBundleToInternalizedAsset.entries()) {
785
- let bundle = bundleGraph.getNode(nodeId);
786
- invariant(bundle != null && bundle !== 'root');
787
-
788
- if (!bundle.internalizedAssets) {
789
- bundle.internalizedAssets = new BitSet(assets.length);
790
- }
791
- for (let asset of internalizedAssets) {
792
- bundle.internalizedAssets.add(nullthrows(assetToIndex.get(asset)));
793
- }
794
- bundle.mainEntryAsset = null;
795
- bundleGroupBundleIds.delete(nodeId); // manual bundles can now act as shared, non-bundle group, should they be non-bundleRoots as well?
796
- }
797
-
798
- /**
799
- * Step Determine Reachability: Determine reachability for every asset from each bundleRoot.
800
- * This is later used to determine which bundles to place each asset in. We build up two
801
- * structures, one traversal each. ReachableRoots to store sync relationships,
802
- * and bundleRootGraph to store the minimal availability through `parallel` and `async` relationships.
803
- * The two graphs, are used to build up ancestorAssets, a structure which holds all availability by
804
- * all means for each asset.
805
- */
806
- let rootNodeId = bundleRootGraph.addNode(-1);
807
- bundleRootGraph.setRootNodeId(rootNodeId);
808
-
809
- for (let [root] of bundleRoots) {
810
- let nodeId = bundleRootGraph.addNode(nullthrows(assetToIndex.get(root)));
811
- assetToBundleRootNodeId.set(root, nodeId);
812
- if (entries.has(root)) {
813
- bundleRootGraph.addEdge(rootNodeId, nodeId);
814
- }
815
- }
816
-
817
- // reachableRoots is an array of bit sets for each asset. Each bit set
818
- // indicates which bundle roots are reachable from that asset synchronously.
819
- let reachableRoots = [];
820
- for (let i = 0; i < assets.length; i++) {
821
- reachableRoots.push(new BitSet(bundleRootGraph.nodes.length));
822
- }
823
-
824
- // reachableAssets is the inverse mapping of reachableRoots. For each bundle root,
825
- // it contains a bit set that indicates which assets are reachable from it.
826
- let reachableAssets = [];
827
-
828
- // ancestorAssets maps bundle roots to the set of all assets available to it at runtime,
829
- // including in earlier parallel bundles. These are intersected through all paths to
830
- // the bundle to ensure that the available assets are always present no matter in which
831
- // order the bundles are loaded.
832
- let ancestorAssets = [];
833
-
834
- let inlineConstantDeps = new DefaultMap(() => new Set());
835
-
836
- for (let [bundleRootId, assetId] of bundleRootGraph.nodes.entries()) {
837
- let reachable = new BitSet(assets.length);
838
- reachableAssets.push(reachable);
839
- ancestorAssets.push(null);
840
-
841
- if (bundleRootId == rootNodeId || assetId == null) continue;
842
- // Add sync relationships to ReachableRoots
843
- let root = assets[assetId];
844
- assetGraph.traverse(
845
- (node, _, actions) => {
846
- if (node.value === root) {
847
- return;
848
- }
849
- if (node.type === 'dependency') {
850
- let dependency = node.value;
851
-
852
- if (
853
- dependency.priority !== 'sync' &&
854
- dependencyBundleGraph.hasContentKey(dependency.id)
855
- ) {
856
- let assets = assetGraph.getDependencyAssets(dependency);
857
- if (assets.length === 0) {
858
- return;
859
- }
860
- invariant(assets.length === 1);
861
- let bundleRoot = assets[0];
862
- let bundle = nullthrows(
863
- bundleGraph.getNode(nullthrows(bundles.get(bundleRoot.id))),
864
- );
865
- if (
866
- bundle !== 'root' &&
867
- bundle.bundleBehavior == null &&
868
- !bundle.env.isIsolated() &&
869
- bundle.env.context === root.env.context
870
- ) {
871
- bundleRootGraph.addEdge(
872
- bundleRootId,
873
- nullthrows(assetToBundleRootNodeId.get(bundleRoot)),
874
- dependency.priority === 'parallel'
875
- ? bundleRootEdgeTypes.parallel
876
- : bundleRootEdgeTypes.lazy,
877
- );
878
- }
879
- }
880
-
881
- if (dependency.priority !== 'sync') {
882
- actions.skipChildren();
883
- }
884
- return;
885
- }
886
- //asset node type
887
- let asset = node.value;
888
- if (asset.bundleBehavior != null) {
889
- actions.skipChildren();
890
- return;
891
- }
892
- let assetIndex = nullthrows(assetToIndex.get(node.value));
893
- reachable.add(assetIndex);
894
- reachableRoots[assetIndex].add(bundleRootId);
895
-
896
- if (asset.meta.isConstantModule === true) {
897
- let parents = assetGraph
898
- .getIncomingDependencies(asset)
899
- .map((dep) => nullthrows(assetGraph.getAssetWithDependency(dep)));
900
-
901
- for (let parent of parents) {
902
- inlineConstantDeps.get(parent).add(asset);
903
- }
904
- }
905
-
906
- return;
907
- },
908
- root,
909
- {skipUnusedDependencies: true},
910
- );
911
- }
912
-
913
- for (let entry of entries.keys()) {
914
- // Initialize an empty set of ancestors available to entries
915
- let entryId = nullthrows(assetToBundleRootNodeId.get(entry));
916
- ancestorAssets[entryId] = new BitSet(assets.length);
917
- }
918
-
919
- // Step Determine Availability
920
- // Visit nodes in a topological order, visiting parent nodes before child nodes.
921
-
922
- // This allows us to construct an understanding of which assets will already be
923
- // loaded and available when a bundle runs, by pushing available assets downwards and
924
- // computing the intersection of assets available through all possible paths to a bundle.
925
- // We call this structure ancestorAssets, a Map that tracks a bundleRoot,
926
- // to all assets available to it (meaning they will exist guaranteed when the bundleRoot is loaded)
927
- // The topological sort ensures all parents are visited before the node we want to process.
928
- for (let nodeId of bundleRootGraph.topoSort(ALL_EDGE_TYPES)) {
929
- if (nodeId === rootNodeId) continue;
930
- const bundleRoot = assets[nullthrows(bundleRootGraph.getNode(nodeId))];
931
- let bundleGroupId = nullthrows(bundleRoots.get(bundleRoot))[1];
932
36
 
933
- // At a BundleRoot, we access it's available assets (via ancestorAssets),
934
- // and add to that all assets within the bundles in that BundleGroup.
935
-
936
- // This set is available to all bundles in a particular bundleGroup because
937
- // bundleGroups are just bundles loaded at the same time. However it is
938
- // not true that a bundle's available assets = all assets of all the bundleGroups
939
- // it belongs to. It's the intersection of those sets.
940
- let available;
941
- if (bundleRoot.bundleBehavior === 'isolated') {
942
- available = new BitSet(assets.length);
943
- } else {
944
- available = nullthrows(ancestorAssets[nodeId]).clone();
945
- for (let bundleIdInGroup of [
946
- bundleGroupId,
947
- ...bundleGraph.getNodeIdsConnectedFrom(bundleGroupId),
948
- ]) {
949
- let bundleInGroup = nullthrows(bundleGraph.getNode(bundleIdInGroup));
950
- invariant(bundleInGroup !== 'root');
951
- if (bundleInGroup.bundleBehavior != null) {
952
- continue;
953
- }
954
-
955
- for (let bundleRoot of bundleInGroup.assets) {
956
- // Assets directly connected to current bundleRoot
957
- available.add(nullthrows(assetToIndex.get(bundleRoot)));
958
- available.union(
959
- reachableAssets[
960
- nullthrows(assetToBundleRootNodeId.get(bundleRoot))
961
- ],
962
- );
963
- }
964
- }
965
- }
966
-
967
- // Now that we have bundleGroup availability, we will propagate that down to all the children
968
- // of this bundleGroup. For a child, we also must maintain parallel availability. If it has
969
- // parallel siblings that come before it, those, too, are available to it. Add those parallel
970
- // available assets to the set of available assets for this child as well.
971
- let children = bundleRootGraph.getNodeIdsConnectedFrom(
972
- nodeId,
973
- ALL_EDGE_TYPES,
974
- );
975
- let parallelAvailability = new BitSet(assets.length);
976
-
977
- for (let childId of children) {
978
- let assetId = nullthrows(bundleRootGraph.getNode(childId));
979
- let child = assets[assetId];
980
- let bundleBehavior = getBundleFromBundleRoot(child).bundleBehavior;
981
- if (bundleBehavior != null) {
982
- continue;
983
- }
984
- let isParallel = bundleRootGraph.hasEdge(
985
- nodeId,
986
- childId,
987
- bundleRootEdgeTypes.parallel,
988
- );
989
-
990
- // Most of the time, a child will have many parent bundleGroups,
991
- // so the next time we peek at a child from another parent, we will
992
- // intersect the availability built there with the previously computed
993
- // availability. this ensures no matter which bundleGroup loads a particular bundle,
994
- // it will only assume availability of assets it has under any circumstance
995
- const childAvailableAssets = ancestorAssets[childId];
996
- let currentChildAvailable = isParallel
997
- ? BitSet.union(parallelAvailability, available)
998
- : available;
999
- if (childAvailableAssets != null) {
1000
- childAvailableAssets.intersect(currentChildAvailable);
1001
- } else {
1002
- ancestorAssets[childId] = currentChildAvailable.clone();
1003
- }
1004
- if (isParallel) {
1005
- parallelAvailability.union(reachableAssets[childId]);
1006
- parallelAvailability.add(assetId); //The next sibling should have older sibling available via parallel
1007
- }
1008
- }
1009
- }
1010
- // Step Internalize async bundles - internalize Async bundles if and only if,
1011
- // the bundle is synchronously available elsewhere.
1012
- // We can query sync assets available via reachableRoots. If the parent has
1013
- // the bundleRoot by reachableRoots AND ancestorAssets, internalize it.
1014
- for (let [id, bundleRootId] of bundleRootGraph.nodes.entries()) {
1015
- if (bundleRootId == null || id === rootNodeId) continue;
1016
- let bundleRoot = assets[bundleRootId];
1017
-
1018
- if (manualAssetToConfig.has(bundleRoot)) {
1019
- // We internalize for MSBs later, we should never delete MSBs
1020
- continue;
1021
- }
1022
-
1023
- let parentRoots = bundleRootGraph.getNodeIdsConnectedTo(id, ALL_EDGE_TYPES);
1024
- let canDelete =
1025
- getBundleFromBundleRoot(bundleRoot).bundleBehavior !== 'isolated';
1026
- if (parentRoots.length === 0) continue;
1027
- for (let parentId of parentRoots) {
1028
- if (parentId === rootNodeId) {
1029
- // connected to root.
1030
- canDelete = false;
1031
- continue;
1032
- }
1033
- if (
1034
- reachableAssets[parentId].has(bundleRootId) ||
1035
- ancestorAssets[parentId]?.has(bundleRootId)
1036
- ) {
1037
- let parentAssetId = nullthrows(bundleRootGraph.getNode(parentId));
1038
- let parent = assets[parentAssetId];
1039
- let parentBundle = bundleGraph.getNode(
1040
- nullthrows(bundles.get(parent.id)),
1041
- );
1042
- invariant(parentBundle != null && parentBundle !== 'root');
1043
- if (!parentBundle.internalizedAssets) {
1044
- parentBundle.internalizedAssets = new BitSet(assets.length);
1045
- }
1046
-
1047
- parentBundle.internalizedAssets.add(bundleRootId);
1048
- } else {
1049
- canDelete = false;
1050
- }
1051
- }
1052
- if (canDelete) {
1053
- deleteBundle(bundleRoot);
1054
- }
1055
- }
1056
-
1057
- function assignInlineConstants(parentAsset: Asset, bundle: Bundle) {
1058
- for (let inlineConstant of inlineConstantDeps.get(parentAsset)) {
1059
- if (!bundle.assets.has(inlineConstant)) {
1060
- bundle.assets.add(inlineConstant);
1061
- bundle.size += inlineConstant.stats.size;
1062
- }
1063
- }
1064
- }
1065
-
1066
- // Step Insert Or Share: Place all assets into bundles or create shared bundles. Each asset
1067
- // is placed into a single bundle based on the bundle entries it is reachable from.
1068
- // This creates a maximally code split bundle graph with no duplication.
1069
- let reachable = new BitSet(assets.length);
1070
- let reachableNonEntries = new BitSet(assets.length);
1071
- let reachableIntersection = new BitSet(assets.length);
1072
- for (let i = 0; i < assets.length; i++) {
1073
- let asset = assets[i];
1074
- let manualSharedObject = manualAssetToConfig.get(asset);
1075
-
1076
- if (bundleRoots.has(asset) && inlineConstantDeps.get(asset).size > 0) {
1077
- let entryBundleId = nullthrows(bundleRoots.get(asset))[0];
1078
- let entryBundle = nullthrows(bundleGraph.getNode(entryBundleId));
1079
- invariant(entryBundle !== 'root');
1080
- assignInlineConstants(asset, entryBundle);
1081
- }
1082
-
1083
- if (asset.meta.isConstantModule === true) {
1084
- // Ignore constant modules as they are placed with their direct parents
1085
- continue;
1086
- }
1087
-
1088
- // Unreliable bundleRoot assets which need to pulled in by shared bundles or other means.
1089
- // Filter out entries, since they can't have shared bundles.
1090
- // Neither can non-splittable, isolated, or needing of stable name bundles.
1091
- // Reserve those filtered out bundles since we add the asset back into them.
1092
- reachableNonEntries.clear();
1093
- reachableRoots[i].forEach((nodeId) => {
1094
- let assetId = bundleRootGraph.getNode(nodeId);
1095
- if (assetId == null) return; // deleted
1096
- let a = assets[assetId];
1097
- if (
1098
- entries.has(a) ||
1099
- !a.isBundleSplittable ||
1100
- (bundleRoots.get(a) &&
1101
- (getBundleFromBundleRoot(a).needsStableName ||
1102
- getBundleFromBundleRoot(a).bundleBehavior === 'isolated'))
1103
- ) {
1104
- // Add asset to non-splittable bundles.
1105
- addAssetToBundleRoot(asset, a);
1106
- } else if (!ancestorAssets[nodeId]?.has(i)) {
1107
- // Filter out bundles from this asset's reachable array if
1108
- // bundle does not contain the asset in its ancestry
1109
- reachableNonEntries.add(assetId);
1110
- }
1111
- });
1112
-
1113
- reachable.bits.set(reachableNonEntries.bits);
1114
-
1115
- // If we encounter a "manual" asset, draw an edge from reachable to its MSB
1116
- if (manualSharedObject && !reachable.empty()) {
1117
- let bundle;
1118
- let bundleId;
1119
- let manualSharedBundleKey = manualSharedObject.name + ',' + asset.type;
1120
- let sourceBundles = [];
1121
- reachable.forEach((id) => {
1122
- sourceBundles.push(nullthrows(bundleRoots.get(assets[id]))[0]);
1123
- });
1124
-
1125
- if (!manualSharedMap.has(manualSharedBundleKey)) {
1126
- let firstSourceBundle = nullthrows(
1127
- bundleGraph.getNode(sourceBundles[0]),
1128
- );
1129
- invariant(firstSourceBundle !== 'root');
1130
-
1131
- bundle = createBundle({
1132
- uniqueKey: manualSharedBundleKey,
1133
- target: firstSourceBundle.target,
1134
- type: asset.type,
1135
- env: firstSourceBundle.env,
1136
- manualSharedBundle: manualSharedObject?.name,
1137
- });
1138
- bundle.sourceBundles = new Set(sourceBundles);
1139
- bundle.assets.add(asset);
1140
- bundleId = bundleGraph.addNode(bundle);
1141
- manualSharedMap.set(manualSharedBundleKey, bundleId);
1142
- } else {
1143
- bundleId = nullthrows(manualSharedMap.get(manualSharedBundleKey));
1144
- bundle = nullthrows(bundleGraph.getNode(bundleId));
1145
- invariant(
1146
- bundle != null && bundle !== 'root',
1147
- 'We tried to use the root incorrectly',
1148
- );
1149
-
1150
- if (!bundle.assets.has(asset)) {
1151
- bundle.assets.add(asset);
1152
- bundle.size += asset.stats.size;
1153
- }
1154
-
1155
- for (let s of sourceBundles) {
1156
- if (s != bundleId) {
1157
- bundle.sourceBundles.add(s);
1158
- }
1159
- }
1160
- }
1161
-
1162
- for (let sourceBundleId of sourceBundles) {
1163
- if (bundleId !== sourceBundleId) {
1164
- bundleGraph.addEdge(sourceBundleId, bundleId);
1165
- }
1166
- }
1167
-
1168
- dependencyBundleGraph.addNodeByContentKeyIfNeeded(String(bundleId), {
1169
- value: bundle,
1170
- type: 'bundle',
1171
- });
1172
- continue;
1173
- }
1174
-
1175
- // Finally, filter out bundleRoots (bundles) from this assets
1176
- // reachable if they are subgraphs, and reuse that subgraph bundle
1177
- // by drawing an edge. Essentially, if two bundles within an asset's
1178
- // reachable array, have an ancestor-subgraph relationship, draw that edge.
1179
- // This allows for us to reuse a bundle instead of making a shared bundle if
1180
- // a bundle represents the exact set of assets a set of bundles would share
1181
-
1182
- // if a bundle b is a subgraph of another bundle f, reuse it, drawing an edge between the two
1183
- if (config.disableSharedBundles === false) {
1184
- reachableNonEntries.forEach((candidateId) => {
1185
- let candidateSourceBundleRoot = assets[candidateId];
1186
- let candidateSourceBundleId = nullthrows(
1187
- bundleRoots.get(candidateSourceBundleRoot),
1188
- )[0];
1189
- if (candidateSourceBundleRoot.env.isIsolated()) {
1190
- return;
1191
- }
1192
- let reuseableBundleId = bundles.get(asset.id);
1193
- if (reuseableBundleId != null) {
1194
- reachable.delete(candidateId);
1195
- bundleGraph.addEdge(candidateSourceBundleId, reuseableBundleId);
37
+ for (let entries of targetMap.values()) {
38
+ let singleFileEntries = new Map();
39
+ let idealGraphEntries = new Map();
1196
40
 
1197
- let reusableBundle = bundleGraph.getNode(reuseableBundleId);
1198
- invariant(reusableBundle !== 'root' && reusableBundle != null);
1199
- reusableBundle.sourceBundles.add(candidateSourceBundleId);
41
+ // Separate out the monolith bundles based on the option on target
42
+ for (let [entryAsset, entryDep] of entries.entries()) {
43
+ if (entryDep.target?.env.unstableSingleFileOutput === true) {
44
+ singleFileEntries.set(entryAsset, entryDep);
1200
45
  } else {
1201
- // Asset is not a bundleRoot, but if its ancestor bundle (in the asset's reachable) can be
1202
- // reused as a subgraph of another bundleRoot in its reachable, reuse it
1203
- reachableIntersection.bits.set(reachableNonEntries.bits);
1204
- reachableIntersection.intersect(
1205
- reachableAssets[
1206
- nullthrows(assetToBundleRootNodeId.get(candidateSourceBundleRoot))
1207
- ],
1208
- );
1209
-
1210
- reachableIntersection.forEach((otherCandidateId) => {
1211
- let otherReuseCandidate = assets[otherCandidateId];
1212
- if (candidateSourceBundleRoot === otherReuseCandidate) return;
1213
- let reusableBundleId = nullthrows(
1214
- bundles.get(otherReuseCandidate.id),
1215
- );
1216
- reachable.delete(candidateId);
1217
- bundleGraph.addEdge(
1218
- nullthrows(bundles.get(candidateSourceBundleRoot.id)),
1219
- reusableBundleId,
1220
- );
1221
- let reusableBundle = bundleGraph.getNode(reusableBundleId);
1222
- invariant(reusableBundle !== 'root' && reusableBundle != null);
1223
- reusableBundle.sourceBundles.add(candidateSourceBundleId);
1224
- });
1225
- }
1226
- });
1227
- }
1228
-
1229
- let reachableArray = [];
1230
- reachable.forEach((id) => {
1231
- reachableArray.push(assets[id]);
1232
- });
1233
-
1234
- // Create shared bundles for splittable bundles.
1235
- if (
1236
- config.disableSharedBundles === false &&
1237
- reachableArray.length > config.minBundles
1238
- ) {
1239
- let sourceBundles = reachableArray.map(
1240
- (a) => nullthrows(bundleRoots.get(a))[0],
1241
- );
1242
- let key = reachableArray.map((a) => a.id).join(',') + '.' + asset.type;
1243
- let bundleId = bundles.get(key);
1244
- let bundle;
1245
- if (bundleId == null) {
1246
- let firstSourceBundle = nullthrows(
1247
- bundleGraph.getNode(sourceBundles[0]),
1248
- );
1249
- invariant(firstSourceBundle !== 'root');
1250
- bundle = createBundle({
1251
- target: firstSourceBundle.target,
1252
- type: asset.type,
1253
- env: firstSourceBundle.env,
1254
- });
1255
- bundle.sourceBundles = new Set(sourceBundles);
1256
- let sharedInternalizedAssets = firstSourceBundle.internalizedAssets
1257
- ? firstSourceBundle.internalizedAssets.clone()
1258
- : new BitSet(assets.length);
1259
-
1260
- for (let p of sourceBundles) {
1261
- let parentBundle = nullthrows(bundleGraph.getNode(p));
1262
- invariant(parentBundle !== 'root');
1263
- if (parentBundle === firstSourceBundle) continue;
1264
-
1265
- if (parentBundle.internalizedAssets) {
1266
- sharedInternalizedAssets.intersect(parentBundle.internalizedAssets);
1267
- } else {
1268
- sharedInternalizedAssets.clear();
1269
- }
1270
- }
1271
- bundle.internalizedAssets = sharedInternalizedAssets;
1272
- bundleId = bundleGraph.addNode(bundle);
1273
- bundles.set(key, bundleId);
1274
- } else {
1275
- bundle = nullthrows(bundleGraph.getNode(bundleId));
1276
- invariant(bundle !== 'root');
1277
- }
1278
- bundle.assets.add(asset);
1279
- bundle.size += asset.stats.size;
1280
-
1281
- assignInlineConstants(asset, bundle);
1282
-
1283
- for (let sourceBundleId of sourceBundles) {
1284
- if (bundleId !== sourceBundleId) {
1285
- bundleGraph.addEdge(sourceBundleId, bundleId);
1286
- }
1287
- }
1288
-
1289
- dependencyBundleGraph.addNodeByContentKeyIfNeeded(String(bundleId), {
1290
- value: bundle,
1291
- type: 'bundle',
1292
- });
1293
- } else if (
1294
- config.disableSharedBundles === true ||
1295
- reachableArray.length <= config.minBundles
1296
- ) {
1297
- for (let root of reachableArray) {
1298
- addAssetToBundleRoot(asset, root);
1299
- }
1300
- }
1301
- }
1302
-
1303
- let manualSharedBundleIds = new Set([...manualSharedMap.values()]);
1304
- // Step split manual shared bundles for those that have the "split" property set
1305
- let remainderMap = new DefaultMap(() => []);
1306
- for (let id of manualSharedMap.values()) {
1307
- let manualBundle = bundleGraph.getNode(id);
1308
- invariant(manualBundle !== 'root' && manualBundle != null);
1309
-
1310
- if (manualBundle.sourceBundles.size > 0) {
1311
- let firstSourceBundle = nullthrows(
1312
- bundleGraph.getNode([...manualBundle.sourceBundles][0]),
1313
- );
1314
- invariant(firstSourceBundle !== 'root');
1315
- let firstAsset = [...manualBundle.assets][0];
1316
- let manualSharedObject = manualAssetToConfig.get(firstAsset);
1317
- invariant(manualSharedObject != null);
1318
- let modNum = manualAssetToConfig.get(firstAsset)?.split;
1319
- if (modNum != null) {
1320
- for (let a of [...manualBundle.assets]) {
1321
- let numRep = getBigIntFromContentKey(a.id);
1322
- // $FlowFixMe Flow doesn't know about BigInt
1323
- let r = Number(numRep % BigInt(modNum));
1324
-
1325
- remainderMap.get(r).push(a);
1326
- }
1327
-
1328
- for (let i = 1; i < [...remainderMap.keys()].length; i++) {
1329
- let bundle = createBundle({
1330
- uniqueKey: manualSharedObject.name + firstSourceBundle.type + i,
1331
- target: firstSourceBundle.target,
1332
- type: firstSourceBundle.type,
1333
- env: firstSourceBundle.env,
1334
- manualSharedBundle: manualSharedObject.name,
1335
- });
1336
- bundle.sourceBundles = manualBundle.sourceBundles;
1337
- bundle.internalizedAssets = manualBundle.internalizedAssets;
1338
- let bundleId = bundleGraph.addNode(bundle);
1339
- manualSharedBundleIds.add(bundleId);
1340
- for (let sourceBundleId of manualBundle.sourceBundles) {
1341
- if (bundleId !== sourceBundleId) {
1342
- bundleGraph.addEdge(sourceBundleId, bundleId);
1343
- }
1344
- }
1345
- for (let sp of remainderMap.get(i)) {
1346
- bundle.assets.add(sp);
1347
- bundle.size += sp.stats.size;
1348
- manualBundle.assets.delete(sp);
1349
- manualBundle.size -= sp.stats.size;
1350
- }
1351
- }
1352
- }
1353
- }
1354
- }
1355
-
1356
- // Step insert constant modules into manual shared bundles.
1357
- // We have to do this separately as they're the only case where a single asset can
1358
- // match multiple MSB's
1359
- for (let [asset, msbs] of constantModuleToMSB.entries()) {
1360
- for (let manualSharedObject of msbs) {
1361
- let bundleId = manualSharedMap.get(manualSharedObject.name + ',js');
1362
- if (bundleId == null) continue;
1363
- let bundle = nullthrows(bundleGraph.getNode(bundleId));
1364
- invariant(
1365
- bundle != null && bundle !== 'root',
1366
- 'We tried to use the root incorrectly',
1367
- );
1368
-
1369
- if (!bundle.assets.has(asset)) {
1370
- bundle.assets.add(asset);
1371
- bundle.size += asset.stats.size;
1372
- }
1373
- }
1374
- }
1375
-
1376
- // Step Merge Share Bundles: Merge any shared bundles under the minimum bundle size back into
1377
- // their source bundles, and remove the bundle.
1378
- // We should include "bundle reuse" as shared bundles that may be removed but the bundle itself would have to be retained
1379
- for (let [bundleNodeId, bundle] of bundleGraph.nodes.entries()) {
1380
- if (!bundle || bundle === 'root') continue;
1381
- if (
1382
- bundle.sourceBundles.size > 0 &&
1383
- bundle.mainEntryAsset == null &&
1384
- bundle.size < config.minBundleSize &&
1385
- !manualSharedBundleIds.has(bundleNodeId)
1386
- ) {
1387
- removeBundle(bundleGraph, bundleNodeId, assetReference);
1388
- }
1389
- }
1390
-
1391
- let modifiedSourceBundles = new Set();
1392
-
1393
- // Step Remove Shared Bundles: Remove shared bundles from bundle groups that hit the parallel request limit.
1394
- if (config.disableSharedBundles === false) {
1395
- for (let bundleGroupId of bundleGraph.getNodeIdsConnectedFrom(rootNodeId)) {
1396
- // Find shared bundles in this bundle group.
1397
- let bundleId = bundleGroupId;
1398
-
1399
- // We should include "bundle reuse" as shared bundles that may be removed but the bundle itself would have to be retained
1400
- let bundleIdsInGroup = getBundlesForBundleGroup(bundleId); //get all bundlegrups this bundle is an ancestor of
1401
-
1402
- // Filter out inline assests as they should not contribute to PRL
1403
- let numBundlesContributingToPRL = bundleIdsInGroup.reduce((count, b) => {
1404
- let bundle = nullthrows(bundleGraph.getNode(b));
1405
- invariant(bundle !== 'root');
1406
- return count + (bundle.bundleBehavior !== 'inline');
1407
- }, 0);
1408
-
1409
- if (numBundlesContributingToPRL > config.maxParallelRequests) {
1410
- let sharedBundleIdsInBundleGroup = bundleIdsInGroup.filter((b) => {
1411
- let bundle = nullthrows(bundleGraph.getNode(b));
1412
- // shared bundles must have source bundles, we could have a bundle
1413
- // connected to another bundle that isnt a shared bundle, so check
1414
- return (
1415
- bundle !== 'root' &&
1416
- bundle.sourceBundles.size > 0 &&
1417
- bundleId != b &&
1418
- !manualSharedBundleIds.has(b)
1419
- );
1420
- });
1421
-
1422
- // Sort the bundles so the smallest ones are removed first.
1423
- let sharedBundlesInGroup = sharedBundleIdsInBundleGroup
1424
- .map((id) => ({
1425
- id,
1426
- bundle: nullthrows(bundleGraph.getNode(id)),
1427
- }))
1428
- .map(({id, bundle}) => {
1429
- // For Flow
1430
- invariant(bundle !== 'root');
1431
- return {id, bundle};
1432
- })
1433
- .sort((a, b) => b.bundle.size - a.bundle.size);
1434
-
1435
- // Remove bundles until the bundle group is within the parallel request limit.
1436
- while (
1437
- sharedBundlesInGroup.length > 0 &&
1438
- numBundlesContributingToPRL > config.maxParallelRequests
1439
- ) {
1440
- let bundleTuple = sharedBundlesInGroup.pop();
1441
- let bundleToRemove = bundleTuple.bundle;
1442
- let bundleIdToRemove = bundleTuple.id;
1443
- //TODO add integration test where bundles in bunlde group > max parallel request limit & only remove a couple shared bundles
1444
- // but total # bundles still exceeds limit due to non shared bundles
1445
-
1446
- // Add all assets in the shared bundle into the source bundles that are within this bundle group.
1447
- let sourceBundles = [...bundleToRemove.sourceBundles].filter((b) =>
1448
- bundleIdsInGroup.includes(b),
1449
- );
1450
-
1451
- for (let sourceBundleId of sourceBundles) {
1452
- let sourceBundle = nullthrows(bundleGraph.getNode(sourceBundleId));
1453
- invariant(sourceBundle !== 'root');
1454
- modifiedSourceBundles.add(sourceBundle);
1455
- bundleToRemove.sourceBundles.delete(sourceBundleId);
1456
- for (let asset of bundleToRemove.assets) {
1457
- addAssetToBundleRoot(
1458
- asset,
1459
- nullthrows(sourceBundle.mainEntryAsset),
1460
- );
1461
- }
1462
- //This case is specific to reused bundles, which can have shared bundles attached to it
1463
- for (let childId of bundleGraph.getNodeIdsConnectedFrom(
1464
- bundleIdToRemove,
1465
- )) {
1466
- let child = bundleGraph.getNode(childId);
1467
- invariant(child !== 'root' && child != null);
1468
- child.sourceBundles.add(sourceBundleId);
1469
- bundleGraph.addEdge(sourceBundleId, childId);
1470
- }
1471
- // needs to add test case where shared bundle is removed from ONE bundlegroup but not from the whole graph!
1472
- // Remove the edge from this bundle group to the shared bundle.
1473
- // If there is now only a single bundle group that contains this bundle,
1474
- // merge it into the remaining source bundles. If it is orphaned entirely, remove it.
1475
- let incomingNodeCount =
1476
- bundleGraph.getNodeIdsConnectedTo(bundleIdToRemove).length;
1477
-
1478
- if (
1479
- incomingNodeCount <= 2 &&
1480
- //Never fully remove reused bundles
1481
- bundleToRemove.mainEntryAsset == null
1482
- ) {
1483
- // If one bundle group removes a shared bundle, but the other *can* keep it, still remove because that shared bundle is pointless (only one source bundle)
1484
- removeBundle(bundleGraph, bundleIdToRemove, assetReference);
1485
- // Stop iterating through bundleToRemove's sourceBundles as the bundle has been removed.
1486
- break;
1487
- } else {
1488
- bundleGraph.removeEdge(sourceBundleId, bundleIdToRemove);
1489
- }
1490
- }
1491
- numBundlesContributingToPRL--;
46
+ idealGraphEntries.set(entryAsset, entryDep);
1492
47
  }
1493
48
  }
1494
- }
1495
- }
1496
-
1497
- function getBigIntFromContentKey(contentKey) {
1498
- let b = Buffer.alloc(64);
1499
- b.write(contentKey);
1500
- // $FlowFixMe Flow doesn't have BigInt types in this version
1501
- return b.readBigInt64BE();
1502
- }
1503
- // Fix asset order in source bundles as they are likely now incorrect after shared bundle deletion
1504
- if (modifiedSourceBundles.size > 0) {
1505
- let assetOrderMap = new Map(assets.map((a, index) => [a, index]));
1506
49
 
1507
- for (let bundle of modifiedSourceBundles) {
1508
- bundle.assets = new Set(
1509
- [...bundle.assets].sort((a, b) => {
1510
- let aIndex = nullthrows(assetOrderMap.get(a));
1511
- let bIndex = nullthrows(assetOrderMap.get(b));
1512
-
1513
- return aIndex - bIndex;
1514
- }),
50
+ // Create separate bundleGraphs per distDir
51
+ graphs.push(
52
+ createIdealGraph(bundleGraph, config, idealGraphEntries, logger),
1515
53
  );
1516
- }
1517
- }
1518
- function deleteBundle(bundleRoot: BundleRoot) {
1519
- bundleGraph.removeNode(nullthrows(bundles.get(bundleRoot.id)));
1520
- bundleRoots.delete(bundleRoot);
1521
- bundles.delete(bundleRoot.id);
1522
- let bundleRootId = assetToBundleRootNodeId.get(bundleRoot);
1523
- if (bundleRootId != null && bundleRootGraph.hasNode(bundleRootId)) {
1524
- bundleRootGraph.removeNode(bundleRootId);
1525
- }
1526
- }
1527
- function getBundlesForBundleGroup(bundleGroupId) {
1528
- let bundlesInABundleGroup = [];
1529
- bundleGraph.traverse((nodeId) => {
1530
- bundlesInABundleGroup.push(nodeId);
1531
- }, bundleGroupId);
1532
- return bundlesInABundleGroup;
1533
- }
1534
-
1535
- function getBundleFromBundleRoot(bundleRoot: BundleRoot): Bundle {
1536
- let bundle = bundleGraph.getNode(
1537
- nullthrows(bundleRoots.get(bundleRoot))[0],
1538
- );
1539
- invariant(bundle !== 'root' && bundle != null);
1540
- return bundle;
1541
- }
1542
54
 
1543
- function addAssetToBundleRoot(asset: Asset, bundleRoot: Asset) {
1544
- let [bundleId, bundleGroupId] = nullthrows(bundleRoots.get(bundleRoot));
1545
- let bundle = nullthrows(bundleGraph.getNode(bundleId));
1546
- invariant(bundle !== 'root');
1547
-
1548
- if (asset.type !== bundle.type) {
1549
- let bundleGroup = nullthrows(bundleGraph.getNode(bundleGroupId));
1550
- invariant(bundleGroup !== 'root');
1551
- let key = nullthrows(bundleGroup.mainEntryAsset).id + '.' + asset.type;
1552
- let typeChangeBundleId = bundles.get(key);
1553
- if (typeChangeBundleId == null) {
1554
- let typeChangeBundle = createBundle({
1555
- uniqueKey: key,
1556
- needsStableName: bundle.needsStableName,
1557
- bundleBehavior: bundle.bundleBehavior,
1558
- type: asset.type,
1559
- target: bundle.target,
1560
- env: bundle.env,
1561
- });
1562
- typeChangeBundleId = bundleGraph.addNode(typeChangeBundle);
1563
- bundleGraph.addEdge(bundleId, typeChangeBundleId);
1564
- bundles.set(key, typeChangeBundleId);
1565
- bundle = typeChangeBundle;
1566
- } else {
1567
- bundle = nullthrows(bundleGraph.getNode(typeChangeBundleId));
1568
- invariant(bundle !== 'root');
55
+ // Do this after the ideal graph so that the mutation of the bundleGraph doesn't
56
+ // interfere with the main bundling algorithm
57
+ for (let [entryAsset, entryDep] of singleFileEntries.entries()) {
58
+ addJSMonolithBundle(bundleGraph, entryAsset, entryDep);
1569
59
  }
1570
60
  }
1571
61
 
1572
- bundle.assets.add(asset);
1573
- bundle.size += asset.stats.size;
1574
- assignInlineConstants(asset, bundle);
1575
- }
1576
-
1577
- function removeBundle(
1578
- bundleGraph: Graph<Bundle | 'root'>,
1579
- bundleId: NodeId,
1580
- assetReference: DefaultMap<Asset, Array<[Dependency, Bundle]>>,
1581
- ) {
1582
- let bundle = nullthrows(bundleGraph.getNode(bundleId));
1583
- invariant(bundle !== 'root');
1584
- for (let asset of bundle.assets) {
1585
- assetReference.set(
1586
- asset,
1587
- assetReference.get(asset).filter((t) => !t.includes(bundle)),
1588
- );
1589
- for (let sourceBundleId of bundle.sourceBundles) {
1590
- let sourceBundle = nullthrows(bundleGraph.getNode(sourceBundleId));
1591
- invariant(sourceBundle !== 'root');
1592
- addAssetToBundleRoot(asset, nullthrows(sourceBundle.mainEntryAsset));
1593
- }
62
+ for (let g of graphs) {
63
+ decorateLegacyGraph(g, bundleGraph); //mutate original graph
1594
64
  }
1595
-
1596
- bundleGraph.removeNode(bundleId);
1597
- }
1598
-
1599
- return {
1600
- assets,
1601
- bundleGraph,
1602
- dependencyBundleGraph,
1603
- bundleGroupBundleIds,
1604
- assetReference,
1605
- manualAssetToBundle,
1606
- };
1607
- }
1608
-
1609
- const CONFIG_SCHEMA: SchemaEntity = {
1610
- type: 'object',
1611
- properties: {
1612
- http: {
1613
- type: 'number',
1614
- enum: Object.keys(HTTP_OPTIONS).map((k) => Number(k)),
1615
- },
1616
- manualSharedBundles: {
1617
- type: 'array',
1618
- items: {
1619
- type: 'object',
1620
- properties: {
1621
- name: {
1622
- type: 'string',
1623
- },
1624
- assets: {
1625
- type: 'array',
1626
- items: {
1627
- type: 'string',
1628
- },
1629
- },
1630
- types: {
1631
- type: 'array',
1632
- items: {
1633
- type: 'string',
1634
- },
1635
- },
1636
- root: {
1637
- type: 'string',
1638
- },
1639
- split: {
1640
- type: 'number',
1641
- },
1642
- },
1643
- required: ['name', 'assets'],
1644
- additionalProperties: false,
1645
- },
1646
- },
1647
- minBundles: {
1648
- type: 'number',
1649
- },
1650
- minBundleSize: {
1651
- type: 'number',
1652
- },
1653
- maxParallelRequests: {
1654
- type: 'number',
1655
- },
1656
- disableSharedBundles: {
1657
- type: 'boolean',
1658
- },
1659
65
  },
1660
- additionalProperties: false,
1661
- };
1662
-
1663
- function createBundle(opts: {|
1664
- uniqueKey?: string,
1665
- target: Target,
1666
- asset?: Asset,
1667
- env?: Environment,
1668
- type?: string,
1669
- needsStableName?: boolean,
1670
- bundleBehavior?: ?BundleBehavior,
1671
- manualSharedBundle?: ?string,
1672
- |}): Bundle {
1673
- if (opts.asset == null) {
1674
- return {
1675
- uniqueKey: opts.uniqueKey,
1676
- assets: new Set(),
1677
- mainEntryAsset: null,
1678
- size: 0,
1679
- sourceBundles: new Set(),
1680
- target: opts.target,
1681
- type: nullthrows(opts.type),
1682
- env: nullthrows(opts.env),
1683
- needsStableName: Boolean(opts.needsStableName),
1684
- bundleBehavior: opts.bundleBehavior,
1685
- manualSharedBundle: opts.manualSharedBundle,
1686
- };
1687
- }
1688
-
1689
- let asset = nullthrows(opts.asset);
1690
- return {
1691
- uniqueKey: opts.uniqueKey,
1692
- assets: new Set([asset]),
1693
- mainEntryAsset: asset,
1694
- size: asset.stats.size,
1695
- sourceBundles: new Set(),
1696
- target: opts.target,
1697
- type: opts.type ?? asset.type,
1698
- env: opts.env ?? asset.env,
1699
- needsStableName: Boolean(opts.needsStableName),
1700
- bundleBehavior: opts.bundleBehavior ?? asset.bundleBehavior,
1701
- manualSharedBundle: opts.manualSharedBundle,
1702
- };
1703
- }
1704
-
1705
- function resolveModeConfig(
1706
- config: BundlerConfig,
1707
- mode: BuildMode,
1708
- ): BaseBundlerConfig {
1709
- let generalConfig = {};
1710
- let modeConfig = {};
1711
-
1712
- for (const key of Object.keys(config)) {
1713
- if (key === 'development' || key === 'production') {
1714
- if (key === mode) {
1715
- modeConfig = config[key];
1716
- }
1717
- } else {
1718
- generalConfig[key] = config[key];
1719
- }
1720
- }
1721
-
1722
- // $FlowFixMe Not sure how to convince flow here...
1723
- return {
1724
- ...generalConfig,
1725
- ...modeConfig,
1726
- };
1727
- }
1728
-
1729
- async function loadBundlerConfig(
1730
- config: Config,
1731
- options: PluginOptions,
1732
- logger: PluginLogger,
1733
- ): Promise<ResolvedBundlerConfig> {
1734
- let conf = await config.getConfig<BundlerConfig>([], {
1735
- packageKey: '@atlaspack/bundler-default',
1736
- });
1737
-
1738
- if (!conf) {
1739
- const modDefault = {
1740
- ...HTTP_OPTIONS['2'],
1741
- projectRoot: options.projectRoot,
1742
- };
1743
- return modDefault;
1744
- }
1745
-
1746
- invariant(conf?.contents != null);
1747
-
1748
- let modeConfig = resolveModeConfig(conf.contents, options.mode);
1749
-
1750
- // minBundles will be ignored if shared bundles are disabled
1751
- if (
1752
- modeConfig.minBundles != null &&
1753
- modeConfig.disableSharedBundles === true
1754
- ) {
1755
- logger.warn({
1756
- origin: '@atlaspack/bundler-default',
1757
- message: `The value of "${modeConfig.minBundles}" set for minBundles will not be used as shared bundles have been disabled`,
1758
- });
1759
- }
1760
-
1761
- // minBundleSize will be ignored if shared bundles are disabled
1762
- if (
1763
- modeConfig.minBundleSize != null &&
1764
- modeConfig.disableSharedBundles === true
1765
- ) {
1766
- logger.warn({
1767
- origin: '@atlaspack/bundler-default',
1768
- message: `The value of "${modeConfig.minBundleSize}" set for minBundleSize will not be used as shared bundles have been disabled`,
1769
- });
1770
- }
1771
-
1772
- // maxParallelRequests will be ignored if shared bundles are disabled
1773
- if (
1774
- modeConfig.maxParallelRequests != null &&
1775
- modeConfig.disableSharedBundles === true
1776
- ) {
1777
- logger.warn({
1778
- origin: '@atlaspack/bundler-default',
1779
- message: `The value of "${modeConfig.maxParallelRequests}" set for maxParallelRequests will not be used as shared bundles have been disabled`,
1780
- });
1781
- }
1782
-
1783
- if (modeConfig.manualSharedBundles) {
1784
- let nameArray = modeConfig.manualSharedBundles.map((a) => a.name);
1785
- let nameSet = new Set(nameArray);
1786
- invariant(
1787
- nameSet.size == nameArray.length,
1788
- 'The name field must be unique for property manualSharedBundles',
1789
- );
1790
- }
1791
-
1792
- validateSchema.diagnostic(
1793
- CONFIG_SCHEMA,
1794
- {
1795
- data: modeConfig,
1796
- source: await options.inputFS.readFile(conf.filePath, 'utf8'),
1797
- filePath: conf.filePath,
1798
- prependKey: `/${encodeJSONKeyComponent('@atlaspack/bundler-default')}`,
1799
- },
1800
- '@atlaspack/bundler-default',
1801
- 'Invalid config for @atlaspack/bundler-default',
1802
- );
1803
-
1804
- let http = modeConfig.http ?? 2;
1805
- let defaults = HTTP_OPTIONS[http];
1806
-
1807
- return {
1808
- minBundles: modeConfig.minBundles ?? defaults.minBundles,
1809
- minBundleSize: modeConfig.minBundleSize ?? defaults.minBundleSize,
1810
- maxParallelRequests:
1811
- modeConfig.maxParallelRequests ?? defaults.maxParallelRequests,
1812
- projectRoot: options.projectRoot,
1813
- disableSharedBundles:
1814
- modeConfig.disableSharedBundles ?? defaults.disableSharedBundles,
1815
- manualSharedBundles:
1816
- modeConfig.manualSharedBundles ?? defaults.manualSharedBundles,
1817
- };
1818
- }
66
+ optimize() {},
67
+ }): Bundler);
1819
68
 
1820
69
  function getEntryByTarget(
1821
70
  bundleGraph: MutableBundleGraph,