0
# Bundle Building
1
2
Functionality for building source-mapped bundles by concatenating strings and their corresponding source maps, producing indexed source maps for efficient debugging.
3
4
## Capabilities
5
6
### BundleBuilder Class
7
8
Main class for building bundles with source maps by concatenating code sections and composing their source maps.
9
10
```javascript { .api }
11
/**
12
* Builds a source-mapped bundle by concatenating strings and their source maps
13
*/
14
class BundleBuilder {
15
/**
16
* Creates a new bundle builder
17
* @param file - Name of the output bundle file
18
*/
19
constructor(file: string);
20
21
/**
22
* Append code with optional source map to the bundle
23
* @param code - Code string to append
24
* @param map - Optional source map for the code
25
* @returns Self for method chaining
26
*/
27
append(code: string, map?: MixedSourceMap): this;
28
29
/**
30
* Get the concatenated code for the bundle
31
* @returns Complete bundle code
32
*/
33
getCode(): string;
34
35
/**
36
* Get the composed source map for the bundle
37
* @returns Indexed source map covering the entire bundle
38
*/
39
getMap(): MixedSourceMap;
40
}
41
```
42
43
**Usage Examples:**
44
45
```javascript
46
const { BundleBuilder } = require("metro-source-map");
47
48
// Create a bundle builder
49
const builder = new BundleBuilder("bundle.js");
50
51
// Append code sections with their source maps
52
builder
53
.append("// Header comment\n") // No source map
54
.append("console.log('module1');\n", module1SourceMap)
55
.append("console.log('module2');\n", module2SourceMap)
56
.append("// Footer\n"); // No source map
57
58
// Get the final bundle
59
const bundleCode = builder.getCode();
60
const bundleMap = builder.getMap();
61
62
console.log(bundleCode);
63
// Output:
64
// // Header comment
65
// console.log('module1');
66
// console.log('module2');
67
// // Footer
68
69
console.log(bundleMap.sections.length); // Number of source map sections
70
```
71
72
### Index Map Creation
73
74
Utility function for creating empty indexed source maps.
75
76
```javascript { .api }
77
/**
78
* Creates an indexed source map from file and sections
79
* @param file - File name for the source map
80
* @param sections - Array of source map sections with offsets
81
* @returns Indexed source map structure
82
*/
83
function createIndexMap(file: string, sections: Array<IndexMapSection>): IndexMap;
84
```
85
86
**Usage Examples:**
87
88
```javascript
89
const { createIndexMap } = require("metro-source-map");
90
91
// Create an index map with sections
92
const sections = [
93
{
94
offset: { line: 0, column: 0 },
95
map: someBasicSourceMap
96
}
97
];
98
const indexMap = createIndexMap("output.js", sections);
99
console.log(indexMap);
100
// {
101
// version: 3,
102
// sections: [...],
103
// file: "output.js"
104
// }
105
106
// Use with BundleBuilder for custom initialization
107
const builder = new BundleBuilder("custom.js");
108
// Builder internally uses createIndexMap
109
```
110
111
### Advanced Bundle Building
112
113
```javascript
114
const { BundleBuilder } = require("metro-source-map");
115
116
// Building a complex bundle with mixed content types
117
const builder = new BundleBuilder("app.bundle.js");
118
119
// Add a header without source map
120
builder.append("(function() {\n");
121
122
// Add main application modules with source maps
123
const modules = [
124
{ code: "var utils = require('./utils');\n", map: utilsSourceMap },
125
{ code: "var app = require('./app');\n", map: appSourceMap },
126
{ code: "app.start();\n", map: startSourceMap }
127
];
128
129
modules.forEach(({ code, map }) => {
130
builder.append(code, map);
131
});
132
133
// Add a footer without source map
134
builder.append("})();\n");
135
136
// Generate the final bundle
137
const result = {
138
code: builder.getCode(),
139
map: builder.getMap()
140
};
141
142
// The resulting map will be an indexed source map with sections
143
// corresponding to each piece of code that had an associated source map
144
console.log(result.map.sections.length); // Number of mapped sections
145
```
146
147
### Index Map Structure
148
149
```javascript { .api }
150
/**
151
* Indexed source map format for bundles
152
*/
153
interface IndexMap {
154
/** Source map version (always 3) */
155
version: number;
156
/** Output file name */
157
file?: string;
158
/** Array of source map sections */
159
sections: Array<IndexMapSection>;
160
/** Facebook extension: byte offsets */
161
x_facebook_offsets?: Array<number>;
162
/** Metro extension: module paths */
163
x_metro_module_paths?: Array<string>;
164
/** Facebook extension: segment map */
165
x_facebook_segments?: FBSegmentMap;
166
/** Hermes extension: function offsets */
167
x_hermes_function_offsets?: HermesFunctionOffsets;
168
/** These fields are void in IndexMap to maintain type safety */
169
mappings?: void;
170
sourcesContent?: void;
171
x_facebook_sources?: void;
172
x_google_ignoreList?: void;
173
}
174
175
/**
176
* Individual section within an indexed source map
177
*/
178
interface IndexMapSection {
179
/** Source map for this section (can be basic or indexed) */
180
map: IndexMap | BasicSourceMap;
181
/** Offset where this section starts in the bundle */
182
offset: {
183
/** Line offset (0-based) */
184
line: number;
185
/** Column offset (0-based) */
186
column: number;
187
};
188
}
189
```
190
191
### Integration with Source Map Types
192
193
```javascript
194
const { BundleBuilder, Generator, fromRawMappings } = require("metro-source-map");
195
196
// Building a bundle using generated source maps
197
const builder = new BundleBuilder("output.js");
198
199
// Generate source maps for individual modules
200
const module1Map = fromRawMappings([{
201
map: [[1, 0, 1, 0], [1, 8, 1, 8]],
202
path: "src/module1.js",
203
source: "console.log('one');",
204
code: "console.log('one');",
205
isIgnored: false
206
}]).toMap();
207
208
const module2Map = fromRawMappings([{
209
map: [[1, 0, 1, 0], [1, 8, 1, 8]],
210
path: "src/module2.js",
211
source: "console.log('two');",
212
code: "console.log('two');",
213
isIgnored: false
214
}]).toMap();
215
216
// Build the bundle
217
builder
218
.append("console.log('one');\n", module1Map)
219
.append("console.log('two');\n", module2Map);
220
221
const finalMap = builder.getMap();
222
// finalMap will be an IndexMap with 2 sections
223
```
224
225
## Error Handling
226
227
BundleBuilder operations may encounter errors in the following cases:
228
229
- **Invalid source maps**: When provided source maps are malformed
230
- **Empty builder**: When `getMap()` or `getCode()` is called before any content is appended
231
232
```javascript
233
const { BundleBuilder } = require("metro-source-map");
234
235
try {
236
const builder = new BundleBuilder("test.js");
237
builder.append("console.log('test');", invalidSourceMap);
238
const map = builder.getMap();
239
} catch (error) {
240
console.error('Bundle building failed:', error);
241
}
242
243
// Safe usage with validation
244
const builder = new BundleBuilder("safe.js");
245
if (someCode && someCode.length > 0) {
246
builder.append(someCode, optionalSourceMap);
247
}
248
```