0
# Bundle Generation
1
2
The Bundler plugin controls how assets are grouped into bundles and optimizes the bundle graph for performance, caching, and loading strategies. Bundlers determine the overall structure of the build output.
3
4
## Capabilities
5
6
### Bundler Class
7
8
Base class for creating bundle generation plugins.
9
10
```typescript { .api }
11
/**
12
* Base class for bundle generation plugins
13
* @template T - Configuration type for this bundler
14
*/
15
export declare class Bundler<T> {
16
constructor(opts: BundlerOpts<T>);
17
}
18
19
/**
20
* Bundler plugin configuration interface
21
* @template ConfigType - Type of configuration returned by loadConfig
22
*/
23
interface BundlerOpts<ConfigType> {
24
/** Load configuration for this bundler */
25
loadConfig?: (args: {
26
config: Config;
27
options: PluginOptions;
28
logger: PluginLogger;
29
tracer: PluginTracer;
30
}) => Promise<ConfigType> | ConfigType;
31
32
/** Create bundles from the asset graph (required) */
33
bundle(args: {
34
bundleGraph: MutableBundleGraph;
35
config: ConfigType;
36
options: PluginOptions;
37
logger: PluginLogger;
38
tracer: PluginTracer;
39
}): Promise<void>;
40
41
/** Optimize the bundle graph (required) */
42
optimize(args: {
43
bundleGraph: MutableBundleGraph;
44
config: ConfigType;
45
options: PluginOptions;
46
logger: PluginLogger;
47
}): Promise<void>;
48
}
49
```
50
51
**Usage Example:**
52
53
```javascript
54
import { Bundler } from "@parcel/plugin";
55
56
export default new Bundler({
57
// Load bundler configuration
58
loadConfig({config}) {
59
return {
60
minBundleSize: config.minBundleSize || 1000,
61
maxBundleSize: config.maxBundleSize || 100000,
62
splitChunks: config.splitChunks !== false
63
};
64
},
65
66
// Create bundles from assets (required)
67
async bundle({bundleGraph, config, logger}) {
68
// Get all assets
69
const assets = bundleGraph.getAssets();
70
71
// Create entry bundles
72
for (const entry of bundleGraph.getEntryAssets()) {
73
const bundle = bundleGraph.createBundle({
74
entryAsset: entry,
75
target: entry.env.context,
76
type: getOutputType(entry.type)
77
});
78
79
bundleGraph.addAssetToBundle(entry, bundle);
80
}
81
82
// Group related assets into shared bundles
83
if (config.splitChunks) {
84
await this.createSharedBundles(bundleGraph, config);
85
}
86
},
87
88
// Optimize bundle graph (required)
89
async optimize({bundleGraph, config, logger}) {
90
// Remove empty bundles
91
for (const bundle of bundleGraph.getBundles()) {
92
if (bundleGraph.getBundleAssets(bundle).length === 0) {
93
bundleGraph.removeBundle(bundle);
94
}
95
}
96
97
// Merge small bundles
98
await this.mergeSmallBundles(bundleGraph, config);
99
100
// Optimize bundle dependencies
101
await this.optimizeBundleDependencies(bundleGraph);
102
}
103
});
104
```
105
106
### Bundle Graph Operations
107
108
```typescript { .api }
109
/**
110
* Mutable bundle graph for creating and modifying bundles
111
*/
112
interface MutableBundleGraph {
113
/** Get all assets in the graph */
114
getAssets(): Array<Asset>;
115
116
/** Get entry assets */
117
getEntryAssets(): Array<Asset>;
118
119
/** Get all bundles */
120
getBundles(): Array<Bundle>;
121
122
/** Create a new bundle */
123
createBundle(options: CreateBundleOptions): Bundle;
124
125
/** Remove a bundle */
126
removeBundle(bundle: Bundle): void;
127
128
/** Add an asset to a bundle */
129
addAssetToBundle(asset: Asset, bundle: Bundle): void;
130
131
/** Remove an asset from a bundle */
132
removeAssetFromBundle(asset: Asset, bundle: Bundle): void;
133
134
/** Get assets in a specific bundle */
135
getBundleAssets(bundle: Bundle): Array<Asset>;
136
137
/** Create a dependency between bundles */
138
createBundleDependency(from: Bundle, to: Bundle): void;
139
140
/** Get bundles that depend on the given bundle */
141
getBundleDependents(bundle: Bundle): Array<Bundle>;
142
143
/** Get bundles that the given bundle depends on */
144
getBundleDependencies(bundle: Bundle): Array<Bundle>;
145
}
146
147
/**
148
* Options for creating a new bundle
149
*/
150
interface CreateBundleOptions {
151
/** Entry asset for the bundle */
152
entryAsset?: Asset;
153
154
/** Bundle target */
155
target: Target;
156
157
/** Bundle output type */
158
type: string;
159
160
/** Whether this bundle needs a stable name */
161
needsStableName?: boolean;
162
163
/** Bundle behavior */
164
bundleBehavior?: BundleBehavior;
165
166
/** Bundle priority */
167
priority?: BundlePriority;
168
169
/** Environment for this bundle */
170
env?: EnvironmentOptions;
171
}
172
173
/**
174
* Bundle priority levels
175
*/
176
type BundlePriority = "sync" | "parallel" | "lazy";
177
```
178
179
### Bundle Information
180
181
```typescript { .api }
182
/**
183
* A bundle in the bundle graph
184
*/
185
interface Bundle {
186
/** Bundle ID */
187
id: string;
188
189
/** Bundle type */
190
type: string;
191
192
/** Target environment */
193
target: Target;
194
195
/** Entry asset if this is an entry bundle */
196
entryAsset?: Asset;
197
198
/** Main entry asset */
199
mainEntryAsset?: Asset;
200
201
/** Bundle file path */
202
filePath?: FilePath;
203
204
/** Bundle name */
205
name?: string;
206
207
/** Bundle display name */
208
displayName?: string;
209
210
/** Bundle statistics */
211
stats: BundleStats;
212
213
/** Environment for this bundle */
214
env: Environment;
215
216
/** Whether this bundle needs a stable name */
217
needsStableName: boolean;
218
219
/** Bundle behavior */
220
bundleBehavior?: BundleBehavior;
221
222
/** Bundle metadata */
223
meta: Record<string, any>;
224
}
225
226
/**
227
* Bundle statistics
228
*/
229
interface BundleStats {
230
/** Bundle size in bytes */
231
size: number;
232
233
/** Time to create bundle */
234
time: number;
235
}
236
```
237
238
### Common Bundling Strategies
239
240
**Entry Point Bundling:**
241
```javascript
242
// Create a bundle for each entry point
243
for (const entry of bundleGraph.getEntryAssets()) {
244
const bundle = bundleGraph.createBundle({
245
entryAsset: entry,
246
target: entry.target,
247
type: getOutputType(entry.type),
248
needsStableName: true
249
});
250
251
bundleGraph.addAssetToBundle(entry, bundle);
252
}
253
```
254
255
**Code Splitting:**
256
```javascript
257
// Create shared bundles for common dependencies
258
const sharedAssets = findSharedAssets(bundleGraph);
259
if (sharedAssets.length > 0) {
260
const sharedBundle = bundleGraph.createBundle({
261
target: primaryTarget,
262
type: 'js',
263
bundleBehavior: 'inline'
264
});
265
266
for (const asset of sharedAssets) {
267
bundleGraph.addAssetToBundle(asset, sharedBundle);
268
}
269
}
270
```
271
272
**Size-based Optimization:**
273
```javascript
274
// Merge small bundles to reduce HTTP requests
275
const smallBundles = bundleGraph.getBundles().filter(bundle =>
276
bundle.stats.size < config.minBundleSize
277
);
278
279
for (const smallBundle of smallBundles) {
280
const targetBundle = findMergeTarget(smallBundle, bundleGraph);
281
if (targetBundle) {
282
mergeBundles(smallBundle, targetBundle, bundleGraph);
283
}
284
}
285
```