Skip to content

add react-native export condition resolving to browser build - #412

Closed
davor-bauk-sh wants to merge 1 commit into
isaacs:mainfrom
davor-bauk-sh:react-native-export-condition
Closed

davor-bauk-sh wants to merge 1 commit into
isaacs:mainfrom
davor-bauk-sh:react-native-export-condition

Conversation

@davor-bauk-sh

Copy link
Copy Markdown
Contributor

Problem

Follow-up to #397 / #399 and react/metro#1681.

Metro resolves package exports with the conditions import/require plus react-native. It never sets browser or node, so for lru-cache it falls through to default, i.e. dist/esm/index.min.js, which does import('node:diagnostics_channel').

Current Metro does recognise the .catch()-guarded dynamic import as optional at build time (the fix from metro#1681), so bundling succeeds. On native, though, the runtime require of an unresolved optional module reports a fatal error through ErrorUtils.reportFatalError instead of throwing, so the promise .catch() never sees it and the app crashes on startup. This is not the node condition being loaded by mistake; it is the default entry.

Change

Add a react-native condition to the root export, in both tshy.exports and the generated exports, pointing at the existing browser build (dist/{esm,commonjs}/browser/). No new build output, no source change. react-native is the conventional condition packages use to give Metro a dedicated entry, and every other resolver ignores it.

Verified with a bare-specifier probe against this branch after npm run prepare:

[node <default>]
  require -> dist/commonjs/node/index.min.js
  import  -> dist/esm/node/index.min.js
[node --conditions=react-native]
  require -> dist/commonjs/browser/index.min.js
  import  -> dist/esm/browser/index.min.js
[node --conditions=browser]
  require -> dist/commonjs/browser/index.min.js
  import  -> dist/esm/browser/index.min.js

tshy preserves the condition on rebuild (git status clean apart from this diff). Browser builds contain no node: references.

Not touched: the ./raw export, which is generated by tshy from source. React Native users importing lru-cache/raw would still hit the default build; happy to hand-write that export too if you'd prefer.

🤖 Generated with Claude Code

Metro (React Native's bundler) resolves package exports with the
conditions `import`/`require` and `react-native`, never `browser`
or `node`, so it falls through to the `default` entry. That build
does `import('node:diagnostics_channel')`, which cannot be provided
in a React Native runtime. Current Metro treats the `.catch()`-
guarded import as optional at build time, but on native the runtime
`require` of an unresolved optional module reports a fatal error via
`ErrorUtils` instead of throwing, so the `.catch()` never runs and
the app crashes on startup.

Expose the existing browser build under the `react-native` condition
as well. This is the conventional way for packages to provide a
Metro-specific entry, is ignored by every other resolver, and adds
no new build output.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@isaacs isaacs closed this in 98b553f Sep 18, 2026
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.

1 participant