Skip to content

fix(core,browser,react): Add react-native export condition to resolve dual ESM/CJS bundling#21362

Open
antonis wants to merge 3 commits into
developfrom
fix/react-native-dual-esm-cjs-bundling
Open

fix(core,browser,react): Add react-native export condition to resolve dual ESM/CJS bundling#21362
antonis wants to merge 3 commits into
developfrom
fix/react-native-dual-esm-cjs-bundling

Conversation

@antonis

@antonis antonis commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).
  • Link an issue if there is one related to your pull request. If no issue is linked, one will be auto-generated and linked.

Closes getsentry/sentry-react-native#6262

Summary

Since React Native 0.79 (April 2025), Metro enables unstable_enablePackageExports by default. @sentry/core, @sentry/browser, and @sentry/react only export import/require conditions. Due to a Metro isESMImport detection issue, some dependencies resolve to CJS while others resolve to ESM — causing both full module trees to be bundled into native apps.

This adds a react-native export condition (pointing to ESM) to all three packages. Metro includes react-native in its default condition names, so it matches first and always resolves to ESM — bypassing the import/require ambiguity.

Impact

  • ~1 MB of unnecessary CJS code eliminated from every RN 0.79+ app shipped to stores
  • Hermes compiles everything in the bundle — there is no dead code elimination after Metro

Bundle analysis (sentry-react-native sample app, Android)

@sentry/core files Bundle size
Before 338 CJS + 338 ESM = 676 5.09 MB
After 0 CJS + 338 ESM = 338 4.56 MB

Safety

The react-native condition is only recognized by Metro (React Native). It has no effect on:

  • Node.js — not a recognized condition
  • Webpack / esbuild / Vite — not in default condition names
  • Any non-RN bundler — falls through to import/require as before

Changes

  • packages/core/package.json — Add react-native condition to ., ./browser, ./server subpaths
  • packages/browser/package.json — Add react-native condition to . (points to prod ESM build)
  • packages/react/package.json — Add react-native condition to .

…ve dual ESM/CJS bundling

Add `react-native` export condition to `@sentry/core`, `@sentry/browser`,
and `@sentry/react` package.json exports. This prevents Metro (RN 0.79+)
from resolving both ESM and CJS builds of these packages into native bundles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@antonis antonis force-pushed the fix/react-native-dual-esm-cjs-bundling branch from b1fd558 to c706d9c Compare June 8, 2026 11:13
@antonis antonis marked this pull request as ready for review June 8, 2026 11:35
@antonis antonis requested review from a team as code owners June 8, 2026 11:35
@antonis antonis requested review from Lms24, chargome, logaretm and nicohrubec and removed request for a team June 8, 2026 11:35

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c706d9c. Configure here.

"react-native": {
"types": "./build/types/index.d.ts",
"default": "./build/esm/index.js"
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing export regression test

Low Severity

This fix PR only updates package.json exports and the changelog, with no unit, integration, or E2E test in the diff that would fail without the react-native conditions and pass with them. Per SDK testing conventions for fix PRs, a regression test for Metro ESM-only resolution is recommended.

Additional Locations (2)
Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

Reviewed by Cursor Bugbot for commit c706d9c. Configure here.

@chargome chargome left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally LGTM but do you also need these export conditions e.g. for browser-utils and other packages that are pulled into our browser SDK?

Comment thread CHANGELOG.md Outdated
antonis and others added 2 commits June 8, 2026 14:02
Co-authored-by: Charly Gomez <charly.gomez1310@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@antonis

antonis commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Generally LGTM but do you also need these export conditions e.g. for browser-utils and other packages that are pulled into our browser SDK?

Thank you for the quick review and feedback @chargome 🙇
Updated with 78c86cc to add those defensively.

@antonis antonis requested a review from chargome June 8, 2026 12:38

@Lms24 Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me in general! I wonder though how other packages handle this? Is it now a requirement for RN-compatible packages supporting CJS and ESM to explicitly define a react-native submodule export? If so that's fine (I have far too little context on Expo/RN to judge this 😅). If not, are there other solutions?

@antonis

antonis commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Looks good to me in general! I wonder though how other packages handle this? Is it now a requirement for RN-compatible packages supporting CJS and ESM to explicitly define a react-native submodule export? If so that's fine (I have far too little context on Expo/RN to judge this 😅). If not, are there other solutions?

I think this is more of a workaround for Metro ESM resolution issues (facebook/metro#1582) and it's cleaner to be in the JS repo than working around this in the react native SDK. RN and most of its ecosystem simply don't use dual import/require conditions, which is why they don't hit this bug.
The issue getsentry/sentry-react-native#6262 (for RN 0.79+) went unnoticed for a while till we got a public ping on this https://x.com/gabimoncha/status/2063607452403200003

@alwx alwx left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I guess the export regression part could be skipped for now.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(metro): Dual ESM/CJS bundling of @sentry/core on RN 0.79+ and unnecessary server integrations in native bundles

4 participants