Skip to content

Commit

Permalink
feat(nuxt): Upload sourcemaps generated by Nitro (#13382)
Browse files Browse the repository at this point in the history
Adding another source maps generation step with rollup to include
Nitro-generated source maps as well.

closes #13383
  • Loading branch information
s1gr1d authored Sep 4, 2024
1 parent c4f68d8 commit 80ec41a
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 38 deletions.
1 change: 1 addition & 0 deletions packages/nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@sentry/core": "8.28.0",
"@sentry/node": "8.28.0",
"@sentry/opentelemetry": "8.28.0",
"@sentry/rollup-plugin": "2.22.3",
"@sentry/types": "8.28.0",
"@sentry/utils": "8.28.0",
"@sentry/vite-plugin": "2.22.3",
Expand Down
126 changes: 88 additions & 38 deletions packages/nuxt/src/vite/sourceMaps.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,102 @@
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) {
nitroConfig.rollupConfig = {};
}

if (nitroConfig.rollupConfig.plugins === null || nitroConfig.rollupConfig.plugins === undefined) {
nitroConfig.rollupConfig.plugins = [];
} else if (!Array.isArray(nitroConfig.rollupConfig.plugins)) {
// `rollupConfig.plugins` can be a single plugin, so we want to put it into an array so that we can push our own plugin
nitroConfig.rollupConfig.plugins = [nitroConfig.rollupConfig.plugins];
}

// Add Sentry plugin
nitroConfig.rollupConfig.plugins.push(sentryRollupPlugin(getPluginOptions(moduleOptions, 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,
isNitro = false,
): 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 ?? isNitro ? ['./.output/server/**/*'] : ['./.output/public/**/*'],
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',
);
}
}
}
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8309,6 +8309,14 @@
"@sentry/cli-win32-i686" "2.33.1"
"@sentry/cli-win32-x64" "2.33.1"

"@sentry/rollup-plugin@2.22.3":
version "2.22.3"
resolved "https://registry.yarnpkg.com/@sentry/rollup-plugin/-/rollup-plugin-2.22.3.tgz#18ab4b7903ee723bee4cf789b38bb3febb05faae"
integrity sha512-I1UsnYzZm5W7/Pyah2yxuMRxmzgf5iDKoptFfMaerpRO5oBhFO3tMnKSLAlYMvuXKRoYkInNv6ckkUcSOF6jig==
dependencies:
"@sentry/bundler-plugin-core" "2.22.3"
unplugin "1.0.1"

"@sentry/vite-plugin@2.22.3", "@sentry/vite-plugin@^2.22.3":
version "2.22.3"
resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.22.3.tgz#b52802412b6f3d8e3e56742afc9624d9babae5b6"
Expand Down

0 comments on commit 80ec41a

Please sign in to comment.