Skip to content
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

Merged
merged 10 commits into from
Sep 4, 2024
3 changes: 2 additions & 1 deletion packages/nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@
"@sentry/core": "8.26.0",
"@sentry/node": "8.26.0",
"@sentry/opentelemetry": "8.26.0",
"@sentry/rollup-plugin": "2.22.1",
"@sentry/types": "8.26.0",
"@sentry/utils": "8.26.0",
"@sentry/vite-plugin": "2.20.1",
"@sentry/vite-plugin": "2.22.1",
"@sentry/vue": "8.26.0"
},
"devDependencies": {
Expand Down
117 changes: 79 additions & 38 deletions packages/nuxt/src/vite/sourceMaps.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,93 @@
import type { Nuxt } from '@nuxt/schema';
import { sentryVitePlugin } from '@sentry/vite-plugin';
import { type SentryRollupPluginOptions, sentryRollupPlugin } from '@sentry/rollup-plugin';
import { type SentryVitePluginOptions, 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.
* Setup source maps for Sentry inside the Nuxt module during build time (in Vite for Nuxt and Rollup for Nitro).
*/
export function setupSourceMaps(moduleOptions: SentryNuxtModuleOptions, nuxt: Nuxt): void {
nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => {
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};

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,
});
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};
const sourceMapsEnabled = sourceMapsUploadOptions.enabled ?? true;

nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => {
if (sourceMapsEnabled && viteInlineConfig.mode !== 'development') {
// Add Sentry plugin
viteInlineConfig.plugins = viteInlineConfig.plugins || [];
viteInlineConfig.plugins.push(sentryPlugin);

const sourceMapsPreviouslyEnabled = viteInlineConfig.build?.sourcemap;

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`,
);
}
}
viteInlineConfig.plugins.push(sentryVitePlugin(getPluginOptions(moduleOptions)));

// Enable source maps
viteInlineConfig.build = viteInlineConfig.build || {};
viteInlineConfig.build.sourcemap = true;

logDebugInfo(moduleOptions, viteInlineConfig.build?.sourcemap);
}
});

nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => {
if (sourceMapsEnabled && !nitroConfig.dev) {
if (nitroConfig.rollupConfig) {
// Add Sentry plugin
if (!Array.isArray(nitroConfig.rollupConfig.plugins)) {
nitroConfig.rollupConfig.plugins = nitroConfig.rollupConfig.plugins ? [nitroConfig.rollupConfig.plugins] : [];
Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Member Author

Choose a reason for hiding this comment

The 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 .push the plugin later on

Copy link
Member

Choose a reason for hiding this comment

The 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(sentryRollupPlugin(getPluginOptions(moduleOptions)));

// 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): SentryVitePluginOptions | SentryRollupPluginOptions {
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/**/*'],
Copy link
Member

Choose a reason for hiding this comment

The 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. Otherwise, source maps might be deployed to production, depending on your configuration',
);
}
}
}
51 changes: 43 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8195,6 +8195,11 @@
resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz#a7e1cc99d1a738d1eb17757341dff4db3a93c2dc"
integrity sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==

"@sentry/babel-plugin-component-annotate@2.22.1":
version "2.22.1"
resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.1.tgz#2877af31f1d0358202593fe6d14141827a2f1e42"
integrity sha512-rQEk8EeCIBQKivWNONllQhd/wGbfuK/WXJRM6TkjeikM3wrqJf4AmIBXoA6eg089DwBFzBaxGjjLWJNHKY440w==

"@sentry/bundler-plugin-core@2.16.0":
version "2.16.0"
resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.16.0.tgz#0c33e7a054fb56e43bd160ac141f71dfebf6dda5"
Expand Down Expand Up @@ -8251,6 +8256,20 @@
magic-string "0.30.8"
unplugin "1.0.1"

"@sentry/bundler-plugin-core@2.22.1":
version "2.22.1"
resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.1.tgz#a3c984fd0e6a7bc3977cd74a635f6222e69c4ef2"
integrity sha512-RFbS57zfPvUBe4DL/pjt6BWCEyGFkk/n4gLNZQ9Cf2gRdUVW80AtAMZwrlEELrpW1D8kONy6/kvWf0leicHRMg==
dependencies:
"@babel/core" "^7.18.5"
"@sentry/babel-plugin-component-annotate" "2.22.1"
"@sentry/cli" "^2.33.1"
dotenv "^16.3.1"
find-up "^5.0.0"
glob "^9.3.2"
magic-string "0.30.8"
unplugin "1.0.1"

"@sentry/cli-darwin@2.33.0":
version "2.33.0"
resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.33.0.tgz#c0f3352a9e58e4f02deca52f0d5a9bd14b3e4a32"
Expand Down Expand Up @@ -8359,6 +8378,14 @@
"@sentry/cli-win32-i686" "2.33.1"
"@sentry/cli-win32-x64" "2.33.1"

"@sentry/rollup-plugin@2.22.1":
version "2.22.1"
resolved "https://registry.yarnpkg.com/@sentry/rollup-plugin/-/rollup-plugin-2.22.1.tgz#644e6e47d4130bca31a578782813835ca243a484"
integrity sha512-ytioqf5e9lyuDc4G8cK0kMtl6DUUuPaE2ob583esnzEw/X15fpvdJOkBDNbyCtOrArm8me8o5lM47vi6FTv1vA==
dependencies:
"@sentry/bundler-plugin-core" "2.22.1"
unplugin "1.0.1"

"@sentry/vite-plugin@2.19.0":
version "2.19.0"
resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.19.0.tgz#c7938fb13eee15036963b87d7b12c4fc851e488b"
Expand All @@ -8367,14 +8394,6 @@
"@sentry/bundler-plugin-core" "2.19.0"
unplugin "1.0.1"

"@sentry/vite-plugin@2.20.1", "@sentry/vite-plugin@^2.20.1":
version "2.20.1"
resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.20.1.tgz#80d5639fca3f68fbf81c316883272ffb34dbc544"
integrity sha512-IOYAJRcV+Uqn0EL8rxcoCvE77PbtGzKjP+B6iIgDZ229AWbpfbpWY8zHCcufwdDzb5PtgOhWWHT74iAsNyij/A==
dependencies:
"@sentry/bundler-plugin-core" "2.20.1"
unplugin "1.0.1"

"@sentry/vite-plugin@2.22.0":
version "2.22.0"
resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.22.0.tgz#09743ac390cf8c1609f2fa6d5424548d0b6f7928"
Expand All @@ -8383,6 +8402,22 @@
"@sentry/bundler-plugin-core" "2.22.0"
unplugin "1.0.1"

"@sentry/vite-plugin@2.22.1":
version "2.22.1"
resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.22.1.tgz#66192485440fd7f3726279a6bda2de4e59e6fd13"
integrity sha512-TC+3RIcu0rnxaEPV8ZHjYlRHLx5M9eRDI2il1lFkSguTc0N89n7Tt/aDnFAwtaPG4yqPkhIMpxi7LfXx+YDJ1Q==
dependencies:
"@sentry/bundler-plugin-core" "2.22.1"
unplugin "1.0.1"

"@sentry/vite-plugin@^2.20.1":
version "2.20.1"
resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.20.1.tgz#80d5639fca3f68fbf81c316883272ffb34dbc544"
integrity sha512-IOYAJRcV+Uqn0EL8rxcoCvE77PbtGzKjP+B6iIgDZ229AWbpfbpWY8zHCcufwdDzb5PtgOhWWHT74iAsNyij/A==
dependencies:
"@sentry/bundler-plugin-core" "2.20.1"
unplugin "1.0.1"

"@sentry/webpack-plugin@2.16.0":
version "2.16.0"
resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-2.16.0.tgz#4764577edb10c9575a8b4ce03135493f995f56b9"
Expand Down
Loading