You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
v3.x bundles react/jsx-runtime into dist, breaking all React Native (Metro) apps in dev mode #75
Since v3.0.0, dist/index.js contains an inlined copy of react/jsx-runtime instead of importing it. React's dev JSX runtime does require("react") internally, and because the ESM output can't emit a static require, Rolldown compiles it into a dynamic-require shim. Metro cannot statically resolve that, so importing the SDK throws immediately in any development build.
Error
[Error: Requiring unknown module "react". If you are sure the module exists, try restarting Metro. You may also want to run yarn or npm install.]
Rollup/Rolldown match these exactly, so "react" does not cover the react/jsx-runtime subpath that the automatic JSX transform emits. It gets bundled instead of externalized.
where m is Rolldown's typeof require < "u" ? require : ... shim. Metro's dependency collector only rewrites literal require("...") calls into numeric module IDs, so this reaches metroRequire("react") with a string at runtime and throws.
This appears to be a regression from the Vite 7 → 8 (esbuild → Rolldown/Oxc) upgrade: 2.4.0 compiled JSX with the classic runtime (React.createElement) and never imported react/jsx-runtime, so the incomplete externals list was harmless. 3.x uses the automatic runtime.
@bastianspirek Confirmed at main - the externals list is exact strings, so react/jsx-runtime (emitted by the automatic JSX transform) falls through and gets bundled. The dev JSX runtime's internal require("react") then becomes Rolldown's dynamic-require shim, which Metro can't resolve - hence the throw on import before any SDK call.
Fix: make the react/react-native/react-dom externals subpath-covering regexes so jsx-runtime stays external. Verified by building both ways: on main dist/index.js carries the inlined dev runtime (react.transitional.element markers); with the fix it's a clean static import from "react/jsx-runtime" in ESM and a literal require in CJS - both forms Metro resolves statically. Package suite stays green (195 tests).
Built by breken, your AI support engineer - breken.ai finds the bug, proves the fix with unmatched RCA, answers customers in your voice, and keeps your code and support docs clean - this one's on us.
Activity
breken-ai commentedon Sep 9, 2026
@bastianspirek Confirmed at main - the externals list is exact strings, so react/jsx-runtime (emitted by the automatic JSX transform) falls through and gets bundled. The dev JSX runtime's internal require("react") then becomes Rolldown's dynamic-require shim, which Metro can't resolve - hence the throw on import before any SDK call.
Fix: make the react/react-native/react-dom externals subpath-covering regexes so jsx-runtime stays external. Verified by building both ways: on main dist/index.js carries the inlined dev runtime (react.transitional.element markers); with the fix it's a clean static import from "react/jsx-runtime" in ESM and a literal require in CJS - both forms Metro resolves statically. Package suite stays green (195 tests).
Fix ready on our fork (PR incoming): https://github.com/breken-ai/react-native/tree/fix-75-jsx-runtime-external
Built by breken, your AI support engineer - breken.ai finds the bug, proves the fix with unmatched RCA, answers customers in your voice, and keeps your code and support docs clean - this one's on us.