Skip to content

Commit 80ec41a

Browse files
authored
feat(nuxt): Upload sourcemaps generated by Nitro (#13382)
Adding another source maps generation step with rollup to include Nitro-generated source maps as well. closes #13383
1 parent c4f68d8 commit 80ec41a

File tree

3 files changed

+97
-38
lines changed

3 files changed

+97
-38
lines changed

packages/nuxt/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"@sentry/core": "8.28.0",
4848
"@sentry/node": "8.28.0",
4949
"@sentry/opentelemetry": "8.28.0",
50+
"@sentry/rollup-plugin": "2.22.3",
5051
"@sentry/types": "8.28.0",
5152
"@sentry/utils": "8.28.0",
5253
"@sentry/vite-plugin": "2.22.3",

packages/nuxt/src/vite/sourceMaps.ts

+88-38
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,102 @@
11
import type { Nuxt } from '@nuxt/schema';
2-
import { sentryVitePlugin } from '@sentry/vite-plugin';
2+
import { type SentryRollupPluginOptions, sentryRollupPlugin } from '@sentry/rollup-plugin';
3+
import { type SentryVitePluginOptions, sentryVitePlugin } from '@sentry/vite-plugin';
4+
import type { NitroConfig } from 'nitropack';
35
import type { SentryNuxtModuleOptions } from '../common/types';
46

57
/**
6-
* Setup source maps for Sentry inside the Nuxt module during build time.
8+
* Setup source maps for Sentry inside the Nuxt module during build time (in Vite for Nuxt and Rollup for Nitro).
79
*/
810
export function setupSourceMaps(moduleOptions: SentryNuxtModuleOptions, nuxt: Nuxt): void {
9-
nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => {
10-
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};
11-
12-
if ((sourceMapsUploadOptions.enabled ?? true) && viteInlineConfig.mode !== 'development') {
13-
const sentryPlugin = sentryVitePlugin({
14-
org: sourceMapsUploadOptions.org ?? process.env.SENTRY_ORG,
15-
project: sourceMapsUploadOptions.project ?? process.env.SENTRY_PROJECT,
16-
authToken: sourceMapsUploadOptions.authToken ?? process.env.SENTRY_AUTH_TOKEN,
17-
telemetry: sourceMapsUploadOptions.telemetry ?? true,
18-
sourcemaps: {
19-
assets: sourceMapsUploadOptions.sourcemaps?.assets ?? undefined,
20-
ignore: sourceMapsUploadOptions.sourcemaps?.ignore ?? undefined,
21-
filesToDeleteAfterUpload: sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload ?? undefined,
22-
},
23-
_metaOptions: {
24-
telemetry: {
25-
metaFramework: 'nuxt',
26-
},
27-
},
28-
debug: moduleOptions.debug ?? false,
29-
});
11+
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};
12+
const sourceMapsEnabled = sourceMapsUploadOptions.enabled ?? true;
3013

14+
nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => {
15+
if (sourceMapsEnabled && viteInlineConfig.mode !== 'development') {
16+
// Add Sentry plugin
3117
viteInlineConfig.plugins = viteInlineConfig.plugins || [];
32-
viteInlineConfig.plugins.push(sentryPlugin);
33-
34-
const sourceMapsPreviouslyEnabled = viteInlineConfig.build?.sourcemap;
35-
36-
if (moduleOptions.debug && !sourceMapsPreviouslyEnabled) {
37-
// eslint-disable-next-line no-console
38-
console.log('[Sentry]: Enabled source maps generation in the Vite build options.');
39-
if (!moduleOptions.sourceMapsUploadOptions?.sourcemaps?.filesToDeleteAfterUpload) {
40-
// eslint-disable-next-line no-console
41-
console.warn(
42-
`[Sentry] We recommend setting the \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload\` option to clean up source maps after uploading.
43-
[Sentry] Otherwise, source maps might be deployed to production, depending on your configuration`,
44-
);
45-
}
46-
}
18+
viteInlineConfig.plugins.push(sentryVitePlugin(getPluginOptions(moduleOptions)));
4719

20+
// Enable source maps
4821
viteInlineConfig.build = viteInlineConfig.build || {};
4922
viteInlineConfig.build.sourcemap = true;
23+
24+
logDebugInfo(moduleOptions, viteInlineConfig.build?.sourcemap);
25+
}
26+
});
27+
28+
nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => {
29+
if (sourceMapsEnabled && !nitroConfig.dev) {
30+
if (!nitroConfig.rollupConfig) {
31+
nitroConfig.rollupConfig = {};
32+
}
33+
34+
if (nitroConfig.rollupConfig.plugins === null || nitroConfig.rollupConfig.plugins === undefined) {
35+
nitroConfig.rollupConfig.plugins = [];
36+
} else if (!Array.isArray(nitroConfig.rollupConfig.plugins)) {
37+
// `rollupConfig.plugins` can be a single plugin, so we want to put it into an array so that we can push our own plugin
38+
nitroConfig.rollupConfig.plugins = [nitroConfig.rollupConfig.plugins];
39+
}
40+
41+
// Add Sentry plugin
42+
nitroConfig.rollupConfig.plugins.push(sentryRollupPlugin(getPluginOptions(moduleOptions, true)));
43+
44+
// Enable source maps
45+
nitroConfig.rollupConfig.output = nitroConfig?.rollupConfig?.output || {};
46+
nitroConfig.rollupConfig.output.sourcemap = true;
47+
nitroConfig.rollupConfig.output.sourcemapExcludeSources = false; // Adding "sourcesContent" to the source map (Nitro sets this eto `true`)
48+
49+
logDebugInfo(moduleOptions, nitroConfig.rollupConfig.output?.sourcemap);
5050
}
5151
});
5252
}
53+
54+
/**
55+
* Normalizes the beginning of a path from e.g. ../../../ to ./
56+
*/
57+
function normalizePath(path: string): string {
58+
return path.replace(/^(\.\.\/)+/, './');
59+
}
60+
61+
function getPluginOptions(
62+
moduleOptions: SentryNuxtModuleOptions,
63+
isNitro = false,
64+
): SentryVitePluginOptions | SentryRollupPluginOptions {
65+
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};
66+
67+
return {
68+
org: sourceMapsUploadOptions.org ?? process.env.SENTRY_ORG,
69+
project: sourceMapsUploadOptions.project ?? process.env.SENTRY_PROJECT,
70+
authToken: sourceMapsUploadOptions.authToken ?? process.env.SENTRY_AUTH_TOKEN,
71+
telemetry: sourceMapsUploadOptions.telemetry ?? true,
72+
sourcemaps: {
73+
assets:
74+
sourceMapsUploadOptions.sourcemaps?.assets ?? isNitro ? ['./.output/server/**/*'] : ['./.output/public/**/*'],
75+
ignore: sourceMapsUploadOptions.sourcemaps?.ignore ?? undefined,
76+
filesToDeleteAfterUpload: sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload ?? undefined,
77+
rewriteSources: (source: string) => normalizePath(source),
78+
},
79+
_metaOptions: {
80+
telemetry: {
81+
metaFramework: 'nuxt',
82+
},
83+
},
84+
debug: moduleOptions.debug ?? false,
85+
};
86+
}
87+
88+
function logDebugInfo(moduleOptions: SentryNuxtModuleOptions, sourceMapsPreviouslyEnabled: boolean): void {
89+
if (moduleOptions.debug && !sourceMapsPreviouslyEnabled) {
90+
// eslint-disable-next-line no-console
91+
console.log('[Sentry]: Enabled source maps generation in the Vite build options.');
92+
93+
const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};
94+
95+
if (!sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload) {
96+
// eslint-disable-next-line no-console
97+
console.warn(
98+
'[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',
99+
);
100+
}
101+
}
102+
}

yarn.lock

+8
Original file line numberDiff line numberDiff line change
@@ -8309,6 +8309,14 @@
83098309
"@sentry/cli-win32-i686" "2.33.1"
83108310
"@sentry/cli-win32-x64" "2.33.1"
83118311

8312+
8313+
version "2.22.3"
8314+
resolved "https://registry.yarnpkg.com/@sentry/rollup-plugin/-/rollup-plugin-2.22.3.tgz#18ab4b7903ee723bee4cf789b38bb3febb05faae"
8315+
integrity sha512-I1UsnYzZm5W7/Pyah2yxuMRxmzgf5iDKoptFfMaerpRO5oBhFO3tMnKSLAlYMvuXKRoYkInNv6ckkUcSOF6jig==
8316+
dependencies:
8317+
"@sentry/bundler-plugin-core" "2.22.3"
8318+
unplugin "1.0.1"
8319+
83128320
"@sentry/[email protected]", "@sentry/vite-plugin@^2.22.3":
83138321
version "2.22.3"
83148322
resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.22.3.tgz#b52802412b6f3d8e3e56742afc9624d9babae5b6"

0 commit comments

Comments
 (0)