0
# Require Optimization
1
2
Inlines top-level require() calls to enable lazy loading and reduce bundle overhead by replacing variable assignments with direct require() calls at usage sites.
3
4
## Capabilities
5
6
### Inline Requires Plugin
7
8
Transforms top-level require() assignments into inline require() calls for improved lazy loading and bundle performance.
9
10
```javascript { .api }
11
/**
12
* Creates a Babel plugin that inlines require() calls
13
* @returns Babel plugin object that processes require() assignments
14
*/
15
function inlineRequiresPlugin(): PluginObj<State>;
16
17
interface InlineRequiresPluginOptions {
18
/** Array of require calls to ignore (e.g., ['fs', 'path']) */
19
ignoredRequires?: ReadonlyArray<string>;
20
/** Function names that can be inlined (default: ['require']) */
21
inlineableCalls?: ReadonlyArray<string>;
22
/** Modules that should not be memoized even when memoizeCalls is true */
23
nonMemoizedModules?: ReadonlyArray<string>;
24
/** Whether to memoize repeated require() calls (default: false) */
25
memoizeCalls?: boolean;
26
}
27
28
interface State {
29
opts?: InlineRequiresPluginOptions;
30
ignoredRequires: Set<string>;
31
inlineableCalls: Set<string>;
32
membersAssigned: Map<string, Set<string>>;
33
}
34
```
35
36
**Usage Examples:**
37
38
```javascript
39
const babel = require("@babel/core");
40
const { inlineRequiresPlugin } = require("metro-transform-plugins");
41
42
const code = `
43
var fs = require('fs');
44
var path = require('path');
45
var lodash = require('lodash');
46
47
function readConfig() {
48
return fs.readFileSync('./config.json', 'utf8');
49
}
50
51
function processPath(inputPath) {
52
return path.join(inputPath, 'processed');
53
}
54
55
console.log(lodash.map([1, 2, 3], x => x * 2));
56
`;
57
58
const transformed = babel.transformSync(code, {
59
plugins: [
60
[inlineRequiresPlugin, {
61
ignoredRequires: ['fs'], // Don't inline fs module
62
memoizeCalls: true
63
}]
64
]
65
});
66
67
// Result:
68
// var fs = require('fs'); // Not inlined (in ignoredRequires)
69
// var _path;
70
// var _lodash;
71
//
72
// function readConfig() {
73
// return fs.readFileSync('./config.json', 'utf8');
74
// }
75
//
76
// function processPath(inputPath) {
77
// return (_path || (_path = require('path'))).join(inputPath, 'processed');
78
// }
79
//
80
// console.log((_lodash || (_lodash = require('lodash'))).map([1, 2, 3], x => x * 2));
81
```
82
83
### Simple Variable Inlining
84
85
Handles basic require() variable assignments:
86
87
```javascript { .api }
88
/**
89
* Simple require assignment inlining
90
* var module = require('module-name');
91
* module.method() → require('module-name').method()
92
*/
93
94
// Before transformation
95
var React = require('react');
96
var Component = React.Component;
97
function render() {
98
return React.createElement('div');
99
}
100
101
// After transformation
102
var Component = require('react').Component;
103
function render() {
104
return require('react').createElement('div');
105
}
106
```
107
108
### Member Expression Inlining
109
110
Inlines require() calls with property access:
111
112
```javascript { .api }
113
/**
114
* Member expression require inlining
115
* var member = require('module').property;
116
* member.method() → require('module').property.method()
117
*/
118
119
// Before transformation
120
var createElement = require('react').createElement;
121
var Fragment = require('react').Fragment;
122
123
function component() {
124
return createElement(Fragment, null, 'Hello');
125
}
126
127
// After transformation
128
function component() {
129
return require('react').createElement(require('react').Fragment, null, 'Hello');
130
}
131
```
132
133
### Destructuring Assignment Inlining
134
135
Handles ES6 destructuring patterns:
136
137
```javascript { .api }
138
/**
139
* Destructuring assignment inlining
140
* const {method} = require('module');
141
* method() → require('module').method()
142
*/
143
144
// Before transformation
145
const { useState, useEffect } = require('react');
146
const { join, resolve } = require('path');
147
148
function component() {
149
const [state, setState] = useState(0);
150
const configPath = join(__dirname, 'config.json');
151
return state;
152
}
153
154
// After transformation
155
function component() {
156
const [state, setState] = require('react').useState(0);
157
const configPath = require('path').join(__dirname, 'config.json');
158
return state;
159
}
160
```
161
162
### Memoized Require Calls
163
164
Optional memoization to avoid repeated module loading:
165
166
```javascript { .api }
167
/**
168
* Memoized require pattern (when memoizeCalls: true)
169
* Creates memoization variables for frequently used modules
170
*/
171
172
// Before transformation (with memoizeCalls: true)
173
var utils = require('./utils');
174
function a() { return utils.helper1(); }
175
function b() { return utils.helper2(); }
176
function c() { return utils.helper3(); }
177
178
// After transformation
179
var _utils;
180
function a() { return (_utils || (_utils = require('./utils'))).helper1(); }
181
function b() { return (_utils || (_utils = require('./utils'))).helper2(); }
182
function c() { return (_utils || (_utils = require('./utils'))).helper3(); }
183
```
184
185
### Require.resolve Support
186
187
Handles require.resolve() patterns for module resolution:
188
189
```javascript { .api }
190
/**
191
* require.resolve() call inlining
192
* var module = require(require.resolve('module-name'));
193
*/
194
195
// Before transformation
196
var config = require(require.resolve('./config'));
197
config.setting = 'value';
198
199
// After transformation
200
require(require.resolve('./config')).setting = 'value';
201
```
202
203
### Safety Checks and Exclusions
204
205
Implements safety mechanisms to prevent breaking transformations:
206
207
```javascript { .api }
208
/**
209
* Safety exclusions prevent incorrect inlining
210
*/
211
212
// Excluded: Modules with member assignments
213
var utils = require('./utils');
214
utils.cache = {}; // Member assignment detected - won't inline utils
215
216
// Excluded: Non-constant violations
217
var fs = require('fs');
218
fs = mockFs; // Reassignment - won't inline fs
219
220
// Excluded: Babel runtime modules (automatically)
221
var helper = require('@babel/runtime/helpers/something'); // Never inlined
222
223
// Excluded: Modules in ignoredRequires option
224
var path = require('path'); // Won't inline if 'path' in ignoredRequires
225
```
226
227
### Block-Level Optimization
228
229
Optimizes memoization based on code block structure:
230
231
```javascript { .api }
232
/**
233
* Block-level memoization optimization
234
* Uses different patterns based on code structure
235
*/
236
237
// Within same block - uses memoization variable
238
function sameBlock() {
239
const a = (_utils || (_utils = require('./utils'))).methodA();
240
const b = _utils.methodB(); // Reuses memoized variable
241
}
242
243
// Across different blocks - uses full memoization expression
244
function differentBlocks() {
245
if (condition) {
246
return (_utils || (_utils = require('./utils'))).methodA();
247
} else {
248
return (_utils || (_utils = require('./utils'))).methodB();
249
}
250
}
251
```
252
253
### Source Location Preservation
254
255
Maintains original source locations for debugging and error reporting:
256
257
```javascript { .api }
258
/**
259
* Source location tracking
260
* Preserves original require() call location information
261
*/
262
263
// Adds METRO_INLINE_REQUIRES_INIT_LOC metadata to inlined expressions
264
// This helps with:
265
// - Source map accuracy
266
// - Error stack trace precision
267
// - Debugging experience
268
```
269
270
### Custom Inlineable Calls
271
272
Supports custom function names beyond 'require':
273
274
```javascript { .api }
275
/**
276
* Custom inlineable function support
277
* @param inlineableCalls - Array of function names to inline
278
*/
279
280
// Configuration: inlineableCalls: ['require', 'load', 'import']
281
var module1 = require('module1'); // Inlined
282
var module2 = load('module2'); // Inlined
283
var module3 = import('module3'); // Inlined
284
var module4 = customLoader('module4'); // Not inlined
285
```
286
287
### Non-Memoized Modules
288
289
Prevents memoization for specific modules that should always be fresh:
290
291
```javascript { .api }
292
/**
293
* Non-memoized module handling
294
* @param nonMemoizedModules - Modules to never memoize
295
*/
296
297
// Configuration: nonMemoizedModules: ['./config', 'dotenv']
298
var config = require('./config'); // Always fresh, never memoized
299
var dotenv = require('dotenv'); // Always fresh, never memoized
300
var utils = require('./utils'); // Can be memoized (if memoizeCalls: true)
301
```
302
303
### Error Recovery
304
305
Graceful handling of transformation failures:
306
307
```javascript { .api }
308
/**
309
* Error recovery mechanism
310
* If replacement fails, keeps original require() assignment
311
*/
312
313
// If inlining fails (e.g., due to complex AST structure):
314
// - Logs the error internally
315
// - Preserves original require() assignment
316
// - Continues processing other requires
317
// - Prevents build failures from transformation issues
318
```