Hook into the Remix 3 asset server so browser modules carry debug IDs, with no config from the app.
- Patch
createAssetServer in @remix-run/assets and install our script loaders.
- Inject a debug ID snippet into every served browser module.
- Default
sourceMaps to external. Remix's own template leaves source maps off in production, which would make every client stack trace unreadable.
Must follow the existing debug ID standard, so events symbolicate the same way they do for every other SDK:
- UUID shaped ID
globalThis._sentryDebugIds keyed by stack, which is what getFilenameToDebugIdMap in @sentry/core reads at runtime
//# debugId= comment on the file and a debugId field in the source map, which is what sentry-cli reads at upload time
The ID must be a hash of the compiled source, not a UUID generated per process. The upload step runs in a separate process from the server, so a per process ID would never match what the browser reports.
scripts.loaders uses Node's synchronous load hook signature. It runs after the TypeScript transform and before minification, so the snippet is minified along with the module.
Done when e2e confirms every served module carries a debug ID, the ID is stable across requests, source maps are served without the app asking for them, and a captured client error carries debug_meta.images with a matching debug_id and code_file.
Hook into the Remix 3 asset server so browser modules carry debug IDs, with no config from the app.
createAssetServerin@remix-run/assetsand install our script loaders.sourceMapstoexternal. Remix's own template leaves source maps off in production, which would make every client stack trace unreadable.Must follow the existing debug ID standard, so events symbolicate the same way they do for every other SDK:
globalThis._sentryDebugIdskeyed by stack, which is whatgetFilenameToDebugIdMapin@sentry/corereads at runtime//# debugId=comment on the file and adebugIdfield in the source map, which is whatsentry-clireads at upload timeThe ID must be a hash of the compiled source, not a UUID generated per process. The upload step runs in a separate process from the server, so a per process ID would never match what the browser reports.
scripts.loadersuses Node's synchronous load hook signature. It runs after the TypeScript transform and before minification, so the snippet is minified along with the module.Done when e2e confirms every served module carries a debug ID, the ID is stable across requests, source maps are served without the app asking for them, and a captured client error carries
debug_meta.imageswith a matchingdebug_idandcode_file.