Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/platforms/javascript/guides/remix/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ categories:
- server
---

<Alert level="warning" title="Remix 3 Not Yet Supported">
<Alert level="warning" title="Using Remix 3?">

The current `@sentry/remix` SDK does not support [Remix 3](https://remix.run/blog/remix-3-beta-preview). If you're using Remix 3, the SDK may not work as expected. We're tracking support — check back for updates.
This guide covers Remix 2. Support for [Remix 3](https://remix.run/blog/remix-3-beta-preview) is in alpha and has its own setup, see <PlatformLink to="/remix-3/">Remix 3 (Alpha)</PlatformLink>.

</Alert>

Expand Down
205 changes: 205 additions & 0 deletions docs/platforms/javascript/guides/remix/remix-3.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
---
title: Remix 3 (Alpha)
sidebar_order: 2
description: "Learn how to set up Sentry in a Remix 3 app, upload source maps, and capture your first errors."
---

<Alert level="warning" title="Alpha">

Support for Remix 3 is in alpha. The API can change in any release. It lives under the `@sentry/remix/v3` subpaths and is separate from the Remix 2 SDK documented on the other pages of this guide. Please [report issues](https://github.com/getsentry/sentry-javascript/issues/new/choose) you run into.

</Alert>

Remix 3 has no build step: the asset server compiles browser modules per request. The SDK works with that instead of a bundler plugin. A module hook instruments the Remix server packages when Node imports them, and the asset server is instrumented so the browser modules it serves carry debug IDs.

<StepConnector selector="h2" showNumbers={true}>

## Install

<SplitLayout>
<SplitSection>
<SplitSectionText>

Install the SDK. It requires `remix@3.0.0-rc.1` or later and Node 20.19 or later.

</SplitSectionText>
<SplitSectionCode>

```bash {tabTitle:npm}
npm install @sentry/remix
```

```bash {tabTitle:yarn}
yarn add @sentry/remix
```

```bash {tabTitle:pnpm}
pnpm add @sentry/remix
```

</SplitSectionCode>
</SplitSection>
</SplitLayout>

## Configure the Server

### Start With the Sentry Entry

<SplitLayout>
<SplitSection>
<SplitSectionText>

Start the app with `--import @sentry/remix/v3/node` instead of `--import remix/node-tsx`. The Sentry entry registers the module hook before your app's modules are imported, then loads `remix/node-tsx` for you.

</SplitSectionText>
<SplitSectionCode>

```json {filename:package.json}
{
"scripts": {
"start": "node --import @sentry/remix/v3/node server.ts"
}
}
```

</SplitSectionCode>
</SplitSection>
</SplitLayout>

### Initialize the SDK

<SplitLayout>
<SplitSection>
<SplitSectionText>

Call `init()` in your server entry.

Each request gets a span named after the matched route pattern. Errors thrown in route handlers, middleware and the request listener are reported. Requests the client aborted are not, and neither are thrown responses with a status from 300 to 499. Pass `shouldHandleError` to `remixV3Integration()` to change that.

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.

That's a callback, right?

Suggested change
Each request gets a span named after the matched route pattern. Errors thrown in route handlers, middleware and the request listener are reported. Requests the client aborted are not, and neither are thrown responses with a status from 300 to 499. Pass `shouldHandleError` to `remixV3Integration()` to change that.
Each request gets a span named after the matched route pattern. Errors thrown in route handlers, middleware and the request listener are reported. Requests the client aborted are not, and neither are thrown responses with a status from 300 to 499. Pass your custom function in `shouldHandleError` to `remixV3Integration()` to change that.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes but it comes with a default already


</SplitSectionText>
<SplitSectionCode>

```ts {filename:server.ts}
import * as Sentry from "@sentry/remix/v3";
import * as http from "node:http";
import { createRequestListener } from "remix/node-fetch-server";

import { router } from "./app/router.ts";

Sentry.init({
dsn: "___PUBLIC_DSN___",
// Adjust this value in production, or use tracesSampler for greater control.
tracesSampleRate: 1.0,
});

http
.createServer(createRequestListener((request) => router.fetch(request)))
.listen(3000);
```

</SplitSectionCode>
</SplitSection>
</SplitLayout>

## Configure the Browser

### Allow the SDK in the Asset Server

<SplitLayout>
<SplitSection>
<SplitSectionText>

Add `@sentry/remix` to `allowPackages` so the asset server can serve the SDK to the browser.

There is no build step to inline environment variables, so use `define` to get the DSN into browser modules. The asset server substitutes these values when it compiles a module.

</SplitSectionText>
<SplitSectionCode>

```ts {filename:app/assets.ts}
import { createAssetServer } from "remix/assets";

export const assets = createAssetServer({
basePath: "/assets",
rootDir: process.cwd(),
allowFiles: ["app/**/public/**"],
allowPackages: ["remix", "@sentry/remix"],
scripts: {
define: {
"process.env.SENTRY_DSN": JSON.stringify(process.env.SENTRY_DSN),
},
},
});
```

</SplitSectionCode>
</SplitSection>
</SplitLayout>

### Initialize the SDK

<SplitLayout>
<SplitSection>
<SplitSectionText>

Call `init()` in your browser entry, before `run()`.

Page loads and navigations get a span each. Errors thrown while a component renders are reported; the Remix runtime does not rethrow those, so nothing else would see them.

</SplitSectionText>
<SplitSectionCode>

```ts {filename:app/entry.ts}
import * as Sentry from "@sentry/remix/v3/client";
import { run } from "remix/ui";

Sentry.init({
dsn: process.env.SENTRY_DSN,
// Adjust this value in production, or use tracesSampler for greater control.
tracesSampleRate: 1.0,
});

export const app = run({
async loadModule(moduleUrl, exportName) {
const mod = await import(moduleUrl);
return mod[exportName];
},
});
```

</SplitSectionCode>
</SplitSection>
</SplitLayout>

## Upload Source Maps

<SplitLayout>
<SplitSection>
<SplitSectionText>

Browser modules served by the asset server carry debug IDs, so stack traces are symbolicated once the source maps are uploaded. Remix 3 has no build output to upload, so the SDK ships a command that compiles the browser module graph through your asset server and uploads it.

Run it from your deploy pipeline, with the same code and configuration the server runs. The debug IDs are hashed from the compiled source, so what is uploaded matches what the running server serves.

</SplitSectionText>
<SplitSectionCode>

```bash
node --import @sentry/remix/v3/node ./node_modules/.bin/sentry-remix-v3-upload-sourcemaps --entry app/entry.ts --project ___PROJECT_SLUG___
```

</SplitSectionCode>
</SplitSection>
</SplitLayout>

The command reads `SENTRY_AUTH_TOKEN` and `SENTRY_ORG` from the environment, and proposes the release from your git history. `--project` has to be passed. Pass `--org` or `--release` to set those yourself.

`--entry` is a browser entry path and can be repeated. The asset server is read from `./app/assets.ts` (export `assets`); set `--assets-module` and `--assets-export` if yours lives elsewhere. `--dry-run` compiles without uploading.

Source maps are generated but hidden by default: modules do not reference them and `.map` requests are not served, so the source only reaches Sentry. Set `sourceMaps: "external"` on the asset server to serve them, or `sourceMaps: false` to turn them off.

## Verify

Start the app and throw an error from a route handler and from a browser component. Both should show up as issues in your project, the browser one with a readable stack trace once the source maps are uploaded.

</StepConnector>
Loading