Repository navigation
Support ESM react-native.config files #2167
Description
Activity
FWIW, we intend to update cosmiconfig in Metro to support
metro.config.mjs(andtype: module) as soon as possible - one thing that's holding us back is that we ran into nodejs/node#35889 - use ofawait importis liable to segfault Node VMs - and we were seeing this intermittently in Jest (integration tests that involved using cosmiconfig) as soon as we tried to update. I'll be trying again as soon as we've moved our CI to Node 20.Related: react/metro#916
Reacted by Kræn Hansen@robhogan so it looks like we're blocked on Metro? Please keep us updated, we'd happily implement this
I wouldn't say blocked - I can't think of any technical reason this couldn't go into the CLI before Metro, although it might be less surprising if we were consistent.
I just wanted to share the experience we had with this upgrade - it might be that you're similarly blocked by Jest under Node<20, if you have integration tests that don't mock out cosmiconfig.
Reacted by Kræn HansenI just wanted to share the experience we had with this upgrade - it might be that you're similarly blocked by Jest under Node<20, if you have integration tests that don't mock out cosmiconfig.
Yes, we have - and I tried updating
cosmiconfigand tests are failing because of this reason.Reacted by Kræn Hansenone thing that's holding us back is that we ran into nodejs/node#35889 - use of
await importis liable to segfault Node VMs@robhogan seems like that issue is now resolved - in case this should be noted anywhere as this blocker being removed.
Reacted by Kræn Hansen, libreom and Bill O'Moreone thing that's holding us back is that we ran into nodejs/node#35889 - use of
await importis liable to segfault Node VMs@robhogan seems like that issue is now resolved - in case this should be noted anywhere as this blocker being removed.
Unfortunately it's only resolved for Node 20, and won't be backported, so it'll need to wait until we're on Node 20 (for CI, at least - there's probably no risk in prod as long as we don't use this in a Node VM).
Reacted by Karl HorkyOk, thanks for the answer! So I guess it's waiting until
facebook/react-nativeandfacebook/metroare on Node.js version 20?Taking a quick look in those repos, maybe that is tracked here?
facebook/react-nativeCI config: https://github.com/facebook/react-native/blob/575507dd61298be2f3071e0fc01ed9715cbd7a66/.circleci/config.yml#L52facebook/react-nativepackage.json->engines: https://github.com/facebook/react-native/blob/575507dd61298be2f3071e0fc01ed9715cbd7a66/packages/react-native/package.json#L23-L25facebook/metroCI config: https://github.com/facebook/metro/blob/84956bd11ab0ded6f06a867120980f8524e9cab6/.circleci/config.yml#L12-L15facebook/metropackage.json->engines: https://github.com/facebook/metro/blob/84956bd11ab0ded6f06a867120980f8524e9cab6/package.json#L93-L95
Or does this also have to do with the
react-native-community/clirepo? I see a couple of references to Node.js version numbers here, which still include v18:cli/.github/workflows/test.yml
Line 30 in 61b6be6
node-version: [18, 20] cli/.github/workflows/test.yml
Line 47 in 61b6be6
node-version: [18, 20] Reacted by Kræn Hansen, Leonardo E. Dominguez and Szymon RybczakThere hasn't been any activity on this issue in the past 3 months, so it has been marked as stale and it will be closed automatically if no further activity occurs in the next 7 days.
not stale
So is there any way we can move this forward without waiting for React Native making Node.js 20 as a default version? I checked and EOL for Node.js 18 is set for 30 Apr 2025.
Reacted by ふぁー, Leonardo E. Dominguez, jack, James Lawson, MJRT and Johannes Schicklinghey! I've created a PR which adds support for ESM: #2453 👍
Reacted by Sasha, ふぁー, MJRT, Karl Horky, Mohamed Yassin, devanb, Johannes Schickling, Colten Krauter, Chafik and Kræn HansenReacted by Karl HorkyReacted by Sasha and Karl HorkyThanks @szymonrybczak for the PR. Hope it will get merged soon.
In the meantime, this was the last issue we had while migrating our monorepo to ESM so we had to find a solution (see below).
WARNING : this is a pretty ugly workaround and might not work for your use case. But in our case it does the job and unlocks us.
# Rename to .js so it can be found and switch temporarily to commonjs mv react-native.config.cjs react-native.config.js && sed -i '' 's/"type": "module"/"type": "commonjs"/g' package.json # Launch the build yarn react-native run-android # When the Gradle tasks have started, revert the temporary changes mv react-native.config.js react-native.config.cjs && git checkout -- package.json
Reacted by Kutsan KaplanReacted by Kutsan KaplanReacted by Karl Horky@c100k ah, I see 😅 I hope that you'll be able to remove this workaround soon! 👍
Copying my comment from the PR, since the issue is probably more visible 🤔
Nice, thanks to all of the contributors and reviewers here, great to have ESM in
react-native.config.jsfiles!I'm not super aware of the upstreaming / integration process here in React Native projects - will this work right away out of the box with
@react-native-community/cli@15.1.0?Eg:
- I guess new React Native projects which start without a framework will receive this feature right away now?
- Does this affect Expo projects at all? (I guess not)
Reacted by Kutsan Kaplan and Bill O'MoreReacted by Kræn Hansen, Anton Melser and Bill O'MoreReacted by Bill O'More- added a commit that references this issue
on Sep 9, 2026 - added a commit that references this issue
on Sep 10, 2026
Describe the Feature
I'd love to use modern ESM code in my React Native apps and libraries. The CLI's config package currently blocks having
"type": "module"in a React Native app or library package, because the config command loads config files synchronous, with a ~ 5 year old version ofcosmiconfig.Setting
"type": "module"in apackage.jsonof an app or dependency yields the following error:Users cannot rename
react-native.config.jstoreact-native.config.cjsbecause it's not in the list of files being searched for, even when patching that list, yields this error:So, there doesn't seem to exist any workaround for this.
Possible Implementations
I believe the best solution is to upgrade
cosmicconfigto a more recent version and use their async API to load the config file.This entails that the following methods would become
async:Which would in practice break the API of both the
@react-native-community/cliand@react-native-community/cli-configpackages and probably require a major version bump.A less intrusive alternative, would be to upgrade but only support CommonJS configs and simply add
react-native.config.cjsand fix the issue loading it.Note: Upgrading
cosmicconfigwould have the added benefit of packages being able to declare their React Native configs in their package.json files too. But that should either be disabled or named differently to avoid conflicts with thereact-nativemain field already relied upon by Metro.I'd be willing to contribute a PR to fix this, if there's a good chance it'll be considered for review.
Related Issues
I'm surprised, but I can't seem to find existing issues mentioning this limitation.