From 25db74182598282491327fb368bb0513fafe559f Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Thu, 9 Jan 2025 12:49:04 +0100 Subject: [PATCH 1/7] automatically enable deleteSourceMapsAfterUpload --- packages/nextjs/src/config/webpack.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 9a218bda6435..a942e1090f12 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -336,11 +336,15 @@ export function constructWebpackConfigFunction( if (sentryWebpackPlugin) { if (!userSentryOptions.sourcemaps?.disable) { - // TODO(v9): Remove this warning and print warning in case source map deletion is auto configured - if (!isServer && !userSentryOptions.sourcemaps?.deleteSourcemapsAfterUpload) { + // enable source map deletion if not explicitly disabled + if (!isServer && userSentryOptions.sourcemaps?.deleteSourcemapsAfterUpload === undefined) { + userSentryOptions.sourcemaps = { + ...userSentryOptions.sourcemaps, + deleteSourcemapsAfterUpload: true, + }; // eslint-disable-next-line no-console console.warn( - "[@sentry/nextjs] The Sentry SDK has enabled source map generation for your Next.js app. If you don't want to serve Source Maps to your users, either set the `sourcemaps.deleteSourcemapsAfterUpload` option to true, or manually delete the source maps after the build. In future Sentry SDK versions `sourcemaps.deleteSourcemapsAfterUpload` will default to `true`. If you do not want to generate and upload sourcemaps, set the `sourcemaps.disable` option in `withSentryConfig()`.", + '[@sentry/nextjs] Source maps will be automatically deleted after being uploaded to Sentry. If you want to keep the source maps, set the `sourcemaps.deleteSourcemapsAfterUpload` option to false in `withSentryConfig()`. If you do not want to generate and upload sourcemaps at all, set the `sourcemaps.disable` option to true.', ); } From 0bd800be5b0d41bcc2514155def4c4021f8b6ab9 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Thu, 9 Jan 2025 13:19:03 +0100 Subject: [PATCH 2/7] update webpack sourcemap generation --- packages/nextjs/src/config/webpack.ts | 39 ++++++++++++++++++--------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index a942e1090f12..ae33c538ef6e 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -338,25 +338,38 @@ export function constructWebpackConfigFunction( if (!userSentryOptions.sourcemaps?.disable) { // enable source map deletion if not explicitly disabled if (!isServer && userSentryOptions.sourcemaps?.deleteSourcemapsAfterUpload === undefined) { + logger.warn( + '[@sentry/nextjs] Source maps will be automatically deleted after being uploaded to Sentry. If you want to keep the source maps, set the `sourcemaps.deleteSourcemapsAfterUpload` option to false in `withSentryConfig()`. If you do not want to generate and upload sourcemaps at all, set the `sourcemaps.disable` option to true.', + ); userSentryOptions.sourcemaps = { ...userSentryOptions.sourcemaps, deleteSourcemapsAfterUpload: true, }; - // eslint-disable-next-line no-console - console.warn( - '[@sentry/nextjs] Source maps will be automatically deleted after being uploaded to Sentry. If you want to keep the source maps, set the `sourcemaps.deleteSourcemapsAfterUpload` option to false in `withSentryConfig()`. If you do not want to generate and upload sourcemaps at all, set the `sourcemaps.disable` option to true.', - ); } - // `hidden-source-map` produces the same sourcemaps as `source-map`, but doesn't include the `sourceMappingURL` - // comment at the bottom. For folks who aren't publicly hosting their sourcemaps, this is helpful because then - // the browser won't look for them and throw errors into the console when it can't find them. Because this is a - // front-end-only problem, and because `sentry-cli` handles sourcemaps more reliably with the comment than - // without, the option to use `hidden-source-map` only applies to the client-side build. - if (isServer || userNextConfig.productionBrowserSourceMaps) { - newConfig.devtool = 'source-map'; - } else { - newConfig.devtool = 'hidden-source-map'; + // Source maps can be configured in 3 ways: + // 1. (next config): productionBrowserSourceMaps + // 2. (next config): experimental.serverSourceMaps + // 3. custom webpack configuration + // + // We only update this if no explicit value is set + // (Next.js defaults to `false`: https://github.com/vercel/next.js/blob/5f4f96c133bd6b10954812cc2fef6af085b82aa5/packages/next/src/build/webpack/config/blocks/base.ts#L61) + if (newConfig.devtool === false) { + logger.info( + `[@sentry/nextjs] Automatically enabling source map generation for ${ + isServer ? 'server' : 'client' + } build.`, + ); + // `hidden-source-map` produces the same sourcemaps as `source-map`, but doesn't include the `sourceMappingURL` + // comment at the bottom. For folks who aren't publicly hosting their sourcemaps, this is helpful because then + // the browser won't look for them and throw errors into the console when it can't find them. Because this is a + // front-end-only problem, and because `sentry-cli` handles sourcemaps more reliably with the comment than + // without, the option to use `hidden-source-map` only applies to the client-side build. + if (isServer) { + newConfig.devtool = 'source-map'; + } else { + newConfig.devtool = 'hidden-source-map'; + } } } From 850f549c1b0f91d82bbec1b9ea0684940a6707c8 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Thu, 9 Jan 2025 17:27:05 +0100 Subject: [PATCH 3/7] set devtool for undefined as well --- packages/nextjs/src/config/webpack.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index ae33c538ef6e..3002a7523f49 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -354,7 +354,7 @@ export function constructWebpackConfigFunction( // // We only update this if no explicit value is set // (Next.js defaults to `false`: https://github.com/vercel/next.js/blob/5f4f96c133bd6b10954812cc2fef6af085b82aa5/packages/next/src/build/webpack/config/blocks/base.ts#L61) - if (newConfig.devtool === false) { + if (!newConfig.devtool) { logger.info( `[@sentry/nextjs] Automatically enabling source map generation for ${ isServer ? 'server' : 'client' From d1ee93b5d14e0b808823e1194a300a94a23abfe6 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Thu, 9 Jan 2025 18:20:30 +0100 Subject: [PATCH 4/7] add missing tests --- .../webpack/constructWebpackConfig.test.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts b/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts index 20af1d99f1ce..4e99dd61950b 100644 --- a/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts +++ b/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts @@ -1,6 +1,7 @@ // mock helper functions not tested directly in this file import '../mocks'; +import * as getWebpackPluginOptionsModule from '../../../src/config/webpackPluginOptions'; import { CLIENT_SDK_CONFIG_FILE, clientBuildContext, @@ -29,6 +30,48 @@ describe('constructWebpackConfigFunction()', () => { ); }); + it('preserves existing devtool setting', async () => { + const customDevtool = 'eval-source-map'; + const finalWebpackConfig = await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: { + ...serverWebpackConfig, + devtool: customDevtool, + }, + incomingWebpackBuildContext: serverBuildContext, + sentryBuildTimeOptions: {}, + }); + + expect(finalWebpackConfig.devtool).toEqual(customDevtool); + }); + + it('automatically enables deleteSourcemapsAfterUpload for client builds when not explicitly set', async () => { + const getWebpackPluginOptionsSpy = jest.spyOn(getWebpackPluginOptionsModule, 'getWebpackPluginOptions'); + + await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: clientWebpackConfig, + incomingWebpackBuildContext: clientBuildContext, + sentryBuildTimeOptions: { + sourcemaps: {}, + }, + }); + + expect(getWebpackPluginOptionsSpy).toHaveBeenCalledWith( + expect.objectContaining({ + isServer: false, + }), + expect.objectContaining({ + sourcemaps: { + deleteSourcemapsAfterUpload: true, + }, + }), + undefined, + ); + + getWebpackPluginOptionsSpy.mockRestore(); + }); + it('preserves unrelated webpack config options', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ exportedNextConfig, From 57f0223e86081110cf6de1294521f1f96e017af3 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Thu, 9 Jan 2025 19:53:49 +0100 Subject: [PATCH 5/7] add migration entry --- docs/migration/v8-to-v9.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/migration/v8-to-v9.md b/docs/migration/v8-to-v9.md index 84e0526d102d..39ddc9c14439 100644 --- a/docs/migration/v8-to-v9.md +++ b/docs/migration/v8-to-v9.md @@ -98,6 +98,10 @@ In v9, an `undefined` value will be treated the same as if the value is not defi This behavior was changed because the Next.js Build ID is non-deterministic and the release name is injected into client bundles, causing build artifacts to be non-deterministic. This caused issues for some users. Additionally, because it is uncertain whether it will be possible to rely on a Build ID when Turbopack becomes stable, we decided to pull the plug now instead of introducing confusing behavior in the future. +- By default, source maps will now be automatically deleted after being uploaded to Sentry for client-side builds. You can opt out of this behavior by explicitly setting `sourcemaps.deleteSourcemapsAfterUpload` to `false` in your Sentry config. + +- Source maps are now automatically enabled for both client and server builds unless explicitly disabled via `sourcemaps.disable`. Client builds use `hidden-source-map` while server builds use `source-map` as their webpack `devtool` setting unless any other value than `false` or `undefined` has been assigned already. + ### Uncategorized (TODO) TODO From f980e6cea476037e98543d4bd844001cfea9ad03 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Fri, 10 Jan 2025 13:08:35 +0100 Subject: [PATCH 6/7] Update packages/nextjs/src/config/webpack.ts Co-authored-by: Luca Forstner --- packages/nextjs/src/config/webpack.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 3002a7523f49..dfc54494c9ff 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -357,7 +357,7 @@ export function constructWebpackConfigFunction( if (!newConfig.devtool) { logger.info( `[@sentry/nextjs] Automatically enabling source map generation for ${ - isServer ? 'server' : 'client' + runtime } build.`, ); // `hidden-source-map` produces the same sourcemaps as `source-map`, but doesn't include the `sourceMappingURL` From 9182421e52867b1e6b20d7b3860e2c6be1e1fe3d Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Fri, 10 Jan 2025 13:11:19 +0100 Subject: [PATCH 7/7] flip stuff around --- docs/migration/v8-to-v9.md | 4 ++-- packages/nextjs/src/config/webpack.ts | 28 ++++++++++++--------------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/docs/migration/v8-to-v9.md b/docs/migration/v8-to-v9.md index 3aa5295a61a1..390d455c891b 100644 --- a/docs/migration/v8-to-v9.md +++ b/docs/migration/v8-to-v9.md @@ -100,10 +100,10 @@ In v9, an `undefined` value will be treated the same as if the value is not defi This behavior was changed because the Next.js Build ID is non-deterministic and the release name is injected into client bundles, causing build artifacts to be non-deterministic. This caused issues for some users. Additionally, because it is uncertain whether it will be possible to rely on a Build ID when Turbopack becomes stable, we decided to pull the plug now instead of introducing confusing behavior in the future. -- By default, source maps will now be automatically deleted after being uploaded to Sentry for client-side builds. You can opt out of this behavior by explicitly setting `sourcemaps.deleteSourcemapsAfterUpload` to `false` in your Sentry config. - - Source maps are now automatically enabled for both client and server builds unless explicitly disabled via `sourcemaps.disable`. Client builds use `hidden-source-map` while server builds use `source-map` as their webpack `devtool` setting unless any other value than `false` or `undefined` has been assigned already. +- By default, source maps will now be automatically deleted after being uploaded to Sentry for client-side builds. You can opt out of this behavior by explicitly setting `sourcemaps.deleteSourcemapsAfterUpload` to `false` in your Sentry config. + ### All Meta-Framework SDKs (`@sentry/astro`, `@sentry/nuxt`) - Updated source map generation to respect the user-provided value of your build config, such as `vite.build.sourcemap`: diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index dfc54494c9ff..80b46570c03e 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -336,17 +336,6 @@ export function constructWebpackConfigFunction( if (sentryWebpackPlugin) { if (!userSentryOptions.sourcemaps?.disable) { - // enable source map deletion if not explicitly disabled - if (!isServer && userSentryOptions.sourcemaps?.deleteSourcemapsAfterUpload === undefined) { - logger.warn( - '[@sentry/nextjs] Source maps will be automatically deleted after being uploaded to Sentry. If you want to keep the source maps, set the `sourcemaps.deleteSourcemapsAfterUpload` option to false in `withSentryConfig()`. If you do not want to generate and upload sourcemaps at all, set the `sourcemaps.disable` option to true.', - ); - userSentryOptions.sourcemaps = { - ...userSentryOptions.sourcemaps, - deleteSourcemapsAfterUpload: true, - }; - } - // Source maps can be configured in 3 ways: // 1. (next config): productionBrowserSourceMaps // 2. (next config): experimental.serverSourceMaps @@ -355,11 +344,7 @@ export function constructWebpackConfigFunction( // We only update this if no explicit value is set // (Next.js defaults to `false`: https://github.com/vercel/next.js/blob/5f4f96c133bd6b10954812cc2fef6af085b82aa5/packages/next/src/build/webpack/config/blocks/base.ts#L61) if (!newConfig.devtool) { - logger.info( - `[@sentry/nextjs] Automatically enabling source map generation for ${ - runtime - } build.`, - ); + logger.info(`[@sentry/nextjs] Automatically enabling source map generation for ${runtime} build.`); // `hidden-source-map` produces the same sourcemaps as `source-map`, but doesn't include the `sourceMappingURL` // comment at the bottom. For folks who aren't publicly hosting their sourcemaps, this is helpful because then // the browser won't look for them and throw errors into the console when it can't find them. Because this is a @@ -371,6 +356,17 @@ export function constructWebpackConfigFunction( newConfig.devtool = 'hidden-source-map'; } } + + // enable source map deletion if not explicitly disabled + if (!isServer && userSentryOptions.sourcemaps?.deleteSourcemapsAfterUpload === undefined) { + logger.warn( + '[@sentry/nextjs] Source maps will be automatically deleted after being uploaded to Sentry. If you want to keep the source maps, set the `sourcemaps.deleteSourcemapsAfterUpload` option to false in `withSentryConfig()`. If you do not want to generate and upload sourcemaps at all, set the `sourcemaps.disable` option to true.', + ); + userSentryOptions.sourcemaps = { + ...userSentryOptions.sourcemaps, + deleteSourcemapsAfterUpload: true, + }; + } } newConfig.plugins = newConfig.plugins || [];