Skip to content

fix: externalize useSyncExternalStore shim to fix App Router crash#760

Merged
jhuleatt merged 1 commit into
FirebaseExtended:mainfrom
tyler-reitz:fix/usyncstore-esm-external
Jul 24, 2026
Merged

fix: externalize useSyncExternalStore shim to fix App Router crash#760
jhuleatt merged 1 commit into
FirebaseExtended:mainfrom
tyler-reitz:fix/usyncstore-esm-external

Conversation

@tyler-reitz

Copy link
Copy Markdown
Contributor

Fixes #759

Summary

Reactfire 4.2.4 and 4.2.5 crash on the client whenever a data hook renders, in any browser bundle that does not expose require. use-sync-external-store/shim (CJS) gets bundled into our ESM dist, which makes the bundler emit a dynamic require(). In a strict-ESM browser context that throws at module evaluation:

Calling `require` for "react" in an environment that doesn't expose the `require` function

4.2.3 predates the current build toolchain and is clean.

Fix

Add use-sync-external-store/shim to the Vite externals so the consumer's bundler resolves it (it is already a runtime dependency). This removes the require from our dist while keeping the shim's React 16/17 fallback, so it stays non-breaking (no peer-range change).

Verification

  • Built ESM dist/index.js: require occurrences 3 to 0; clean import ... from "use-sync-external-store/shim".
  • Reproduced the live crash with published 4.2.5 in two setups: a Next 16 App Router app (turbopack) and a Vite SPA (both crash client-side at module evaluation).
  • Rebuilt both against this fix: Next client chunk no longer carries the throw path; the Vite app renders successfully (hook reaches status: 'success').

Patch-level, non-breaking. Fixes the regression in latest. Version bump to 4.2.6 left as a separate publish-time commit, per convention.

Bundling use-sync-external-store/shim (a CJS module) into the ESM dist
makes rolldown emit a dynamic require() that throws "dynamic usage of
require is not supported" when a reactfire data hook loads client-side in
a Next.js App Router (strict ESM) context. This regression shipped in
4.2.4 and 4.2.5; 4.2.3 predates the current build toolchain and is clean.

Externalizing the shim lets the consumer's bundler resolve it (it is
already a runtime dependency), removing the require from our dist while
keeping the shim's React 16/17 fallback. Verified the throw path is
absent from the built ESM dist and from a rebuilt Next.js App Router
client chunk.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@tyler-reitz

Copy link
Copy Markdown
Contributor Author

@jhuleatt flagging this for an expedited 4.2.6, since it is a regression in latest.

What: reactfire 4.2.4 and 4.2.5 crash on the client whenever a data hook renders. The bundled use-sync-external-store/shim becomes a dynamic require() that throws at module evaluation in any browser bundle without require.

Blast radius (runtime-confirmed): reproduced live in both a Next 16 App Router app (turbopack) and a Vite SPA on published 4.2.5, so it spans the two most common modern reactfire setups, not one bundler. Server prerender is unaffected (Node has require); the break is client-side. 4.2.3 is clean, so it came in with the build-tooling change around 4.2.4. No user reports yet is consistent with 4.2.4/4.2.5 being only a couple of days old.

Fix (this PR): one-line Vite externals change, non-breaking, React 16/17 fallback preserved. Verified the crash is gone (Next client chunk no longer carries the throw path; the Vite app renders status: 'success'). Armando is on for the technical review.

Since you are the manual publish path, this needs you for the 4.2.6 release once reviewed. Separately: this is the second dist-level regression to ship as a patch (after the 4.2.4 .d.ts change), so I think our release process needs a built-artifact diff gate before publish.

@jhuleatt
jhuleatt merged commit 1892f09 into FirebaseExtended:main Jul 24, 2026
14 checks passed
@tyler-reitz
tyler-reitz deleted the fix/usyncstore-esm-external branch July 24, 2026 20:27
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.

App Router crash: reactfire 4.2.4/4.2.5 throw "dynamic usage of require is not supported" on the client

2 participants