Skip to content

fix(react-router): Resolve the Cloudflare entry in Workers and skip trace meta tags in prerendered pages - #24866

Merged
JPeer264 merged 5 commits into
developfrom
jp/react-router-cloudflare-worker-fixes
Oct 2, 2026
Merged

JPeer264 merged 5 commits into
developfrom
jp/react-router-cloudflare-worker-fixes

Conversation

@JPeer264

@JPeer264 JPeer264 commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Three bugs in @sentry/react-router, found by running the react-router-8-framework e2e suite on workerd and Bun.

Cloudflare builds resolve with both the worker and the browser condition (the Vite plugin sets workerd, worker, module, browser, wrangler sets workerd, worker, browser), and the exports map listed browser before worker, so worker was never reached. import * as Sentry from '@sentry/react-router' in a route got the client build, and Sentry.startSpan() / Sentry.flush() compiled to undefined: loaders and middleware that call them threw TypeError: (void 0) is not a function. A workerd key now comes first and resolves the Cloudflare entry. Only Cloudflare sets workerd, so nothing else changes: moving worker above browser would also have switched webpack builds with target: 'webworker', which set worker and browser, to the Cloudflare entry.

On Cloudflare, react-router build prerenders pages by running them through the wrapped Worker, so injectTraceMetaTags wrote a build-time sentry-trace and baggage into the static HTML. Every visitor of a prerendered page then continued that one trace with its sampling decision. Such a path never reaches the handler in production (it is served as a static file), so a render of a path from the build's prerender list is the build-time prerender, and it now gets no meta tags. For that, the server build capture also records prerender, and wrapSentryHandleRequest registers the capture: on Cloudflare only the Node server integration did that before, so the build was never captured there.

An index route has no path of its own, so wrapSentryHandleRequest never gave it a route name. On Node, Express names the span first and hid this. On runtimes without that layer (Bun, and a React Router app on any non-Express server) the index page kept a URL-sourced name, so its baggage had no sentry-transaction. An index route now takes its nearest ancestor's path, or /. On Node this changes the transaction of an index page from Express's catch-all GET * to GET /, which is why react-router-7-framework-static now expects that name.

🤖 Generated with Claude Code

@JPeer264
JPeer264 added this pull request to stack #24867 September 30, 2026 08:07
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 29.51 kB - -
@sentry/browser - with treeshaking flags 27.68 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 27.58 kB - -
@sentry/browser (incl. Tracing) 51.46 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 51.47 kB - -
@sentry/browser (incl. Tracing, Profiling) 54.47 kB - -
@sentry/browser (incl. Tracing, Replay) 91.05 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 80.03 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 95.73 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 108.72 kB - -
@sentry/browser (incl. Feedback) 47.04 kB - -
@sentry/browser (incl. sendFeedback) 34.57 kB - -
@sentry/browser (incl. FeedbackAsync) 39.69 kB - -
@sentry/browser (incl. Metrics) 30.53 kB - -
@sentry/browser (incl. Logs) 30.82 kB - -
@sentry/browser (incl. Metrics & Logs) 31.48 kB - -
@sentry/react 31.36 kB - -
@sentry/react (incl. Tracing) 53.82 kB - -
@sentry/vue 37.51 kB - -
@sentry/vue (incl. Tracing) 54.36 kB - -
@sentry/svelte 29.54 kB - -
@sentry/remix (Remix 3 client bundle) 55.75 kB - -
CDN Bundle 31.22 kB - -
CDN Bundle (incl. Tracing) 51.99 kB - -
CDN Bundle (incl. Logs, Metrics) 33.46 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 53.94 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 74.2 kB - -
CDN Bundle (incl. Tracing, Replay) 89.56 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 91.54 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 95.73 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 97.73 kB - -
CDN Bundle - uncompressed 92.14 kB - -
CDN Bundle (incl. Tracing) - uncompressed 154.53 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 98.71 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 160.48 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 228.28 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 274.26 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 280.2 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 287.96 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 293.89 kB - -
@sentry/nextjs (client) 56.33 kB - -
@sentry/sveltekit (client) 51.88 kB - -
@sentry/core/server 39.99 kB - -
@sentry/core/browser 13.63 kB - -
@sentry/node 144.48 kB +0.01% +9 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 83.08 kB - -
@sentry/node - without tracing 93.03 kB +0.02% +10 B 🔺
@sentry/node - without channel injection 122.76 kB +0.01% +11 B 🔺
@sentry/aws-serverless 101.33 kB +0.01% +7 B 🔺
@sentry/cloudflare (withSentry) - minified 207.1 kB - -
@sentry/cloudflare (withSentry) 515.31 kB - -

View base workflow run

@JPeer264
JPeer264 force-pushed the jp/react-router-cloudflare-worker-fixes branch 2 times, most recently from 0b6e114 to 05f82b1 Compare October 1, 2026 13:14
JPeer264 and others added 5 commits October 1, 2026 19:54
…race meta tags in prerendered pages

In a Worker build, the Cloudflare Vite plugin resolves with the `browser`
condition set, and the exports map lists `browser` first, so
`@sentry/react-router` resolved to the client build. `Sentry.startSpan()`
and `Sentry.flush()` then compiled to `undefined` in loaders and middleware.
The Cloudflare entry is now resolved under the `workerd` condition.

On Cloudflare, `react-router build` prerenders pages through the wrapped
Worker, so `injectTraceMetaTags` wrote one build-time `sentry-trace` into the
static HTML and every visitor continued that trace. The server build capture
now also records the `prerender` list, `wrapSentryHandleRequest` registers the
capture (on Cloudflare nothing did), and paths from that list get no meta tags.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… skip trace meta tags in prerendered pages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… skip trace meta tags in prerendered pages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… skip trace meta tags in prerendered pages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… skip trace meta tags in prerendered pages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JPeer264
JPeer264 force-pushed the jp/react-router-cloudflare-worker-fixes branch from ee8e6e3 to ba877af Compare October 1, 2026 17:54
@JPeer264

JPeer264 commented Oct 2, 2026

Copy link
Copy Markdown
Member Author

bugbot run

@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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ba877af. Configure here.

@JPeer264
JPeer264 marked this pull request as ready for review October 2, 2026 08:49
@JPeer264
JPeer264 requested a review from a team as a code owner October 2, 2026 08:49
@JPeer264
JPeer264 requested review from chargome and nicohrubec and removed request for a team October 2, 2026 08:49
@JPeer264 JPeer264 self-assigned this Oct 2, 2026
@JPeer264
JPeer264 merged commit 425a304 into develop Oct 2, 2026
51 checks passed
@JPeer264
JPeer264 deleted the jp/react-router-cloudflare-worker-fixes branch October 2, 2026 09:51
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.

2 participants