0
# Module System Transformation
1
2
Transforms ES6 import/export statements into CommonJS require/exports for Metro's module system, enabling modern JavaScript syntax while maintaining compatibility with Metro's bundling pipeline.
3
4
## Capabilities
5
6
### Import Export Plugin
7
8
Converts ES6 modules to CommonJS format with customizable import/export handling.
9
10
```javascript { .api }
11
/**
12
* Creates a Babel plugin that transforms ES6 import/export to CommonJS
13
* @param context - Babel plugin context with types utility
14
* @returns Babel plugin object with comprehensive import/export handling
15
*/
16
function importExportPlugin(context: {
17
types: Types
18
}): PluginObj<State>;
19
20
interface ImportExportPluginOptions {
21
/** Name of the default import function (e.g., 'require') */
22
importDefault: string;
23
/** Name of the import all function (e.g., 'require') */
24
importAll: string;
25
/** Whether to resolve module paths to absolute paths */
26
resolve: boolean;
27
/** Output metadata object to track ES module status */
28
out?: { isESModule: boolean };
29
}
30
31
interface State {
32
exportAll: Array<{ file: string; loc?: BabelSourceLocation }>;
33
exportDefault: Array<{ local: string; loc?: BabelSourceLocation }>;
34
exportNamed: Array<{ local: string; remote: string; loc?: BabelSourceLocation }>;
35
imports: Array<{ node: Statement }>;
36
importDefault: BabelNode;
37
importAll: BabelNode;
38
opts: ImportExportPluginOptions;
39
}
40
```
41
42
**Usage Examples:**
43
44
```javascript
45
const babel = require("@babel/core");
46
const { importExportPlugin } = require("metro-transform-plugins");
47
48
const code = `
49
import React, { useState } from 'react';
50
import * as Utils from './utils';
51
export default function MyComponent() {
52
return <div>Hello</div>;
53
}
54
export const version = '1.0.0';
55
`;
56
57
const transformed = babel.transformSync(code, {
58
plugins: [
59
importExportPlugin({
60
types: babel.types,
61
opts: {
62
importDefault: 'require',
63
importAll: 'require',
64
resolve: false
65
}
66
})
67
]
68
});
69
70
// Result:
71
// Object.defineProperty(exports, '__esModule', {value: true});
72
// var React = require('react');
73
// var useState = require('react').useState;
74
// var Utils = require('./utils');
75
// function MyComponent() { return React.createElement('div', null, 'Hello'); }
76
// var version = '1.0.0';
77
// exports.default = MyComponent;
78
// exports.version = version;
79
```
80
81
### Import Transformations
82
83
Handles all ES6 import patterns and converts them to CommonJS require calls:
84
85
```javascript { .api }
86
/**
87
* Import declaration processing
88
* Converts various import patterns to require() calls
89
*/
90
91
// Default imports: import React from 'react'
92
// → var React = require('react');
93
94
// Named imports: import { useState, useEffect } from 'react'
95
// → var useState = require('react').useState;
96
// → var useEffect = require('react').useEffect;
97
98
// Namespace imports: import * as React from 'react'
99
// → var React = require('react');
100
101
// Side effect imports: import './styles.css'
102
// → require('./styles.css');
103
104
// Mixed imports: import React, { useState } from 'react'
105
// → var React = require('react');
106
// → var useState = require('react').useState;
107
```
108
109
### Export Transformations
110
111
Converts ES6 export syntax to CommonJS exports:
112
113
```javascript { .api }
114
/**
115
* Export declaration processing
116
* Handles default, named, and re-exports
117
*/
118
119
// Default exports: export default function() {}
120
// → function _default() {}
121
// → exports.default = _default;
122
123
// Named exports: export const value = 42;
124
// → const value = 42;
125
// → exports.value = value;
126
127
// Export from: export { something } from './other'
128
// → var _temp = require('./other');
129
// → exports.something = _temp.something;
130
131
// Export all: export * from './other'
132
// → var _required = require('./other');
133
// → for (var key in _required) { exports[key] = _required[key]; }
134
```
135
136
### Template-Based Code Generation
137
138
Uses Babel templates for consistent and reliable code generation:
139
140
```javascript { .api }
141
/**
142
* Babel templates used internally for code generation
143
*/
144
145
// Import template: var LOCAL = IMPORT(FILE);
146
const importTemplate = template.statement(`var LOCAL = IMPORT(FILE);`);
147
148
// Named import template: var LOCAL = require(FILE).REMOTE;
149
const importNamedTemplate = template.statement(`var LOCAL = require(FILE).REMOTE;`);
150
151
// Side effect template: require(FILE);
152
const importSideEffectTemplate = template.statement(`require(FILE);`);
153
154
// Export template: exports.REMOTE = LOCAL;
155
const exportTemplate = template.statement(`exports.REMOTE = LOCAL;`);
156
157
// ES module marker: Object.defineProperty(exports, '__esModule', {value: true});
158
const esModuleExportTemplate = template.statement(`
159
Object.defineProperty(exports, '__esModule', {value: true});
160
`);
161
```
162
163
### Module Resolution
164
165
Optional module path resolution to fully-qualified paths:
166
167
```javascript { .api }
168
/**
169
* Path resolution functionality
170
* @param node - The module specifier node
171
* @param resolve - Whether to resolve to absolute path
172
* @returns Expression node with resolved path or original node
173
*/
174
function resolvePath<TNode extends Node>(
175
node: TNode,
176
resolve: boolean
177
): BabelNodeExpression | TNode;
178
179
// When resolve: true
180
// import './utils' → require(require.resolve('./utils'))
181
// import 'lodash' → require(require.resolve('lodash'))
182
```
183
184
### Shared Module Optimization
185
186
Optimizes multiple named imports from the same module:
187
188
```javascript
189
// Before optimization
190
import { a, b, c, d } from 'large-module';
191
192
// After optimization
193
var _largeModule = require('large-module');
194
var a = _largeModule.a;
195
var b = _largeModule.b;
196
var c = _largeModule.c;
197
var d = _largeModule.d;
198
```
199
200
### ES Module Detection
201
202
Automatically marks transformed modules as ES modules:
203
204
```javascript { .api }
205
/**
206
* ES Module metadata tracking
207
* Adds __esModule property when exports are detected
208
*/
209
210
// When any exports are found:
211
Object.defineProperty(exports, '__esModule', {value: true});
212
213
// Updates options.out.isESModule if provided
214
if (state.opts.out) {
215
state.opts.out.isESModule = true; // or false if no exports
216
}
217
```
218
219
### Location Preservation
220
221
Maintains source location information for debugging and source maps:
222
223
```javascript { .api }
224
/**
225
* Source location preservation
226
* @param node - AST node or array of nodes
227
* @param loc - Source location to apply
228
* @returns Node(s) with preserved location information
229
*/
230
function withLocation<TNode extends BabelNode>(
231
node: TNode | ReadonlyArray<TNode>,
232
loc?: BabelNodeSourceLocation
233
): TNode | Array<TNode>;
234
```
235
236
### Variable Renaming
237
238
Renames conflicting variables to avoid namespace collisions:
239
240
```javascript
241
// Automatically renames variables that might conflict with Metro's module wrapper:
242
// - 'module' → '_module'
243
// - 'global' → '_global'
244
// - 'exports' → '_exports'
245
// - 'require' → '_require'
246
```
247
248
### Module String Names
249
250
Handles modern JavaScript module string names syntax:
251
252
```javascript { .api }
253
// Throws error for unsupported module string names:
254
// export { "module-name" as something } from './module';
255
// → Error: Module string names are not supported
256
```