diff --git a/docs/platforms/javascript/guides/cloudflare/frameworks/react-router.mdx b/docs/platforms/javascript/guides/cloudflare/frameworks/react-router.mdx new file mode 100644 index 00000000000000..9a3ae1f7bf215d --- /dev/null +++ b/docs/platforms/javascript/guides/cloudflare/frameworks/react-router.mdx @@ -0,0 +1,278 @@ +--- +title: React Router on Cloudflare +description: "Learn how to instrument your React Router framework app on Cloudflare Workers with Sentry." +--- + + + + + +This guide is for React Router [framework mode](https://reactrouter.com/start/modes#framework) apps on Cloudflare Workers. For Node.js, see the [React Router guide](/platforms/javascript/guides/react-router/). For Shopify Oxygen, see [Hydrogen with React Router](/platforms/javascript/guides/cloudflare/frameworks/hydrogen-react-router/). + + + +## Prerequisites + +You need: + +- A Sentry [account](https://sentry.io/signup/) and [project](/product/projects/) +- Your application up and running on Cloudflare Workers ([Cloudflare's setup guide](https://developers.cloudflare.com/workers/framework-guides/web-apps/react-router/)) +- React Router version `7.15.0` or above (framework mode) + + + +## Install + +Install the Sentry SDKs: + +```bash {tabTitle:npm} +npm install @sentry/react-router @sentry/cloudflare +``` + +```bash {tabTitle:yarn} +yarn add @sentry/react-router @sentry/cloudflare +``` + +```bash {tabTitle:pnpm} +pnpm add @sentry/react-router @sentry/cloudflare +``` + +## Configure + +**Error Monitoring** starts working as soon as you configure Sentry. **Logs** and **Application Metrics** need no extra configuration, and you'll learn how to send them in steps [#3](#send-logs) and [#4](#send-application-metrics-). +This guide also enables **Tracing**, **Session Replay**, and **User Feedback**. + + + +### Expose Entry Point Files + +If your app doesn't have `entry.client.tsx` and `entry.server.tsx` yet, expose them: + +```bash +npx react-router reveal +``` + +### Configure Client-Side Sentry + +Initialize Sentry in `entry.client.tsx`. + +The snippet also turns on: + +- Tracing: via `tracesSampleRate` and `reactRouterTracingIntegration()` +- Session Replay: via `replayIntegration()`, sampled with `replaysSessionSampleRate` and `replaysOnErrorSampleRate` +- User Feedback: via `feedbackIntegration()` + +Don't need a feature? Remove its integration and options from the snippet. + +```tsx {filename:app/entry.client.tsx} +import * as Sentry from "@sentry/react-router"; +import { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; +import { HydratedRouter } from "react-router/dom"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + + integrations: [ + // Registers and configures the Tracing integration, + // which automatically instruments your application to monitor its + // performance, including custom React Router routing instrumentation + Sentry.reactRouterTracingIntegration(), + // Registers the Replay integration, + // which automatically captures Session Replays + Sentry.replayIntegration(), + // Registers the User Feedback integration + Sentry.feedbackIntegration({ + // Additional SDK configuration goes in here, for example: + colorScheme: "system", + }), + ], + + // Enables Tracing. + // Set to 1.0 to capture 100% of spans for tracing. + // We recommend reducing this value in production. + tracesSampleRate: 1.0, + + // Set `tracePropagationTargets` to declare which URL(s) should have trace propagation enabled + tracePropagationTargets: [/^\//, /^https:\/\/yourserver\.io\/api/], + + // Capture replays for 10% of all sessions, + // plus for 100% of sessions with an error + // Requires Sentry.replayIntegration() + replaysSessionSampleRate: 0.1, + replaysOnErrorSampleRate: 1.0, +}); + +startTransition(() => { + hydrateRoot( + document, + + {/* Captures client-side errors */} + + + ); +}); +``` + +### Add the Vite Plugin + +Add the Sentry Cloudflare Vite plugin at the end of the `plugins` array in your `vite.config.ts`. To learn what it does and see its options, see Vite Plugin. + +```typescript {diff} {filename:vite.config.ts} ++import { sentryCloudflareVitePlugin } from "@sentry/cloudflare/vite"; + + export default defineConfig({ + plugins: [ + cloudflare({ viteEnvironment: { name: "ssr" } }), + reactRouter(), ++ sentryCloudflareVitePlugin(), + ], + }); +``` + +### Wrangler Configuration + + + +### Configure Server-Side Sentry + +Create a `workers/instrument.server.ts` file to initialize Sentry on the server. + +The snippet also turns on: + +- Tracing: via `tracesSampleRate` + +Don't need a feature? Remove its options from the snippet. + +```typescript {filename:workers/instrument.server.ts} +import { defineCloudflareOptions } from "@sentry/cloudflare"; + +export default defineCloudflareOptions((env) => ({ + dsn: "___PUBLIC_DSN___", + + // Enables Tracing. + // Set to 1.0 to capture 100% of spans for tracing. + // We recommend reducing this value in production. + tracesSampleRate: 1.0, +})); +``` + +Next, replace the default `handleRequest` and `handleError` functions in your `entry.server.tsx` file with Sentry's versions, and export `instrumentations` to enable automatic tracing. On Workers, import from `@sentry/react-router/cloudflare`: + +```tsx {filename:app/entry.server.tsx} +import { captureException } from "@sentry/cloudflare"; +import * as Sentry from "@sentry/react-router/cloudflare"; +import { renderToReadableStream } from "react-dom/server"; +import { ServerRouter, type HandleErrorFunction } from "react-router"; + +// Renders the app and connects server and client traces +export default Sentry.createSentryHandleRequest({ + ServerRouter, + renderToReadableStream, +}); + +export const handleError: HandleErrorFunction = (error, { request }) => { + // React Router also calls handleError for aborted requests, skip those + if (!request.signal.aborted) { + captureException(error, { + mechanism: { type: "react-router", handled: false }, + }); + } +}; + +// Automatically instruments all server loaders, actions, middleware, +// and request handlers. +export const instrumentations = [Sentry.createSentryServerInstrumentation()]; +``` + +`createSentryHandleRequest` needs SDK version `11.10.0` or above. For CSP nonces, pass [`getNonce`](/platforms/javascript/guides/react-router/manual-setup/#configure-server-side-sentry). + + + +For custom rendering logic or SDK versions `11.5.0` to `11.9.x`, wrap your own `handleRequest` instead: + +```tsx {diff} {filename:app/entry.server.tsx} ++import * as Sentry from "@sentry/react-router/cloudflare"; + // ... your existing imports + +-export default async function handleRequest( ++async function handleRequest( + // ... your existing parameters + ) { + // ... your existing rendering logic + +- return new Response(body, { ++ return new Response(Sentry.injectTraceMetaTags(body), { + headers: responseHeaders, + status: responseStatusCode, + }); + } + ++export default Sentry.wrapSentryHandleRequest(handleRequest); +``` + +Keep the `handleError` and `instrumentations` exports from above. + + + +### Add Readable Stack Traces With Source Maps + +Follow the [React Router source maps setup](/platforms/javascript/guides/react-router/manual-setup/#add-readable-stack-traces-with-source-maps). + +### Control the Data You Send to Sentry + + + +## Send Logs + + + +Already logging with `console` or Consola? Capture those logs with the console integrations. + +## Send Application Metrics + + + +## Verify Your Setup + +To confirm events are reaching Sentry, add a test button to your app and click it: + +```tsx + +``` + + + +### View Captured Data in Sentry + +Now, head over to your project on [Sentry.io](https://sentry.io) to view the collected data (it takes a couple of moments for the data to appear). + + + +## Next Steps + +Here's what to explore next: + +- Explore [practical guides](/get-started/guides/) on what to monitor, log, track, and investigate after setup +- Set up tunneling to avoid ad blockers blocking Sentry events +- Set up Agent Tracing to monitor your AI systems + + + +- Check out setup instructions for other popular [frameworks on Cloudflare](/platforms/javascript/guides/cloudflare/frameworks/) +- Find various support topics in troubleshooting +- [Get support](https://www.sentry.help/en/) + + + + diff --git a/docs/platforms/javascript/guides/cloudflare/index.mdx b/docs/platforms/javascript/guides/cloudflare/index.mdx index 76049c2c545523..e2a0fc10ce5840 100644 --- a/docs/platforms/javascript/guides/cloudflare/index.mdx +++ b/docs/platforms/javascript/guides/cloudflare/index.mdx @@ -19,6 +19,7 @@ If you're using any of the listed frameworks, follow their specific setup instru - **[Hydrogen](/platforms/javascript/guides/cloudflare/frameworks/hydrogen-react-router/)** - **[Next.js](/platforms/javascript/guides/cloudflare/frameworks/nextjs/)** - **[Nuxt](/platforms/javascript/guides/cloudflare/frameworks/nuxt/)** +- **[React Router](/platforms/javascript/guides/cloudflare/frameworks/react-router/)** - **[Remix](/platforms/javascript/guides/cloudflare/frameworks/remix/)** - **[SvelteKit](/platforms/javascript/guides/cloudflare/frameworks/sveltekit/)** - **[TanStack Start](/platforms/javascript/guides/cloudflare/frameworks/tanstack-start/)**