feat(nitro): Handle sourcemap preparation and upload#19304
feat(nitro): Handle sourcemap preparation and upload#19304logaretm merged 18 commits intoawad/create-nitro-sdk-metadatafrom
Conversation
Codecov Results 📊Generated by Codecov Action |
size-limit report 📦
|
1923dda to
be2f037
Compare
0d86a79 to
9f6254a
Compare
be2f037 to
3b30e36
Compare
9f6254a to
63a2175
Compare
3b30e36 to
36c96b6
Compare
d3e3ae1 to
a24cad5
Compare
|
This pull request has gone three weeks without activity. In another week, I will close it. But! If you comment or otherwise update it, I will reset the clock, and if you apply the label |
3cf1515 to
342ea3b
Compare
a24cad5 to
1583866
Compare
342ea3b to
8d44437
Compare
a967e7a to
00bd835
Compare
There was a problem hiding this comment.
Pull request overview
Adds build-time sourcemap generation + post-build sourcemap (and debug ID) handling to the @sentry/nitro SDK by wiring Nitro’s compiled hook to @sentry/bundler-plugin-core.
Changes:
- Introduces
packages/nitro/src/sourceMaps.tsto configure Nitro sourcemap settings and to run a post-build upload flow viacreateSentryBuildPluginManager. - Threads
SentryNitroOptionsthrough module setup so sourcemap behavior can be configured fromwithSentryConfig/setupSentryNitroModule. - Adds Vitest coverage for option-shaping and basic hook registration behavior.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/nitro/src/sourceMaps.ts | New sourcemap config + post-build hook which injects debug IDs and uploads sourcemaps via bundler-plugin-core |
| packages/nitro/test/sourceMaps.test.ts | New unit tests for plugin option building, config mutation, and hook registration |
| packages/nitro/src/module.ts | Passes Sentry options into module setup to enable sourcemap handling |
| packages/nitro/src/config.ts | Defines SentryNitroOptions from bundler-plugin-core options and enables sourcemap config during module setup |
| packages/nitro/rollup.npm.config.mjs | Marks @sentry/bundler-plugin-core as external in the package build |
| packages/nitro/package.json | Adds @sentry/bundler-plugin-core dependency |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…is set When `sourcemaps.disable` is `'disable-upload'`, the plugin should still inject debug IDs and keep `.map` files so users can upload them manually. Previously, both `injectDebugIds()` and `deleteArtifacts()` were incorrectly gated or ungated, causing debug IDs to be skipped and source maps to be deleted even in the manual-upload workflow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Derive `SentryNitroOptions` from `BuildTimeOptionsBase` (from `@sentry/core`) instead of picking from the bundler plugin's internal `Options` type. This provides a stable public API that follows this repo's semver, rather than exposing bundler-plugin-specific fields like `_metaOptions` and top-level `disable`. Key changes: - `url` option renamed to `sentryUrl` (consistent with other SDKs) - Top-level `disable` removed (use `sourcemaps.disable` instead) - `_metaOptions` no longer user-configurable Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ing `true` Previously, `configureSourcemapSettings` unconditionally set `config.sourcemap = true`, overriding the user's explicit `false`. This could expose source maps publicly when users intentionally disabled them. Now follows the same 3-case pattern as other meta-framework SDKs (Nuxt): 1. User disabled (false) → keep their setting, warn about unminified errors 2. User enabled (true) → keep their setting 3. User didn't set (undefined) → enable for Sentry Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
`configureSourcemapSettings` runs at build time, but the `debug` logger from `@sentry/core` is only initialized by `Sentry.init()` at runtime. Switch to `console.warn`/`console.log` so build-time warnings (e.g. source maps explicitly disabled) are actually visible to developers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The `rewriteSources` option was hardcoded to `normalizePath`, silently discarding any custom function provided by the user. Now falls back to `normalizePath` only when the user doesn't provide their own function, matching the behavior of other meta-framework SDKs (Nuxt, Next.js). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously `filesToDeleteAfterUpload` defaulted to `['**/*.map']` unconditionally, deleting user-generated source maps even when the user explicitly set `sourcemap: true` in their Nitro config. Now the default only applies when Sentry was the one to enable sourcemap generation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Nitro spawns a nested Nitro instance for prerendering with the user's `modules` array re-installed, which caused the Sentry module to run twice and upload source maps + create a release twice per build. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ff591f3 to
14b31ea
Compare
| // We don't prepare the artifacts because we injected debug IDs manually before | ||
| prepareArtifacts: false, | ||
| }); | ||
| await sentryBuildPluginManager.deleteArtifacts(); |
There was a problem hiding this comment.
Did you manually also check if this deletes the correct source maps - based on the user-set source map setting?
There was a problem hiding this comment.
I tried 3 scenarios locally:
- default: Sourcemaps files get deleted
- explicit
true, sourcemap files is retained disable-upload: retained but not uploaded
I did miss that it should only delete nitro's sourcemaps (fixed now in 1c13825) but not sure what other scenarios to take into account. Also checked that it respects the filesToDeleteAfterUpload option, is that what you meant?
There was a problem hiding this comment.
Yes, your scenarios plus:
- respecting
filesToDeleteAfterUpload undefinedsource maps: setting them tohidden, uploading them and deleting them afterwards
There was a problem hiding this comment.
Yep I did test filesToDeleteAfterUpload and it was respected. For hidden, it isn't part of nitro's v3 API but it works under the hood since it forwards it to vite so i'm not sure. I will follow your suggestion still.
`filesToDeleteAfterUpload` previously defaulted to `['**/*.map']`, which is resolved from the project root and could traverse `node_modules`. Scope the default to `nitro.options.output.serverDir` so we only touch maps we generated. Also log the chosen glob in debug mode to match the Nuxt SDK UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| } | ||
|
|
||
| let sentryEnabledSourcemaps = false; | ||
| if (config.sourcemap === true) { |
There was a problem hiding this comment.
They could also be enabled with 'inline' | 'hidden'
There was a problem hiding this comment.
Not part of Nitro's v3 API, it's always a boolean but hidden would work through vite still so I'm not sure what to do here.
| } | ||
| } else { | ||
| // User did not explicitly set sourcemap — enable it for Sentry | ||
| config.sourcemap = true; |
There was a problem hiding this comment.
| config.sourcemap = true; | |
| config.sourcemap = 'hidden'; |
It's safer to set them to hidden, if they are not already set by something by the user.
There was a problem hiding this comment.
It's not part of nitro's API for some reason but it works, so I will follow your suggestion.
Previously when users didn't set `sourcemap`, we set it to `true`, which causes Nitro/Vite to append `//# sourceMappingURL=` to each output file, publicly exposing sourcemap references. Switch to `'hidden'` so .map files are still emitted (and uploaded/deleted by Sentry) without the public reference comment. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| // Nitro types `sourcemap` as `boolean`, but it forwards the value to Vite which supports `'hidden'`. | ||
| // `'hidden'` emits .map files without adding a `//# sourceMappingURL=` comment to the output, avoiding public exposure. | ||
| (config as { sourcemap?: unknown }).sourcemap = 'hidden'; | ||
| sentryEnabledSourcemaps = true; |
There was a problem hiding this comment.
Source map config modified unconditionally including dev mode
Medium Severity
configureSourcemapSettings unconditionally sets config.sourcemap = 'hidden' at config construction time, affecting both dev and production builds. While shouldSkipSourcemapUpload correctly skips the upload hook in dev mode, the config-level sourcemap change to 'hidden' persists. This differs from the Nuxt implementation, which defers source map modifications to a lifecycle hook guarded by !nuxt.options.dev. Setting 'hidden' in dev mode removes the //# sourceMappingURL= comment, potentially degrading Node.js source map support during development.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 3f30c9a. Configure here.
…ne'`) Nitro types `sourcemap` as `boolean`, but the value is forwarded to Vite which also accepts `'hidden'` and `'inline'`. The previous logic treated any non-`true`/`false` value as unset and overwrote it with `'hidden'` plus default deletion, which (1) clobbered an explicit `'inline'` choice and (2) auto-deleted `.map` files the user had configured via `'hidden'`. Now we keep `'hidden'` and `true` as-is (upload, no deletion), warn and skip upload for `'inline'` (no `.map` files exist to upload), and only enable hidden + deletion when `sourcemap` is unset. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 26a6dd2. Configure here.
| prepareArtifacts: false, | ||
| }); | ||
| await sentryBuildPluginManager.deleteArtifacts(); | ||
| } |
There was a problem hiding this comment.
Sourcemap disable passed redundantly to plugin manager
Medium Severity
The sourcemaps.disable value (e.g., 'disable-upload') is passed to the bundler plugin manager via getPluginOptions at line 110, AND the same value is manually checked at line 55 to skip uploadSourcemaps/deleteArtifacts. If the plugin manager internally also honors disable: 'disable-upload' (as it does in other SDKs), these calls would be no-ops anyway. But if the plugin manager treats 'disable-upload' as also suppressing createRelease or injectDebugIds internally, those calls on lines 51 and 53 could silently fail. The Next.js implementation avoids this by letting the plugin manager handle disable internally rather than double-gating. Consider either not passing disable to the plugin options (letting the manual orchestration control the flow) or removing the manual check and letting the plugin manager handle it, but not both.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 26a6dd2. Configure here.
Implements HTTP server instrumentation for both `h3` and `srvx` by listening to their tracing channel events. - `h3` TC PR: h3js/h3#1251 - `srvx` TC PR: h3js/srvx#141 Closes #18123 --- **This PR is part of a stack:** - #20358 - #19224 - #19225 👈 - #19304 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds automatic sourcemap handling to the Nitro SDK, using `@sentry/bundler-plugin-core` for builder-agnostic post-build upload. Nitro uses rollup or rolldown, so it made sense to make it as agnostic as possible. Closes #17992 --- **This PR is part of a stack:** - #20358 - #19224 - #19225 - #19304 👈 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements HTTP server instrumentation for both `h3` and `srvx` by listening to their tracing channel events. - `h3` TC PR: h3js/h3#1251 - `srvx` TC PR: h3js/srvx#141 Closes #18123 --- **This PR is part of a stack:** - #20358 - #19224 - #19225 👈 - #19304 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds automatic sourcemap handling to the Nitro SDK, using `@sentry/bundler-plugin-core` for builder-agnostic post-build upload. Nitro uses rollup or rolldown, so it made sense to make it as agnostic as possible. Closes #17992 --- **This PR is part of a stack:** - #20358 - #19224 - #19225 - #19304 👈 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This PR just isolates the mundane changes needed for a new SDK to keep the next stacked PRs clean, it adds the Nitro SDK to the monorepo. This PR is a base of a stack, the stacked PRs will be merged into it. I thought this will be easier to review. --- **This PR is part of a stack:** - #20358 - #19224 👈 - #19225 - #19304 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>


Adds automatic sourcemap handling to the Nitro SDK, using
@sentry/bundler-plugin-corefor builder-agnostic post-build upload.Nitro uses rollup or rolldown, so it made sense to make it as agnostic as possible.
Closes #17992
This PR is part of a stack: