0
# Code Generation Utilities
1
2
Utility functions for Metro code generation including parameter injection, pseudoglobal variable management, and cache key generation for build optimization.
3
4
## Capabilities
5
6
### Add Parameters to Define Call
7
8
Simple utility for adding additional parameters to Metro's define() calls in generated bundle code.
9
10
```javascript { .api }
11
/**
12
* Adds additional parameters to the end of define calls in Metro bundle code
13
* @param code - The source code containing a define() call
14
* @param paramsToAdd - Additional parameters to append
15
* @returns Modified code with additional parameters
16
*/
17
function addParamsToDefineCall(
18
code: string,
19
...paramsToAdd: Array<mixed>
20
): string;
21
```
22
23
**Usage Examples:**
24
25
```javascript
26
const { addParamsToDefineCall } = require("metro-transform-plugins");
27
28
// Basic usage - add metadata to define call
29
const originalCode = `define(['dep1', 'dep2'], function(a, b) {
30
return a + b;
31
});`;
32
33
const enhanced = addParamsToDefineCall(
34
originalCode,
35
{ meta: true, version: '1.0.0' },
36
['extra', 'data'],
37
undefined,
38
null
39
);
40
41
// Result:
42
// define(['dep1', 'dep2'], function(a, b) {
43
// return a + b;
44
// },{"meta":true,"version":"1.0.0"},["extra","data"],undefined,null);
45
46
// Practical use case - adding dependency map
47
const withDependencyMap = addParamsToDefineCall(
48
moduleCode,
49
dependencyMap,
50
inverseDependencies
51
);
52
```
53
54
### Parameter Serialization
55
56
Handles different parameter types with proper JSON serialization:
57
58
```javascript { .api }
59
/**
60
* Parameter serialization rules:
61
* - Objects and arrays: JSON.stringify()
62
* - undefined: 'undefined' (string literal)
63
* - null: 'null' (JSON serialized)
64
* - Other values: JSON.stringify()
65
*/
66
67
// Examples of parameter handling:
68
addParamsToDefineCall(code,
69
{ key: 'value' }, // → {"key":"value"}
70
['array', 'data'], // → ["array","data"]
71
undefined, // → undefined (literal)
72
null, // → null
73
'string', // → "string"
74
42, // → 42
75
true // → true
76
);
77
```
78
79
### Normalize Pseudoglobals
80
81
Shortens long parameter names in Metro's module wrapper functions to reduce bundle size.
82
83
```javascript { .api }
84
/**
85
* Normalizes and shortens pseudoglobal variable names in Metro modules
86
* @param ast - Babel AST of the module
87
* @param options - Configuration options
88
* @returns Array of renamed parameter names
89
*/
90
function normalizePseudoglobals(
91
ast: BabelNode,
92
options?: NormalizePseudoGlobalsOptions
93
): ReadonlyArray<string>;
94
95
interface NormalizePseudoGlobalsOptions {
96
/** Array of names that cannot be shortened */
97
reservedNames: ReadonlyArray<string>;
98
}
99
```
100
101
**Usage Examples:**
102
103
```javascript
104
const babel = require("@babel/core");
105
const { normalizePseudoglobals } = require("metro-transform-plugins");
106
107
// Original Metro module wrapper
108
const moduleCode = `
109
(function(XMLHttpRequest, FileSystemInterface, DatabaseConnection) {
110
// Module code using long parameter names
111
const xhr = new XMLHttpRequest();
112
const fs = FileSystemInterface.create();
113
const db = DatabaseConnection.connect();
114
});
115
`;
116
117
const ast = babel.parseSync(moduleCode);
118
const renamedParams = normalizePseudoglobals(ast, {
119
reservedNames: ['require', 'module', 'exports']
120
});
121
122
// Result: ['x', 'f', 'd'] - shortened semantic names
123
// Transformed code:
124
// (function(x, f, d) {
125
// const xhr = new x();
126
// const fs = f.create();
127
// const db = d.connect();
128
// });
129
```
130
131
### Semantic Name Generation
132
133
Generates meaningful short names based on original parameter names:
134
135
```javascript { .api }
136
/**
137
* Semantic name generation algorithm
138
* Extracts meaningful characters from original names
139
*/
140
141
// Examples of name shortening:
142
'XMLHttpRequest' → 'x' // First letter
143
'FileSystemInterface' → 'f' // First letter of each word
144
'DatabaseConnection' → 'd' // First letter
145
'React' → 'r' // Simple first letter
146
'MyCustomUtility' → 'm' // First letter
147
'HTTPClient' → 'h' // First letter
148
149
// Pattern matching (case insensitive):
150
// - ^[^A-Za-z]*([A-Za-z]) - First letter after non-letters
151
// - ([A-Z])[a-z] - Capital letter followed by lowercase
152
// - ([A-Z])[A-Z]+$ - Capital letter in all-caps sequence
153
```
154
155
### Name Conflict Resolution
156
157
Handles naming conflicts and reserved names:
158
159
```javascript { .api }
160
/**
161
* Conflict resolution strategy
162
* Ensures unique names and respects reserved names
163
*/
164
165
// When conflicts occur:
166
'XMLHttpRequest' → 'x'
167
'XMLParser' → 'x2' // generateUid creates unique name
168
169
// Reserved names are never used:
170
const options = { reservedNames: ['r', 'x', 'm'] };
171
'React' → 'r2' // 'r' is reserved, so generates alternative
172
173
// Scope-aware renaming:
174
// Uses Babel's scope.rename() to properly update all references
175
// Handles nested scopes correctly
176
// Updates program scope references and UIDs
177
```
178
179
### Cache Key Generation
180
181
Provides file paths for Metro's cache key generation system:
182
183
```javascript { .api }
184
/**
185
* Returns array of file paths used for transform plugin cache keys
186
* @returns Array of absolute file paths for cache key generation
187
*/
188
function getTransformPluginCacheKeyFiles(): ReadonlyArray<string>;
189
```
190
191
**Usage Examples:**
192
193
```javascript
194
const { getTransformPluginCacheKeyFiles } = require("metro-transform-plugins");
195
196
// Get cache key files for Metro configuration
197
const cacheKeyFiles = getTransformPluginCacheKeyFiles();
198
199
// Result array contains paths to:
200
// - /path/to/metro-transform-plugins/src/index.js
201
// - /path/to/metro-transform-plugins/src/constant-folding-plugin.js
202
// - /path/to/metro-transform-plugins/src/import-export-plugin.js
203
// - /path/to/metro-transform-plugins/src/inline-plugin.js
204
// - /path/to/metro-transform-plugins/src/inline-requires-plugin.js
205
// - /path/to/metro-transform-plugins/src/normalizePseudoglobals.js
206
207
// Use in Metro configuration:
208
module.exports = {
209
transformer: {
210
babelTransformerPath: require.resolve('./custom-transformer'),
211
212
// Include plugin files in cache key calculation
213
additionalFiles: getTransformPluginCacheKeyFiles()
214
}
215
};
216
```
217
218
### Module Wrapper Detection
219
220
Correctly identifies Metro's module wrapper function structure:
221
222
```javascript { .api }
223
/**
224
* Metro module wrapper pattern detection
225
* Identifies the specific AST structure of Metro modules
226
*/
227
228
// Expected Metro module structure:
229
// Program
230
// └── ExpressionStatement
231
// └── CallExpression (function invocation)
232
// └── FunctionExpression (module wrapper)
233
// ├── params[] (pseudoglobal parameters)
234
// └── body (module content)
235
236
// Only processes modules matching this exact structure
237
// Safely ignores non-Metro code patterns
238
```
239
240
### Pseudoglobal Parameter Processing
241
242
Handles the specific parameter patterns used by Metro:
243
244
```javascript
245
// Typical Metro pseudoglobal parameters:
246
['__d', 'global', 'require', 'module', 'exports', 'XMLHttpRequest', 'fetch', ...]
247
248
// Processing logic:
249
// 1. Extract parameter names from function signature
250
// 2. Filter out reserved names (like 'require', 'module', 'exports')
251
// 3. Generate semantic short names for remaining parameters
252
// 4. Check for conflicts and resolve using generateUid
253
// 5. Rename all references using Babel scope manipulation
254
// 6. Return array of final shortened names
255
```
256
257
### Advanced Renaming Features
258
259
Provides sophisticated variable renaming capabilities:
260
261
```javascript { .api }
262
/**
263
* Advanced scope-aware renaming
264
* Handles complex variable binding scenarios
265
*/
266
267
// Checks multiple binding types:
268
scope.hasLabel(name) // Label declarations (label:)
269
scope.hasBinding(name) // Variable bindings (var, let, const)
270
scope.hasGlobal(name) // Global variable references
271
scope.hasReference(name) // Any reference to the name
272
273
// Program scope management:
274
// Updates program scope references map
275
// Updates program scope UIDs map
276
// Ensures Metro's module system compatibility
277
278
// Graceful handling of edge cases:
279
// - Names that can't be shortened (throws descriptive errors)
280
// - Duplicate semantic matches (generates unique alternatives)
281
// - Reserved name conflicts (uses generateUid for alternatives)
282
```