-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(nuxt): Upload sourcemaps generated by Nitro #13382
Changes from 1 commit
d16753d
8765634
09f5f13
28efd99
e4fe965
6a94108
a1f3890
3cf9f85
2b5444a
cc7713f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,97 @@ | ||
import type { Nuxt } from '@nuxt/schema'; | ||
import { sentryRollupPlugin } from '@sentry/rollup-plugin'; | ||
import { sentryVitePlugin } from '@sentry/vite-plugin'; | ||
import type { NitroConfig } from 'nitropack'; | ||
import type { SentryNuxtModuleOptions } from '../common/types'; | ||
|
||
/** | ||
* Setup source maps for Sentry inside the Nuxt module during build time. | ||
*/ | ||
export function setupSourceMaps(moduleOptions: SentryNuxtModuleOptions, nuxt: Nuxt): void { | ||
nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => { | ||
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {}; | ||
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {}; | ||
const sourceMapsEnabled = sourceMapsUploadOptions.enabled ?? true; | ||
|
||
if ((sourceMapsUploadOptions.enabled ?? true) && viteInlineConfig.mode !== 'development') { | ||
const sentryPlugin = sentryVitePlugin({ | ||
org: sourceMapsUploadOptions.org ?? process.env.SENTRY_ORG, | ||
project: sourceMapsUploadOptions.project ?? process.env.SENTRY_PROJECT, | ||
authToken: sourceMapsUploadOptions.authToken ?? process.env.SENTRY_AUTH_TOKEN, | ||
telemetry: sourceMapsUploadOptions.telemetry ?? true, | ||
sourcemaps: { | ||
assets: sourceMapsUploadOptions.sourcemaps?.assets ?? undefined, | ||
ignore: sourceMapsUploadOptions.sourcemaps?.ignore ?? undefined, | ||
filesToDeleteAfterUpload: sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload ?? undefined, | ||
}, | ||
_metaOptions: { | ||
telemetry: { | ||
metaFramework: 'nuxt', | ||
}, | ||
}, | ||
debug: moduleOptions.debug ?? false, | ||
}); | ||
nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => { | ||
if (sourceMapsEnabled && viteInlineConfig.mode !== 'development') { | ||
const sentryPlugin = sentryVitePlugin(getPluginOptions(moduleOptions)); | ||
|
||
// Add Sentry plugin | ||
viteInlineConfig.plugins = viteInlineConfig.plugins || []; | ||
viteInlineConfig.plugins.push(sentryPlugin); | ||
|
||
const sourceMapsPreviouslyEnabled = viteInlineConfig.build?.sourcemap; | ||
// Enable source maps | ||
viteInlineConfig.build = viteInlineConfig.build || {}; | ||
viteInlineConfig.build.sourcemap = true; | ||
|
||
if (moduleOptions.debug && !sourceMapsPreviouslyEnabled) { | ||
// eslint-disable-next-line no-console | ||
console.log('[Sentry]: Enabled source maps generation in the Vite build options.'); | ||
if (!moduleOptions.sourceMapsUploadOptions?.sourcemaps?.filesToDeleteAfterUpload) { | ||
// eslint-disable-next-line no-console | ||
console.warn( | ||
`[Sentry] We recommend setting the \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload\` option to clean up source maps after uploading. | ||
[Sentry] Otherwise, source maps might be deployed to production, depending on your configuration`, | ||
); | ||
logDebugInfo(moduleOptions, viteInlineConfig.build?.sourcemap); | ||
} | ||
}); | ||
|
||
nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => { | ||
if (sourceMapsEnabled && !nitroConfig.dev) { | ||
const sentryPlugin = sentryRollupPlugin(getPluginOptions(moduleOptions)); | ||
|
||
if (nitroConfig.rollupConfig) { | ||
// Add Sentry plugin | ||
if (!Array.isArray(nitroConfig.rollupConfig.plugins)) { | ||
nitroConfig.rollupConfig.plugins = nitroConfig.rollupConfig.plugins ? [nitroConfig.rollupConfig.plugins] : []; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would you mind adding a short comment why we are overriding the plugins with themselves but as a single item in an array? 🤔 What is happening here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the type it is not always an array and I am converting it to an array to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question is, is converting it from whatever it is to an array safe? |
||
} | ||
} | ||
nitroConfig.rollupConfig.plugins.push(sentryPlugin); | ||
|
||
viteInlineConfig.build = viteInlineConfig.build || {}; | ||
viteInlineConfig.build.sourcemap = true; | ||
// Enable source maps | ||
nitroConfig.rollupConfig.output = nitroConfig?.rollupConfig?.output || {}; | ||
nitroConfig.rollupConfig.output.sourcemap = true; | ||
nitroConfig.rollupConfig.output.sourcemapExcludeSources = false; // Adding "sourcesContent" to the source map (Nitro sets this eto `true`) | ||
|
||
logDebugInfo(moduleOptions, nitroConfig.rollupConfig.output?.sourcemap); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Normalizes the beginning of a path from e.g. ../../../ to ./ | ||
*/ | ||
function normalizePath(path: string): string { | ||
return path.replace(/^(\.\.\/)+/, './'); | ||
} | ||
|
||
function getPluginOptions(moduleOptions: SentryNuxtModuleOptions): object { | ||
lforst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {}; | ||
|
||
return { | ||
org: sourceMapsUploadOptions.org ?? process.env.SENTRY_ORG, | ||
project: sourceMapsUploadOptions.project ?? process.env.SENTRY_PROJECT, | ||
authToken: sourceMapsUploadOptions.authToken ?? process.env.SENTRY_AUTH_TOKEN, | ||
telemetry: sourceMapsUploadOptions.telemetry ?? true, | ||
sourcemaps: { | ||
assets: sourceMapsUploadOptions.sourcemaps?.assets ?? ['./.output/public/**/*', './.output/server/**/*'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. m: I am wondering whether we will upload the same exact thing twice here because the plugin runs two times, one for nitro and one for nuxt. Is there a way we can avoid (too much) duplication? Sometimes it's unavoidable but here it might be possible to avoid it. |
||
ignore: sourceMapsUploadOptions.sourcemaps?.ignore ?? undefined, | ||
filesToDeleteAfterUpload: sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload ?? undefined, | ||
rewriteSources: (source: string) => normalizePath(source), | ||
}, | ||
_metaOptions: { | ||
telemetry: { | ||
metaFramework: 'nuxt', | ||
}, | ||
}, | ||
debug: moduleOptions.debug ?? false, | ||
}; | ||
} | ||
|
||
function logDebugInfo(moduleOptions: SentryNuxtModuleOptions, sourceMapsPreviouslyEnabled: boolean): void { | ||
if (moduleOptions.debug && !sourceMapsPreviouslyEnabled) { | ||
// eslint-disable-next-line no-console | ||
console.log('[Sentry]: Enabled source maps generation in the Vite build options.'); | ||
|
||
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {}; | ||
|
||
if (!sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload) { | ||
// eslint-disable-next-line no-console | ||
console.warn( | ||
`[Sentry] We recommend setting the \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload\` option to clean up source maps after uploading. | ||
[Sentry] Otherwise, source maps might be deployed to production, depending on your configuration`, | ||
lforst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
h: Can we move this assignment inside the if statment where we use the variable? In general I would avoid creating variables for things we only use once (unless it becomes absolutely unreadable). It tricks you into thinking something is used in more than one place.