Skip to content

Support .mjs and other ESM config files#1557

Closed
robhogan wants to merge 1 commit intomainfrom
export-D80267431
Closed

Support .mjs and other ESM config files#1557
robhogan wants to merge 1 commit intomainfrom
export-D80267431

Conversation

@robhogan
Copy link
Contributor

@robhogan robhogan commented Aug 14, 2025

Summary:
Support ESM metro.config.js files, including with top-level await, with either the .js extension (as long as the nearest package.json does not have "type": "commonjs"), or the .mjs extension.

Implementation

Since Metro now requires Node.js >= 20.19, most supported versions should have backported Node-native require(esm) support (exception: early releases of 22.x) - this works for any sync ESM graphs, as well as of course CommonJS.

When require(esm) throws (eg top-level await, or early Node 22), we fall back to await import.

We could simply only use await import(), unfortunately the main problem with that is poor support in Jest in current Node (TypeError: A dynamic import callback was invoked without --experimental-vm-modules), which is also why we're not adding a test fixture.

Changelog:

 - **[Feature]** Support ESM `metro.config.js` / `metro.config.mjs`

Differential Revision: D80267431

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 14, 2025
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D80267431

@robhogan robhogan changed the title Support .mjs and `"type": "module" config files Support .mjs and other ESM config files Aug 14, 2025
robhogan added a commit that referenced this pull request Aug 15, 2025
Summary:

Support ESM `metro.config.js` files, including with top-level await, with either the `.js` extension (as long as the nearest `package.json` does not have `"type": "commonjs"`), or the `.mjs` extension.

## Implementation
Since Metro now requires Node.js >= 20.19, most supported versions should have backported Node-native `require(esm)` support (exception: early releases of 22.x) - this works for any sync ESM graphs, as well as of course CommonJS.

When `require(esm)` throws (eg top-level await, or early Node 22), we fall back to `await import`.

We could simply only use `await import()`, unfortunately the main problem with that is poor support in Jest in current Node.js (`TypeError: A dynamic import callback was invoked without --experimental-vm-modules`), which is also why we're not adding a test fixture.

Changelog:
```
 - **[Feature]** Support ESM `metro.config.js` / `metro.config.mjs`
```

Reviewed By: huntie

Differential Revision: D80267431
Summary:
Pull Request resolved: #1557

Support ESM `metro.config.js` files, including with top-level await, with either the `.js` extension (as long as the nearest `package.json` does not have `"type": "commonjs"`), or the `.mjs` extension.

## Implementation
Since Metro now requires Node.js >= 20.19, most supported versions should have backported Node-native `require(esm)` support (exception: early releases of 22.x) - this works for any sync ESM graphs, as well as of course CommonJS.

When `require(esm)` throws (eg top-level await, or early Node 22), we fall back to `await import`.

We could simply only use `await import()`, unfortunately the main problem with that is poor support in Jest in current Node.js (`TypeError: A dynamic import callback was invoked without --experimental-vm-modules`), which is also why we're not adding a test fixture.

Changelog:
```
 - **[Feature]** Support ESM `metro.config.js` / `metro.config.mjs`
```

Reviewed By: huntie

Differential Revision: D80267431
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D80267431

robhogan added a commit that referenced this pull request Aug 15, 2025
Summary:

Support ESM `metro.config.js` files, including with top-level await, with either the `.js` extension (as long as the nearest `package.json` does not have `"type": "commonjs"`), or the `.mjs` extension.

## Implementation
Since Metro now requires Node.js >= 20.19, most supported versions should have backported Node-native `require(esm)` support (exception: early releases of 22.x) - this works for any sync ESM graphs, as well as of course CommonJS.

When `require(esm)` throws (eg top-level await, or early Node 22), we fall back to `await import`.

We could simply only use `await import()`, unfortunately the main problem with that is poor support in Jest in current Node.js (`TypeError: A dynamic import callback was invoked without --experimental-vm-modules`), which is also why we're not adding a test fixture.

Changelog:
```
 - **[Feature]** Support ESM `metro.config.js` / `metro.config.mjs`
```

Reviewed By: huntie

Differential Revision: D80267431
@facebook-github-bot
Copy link
Contributor

This pull request has been merged in 974d8e5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported Merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants