diff --git a/CHANGELOG.md b/CHANGELOG.md index 005f0204866b..936edff4c346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott -Work in this release was contributed by @KyGuy2002 and @artzhookov. Thank you for your contributions! +Work in this release was contributed by @KyGuy2002, @artzhookov, and @julianCast. Thank you for your contributions! ## 8.30.0 diff --git a/packages/gatsby/README.md b/packages/gatsby/README.md index 5de12ed78410..cf5eadf7045b 100644 --- a/packages/gatsby/README.md +++ b/packages/gatsby/README.md @@ -65,6 +65,24 @@ module.exports = { }; ``` +Additionally, you can delete source map files after they have been uploaded by setting the `deleteSourcemapsAfterUpload` +option to be `true`. + +```javascript +module.exports = { + // ... + plugins: [ + { + resolve: '@sentry/gatsby', + options: { + deleteSourcemapsAfterUpload: true, + }, + }, + // ... + ], +}; +``` + ## Links - [Official SDK Docs](https://docs.sentry.io/quickstart/) diff --git a/packages/gatsby/gatsby-node.js b/packages/gatsby/gatsby-node.js index de88ee73adc0..911fcda7b437 100644 --- a/packages/gatsby/gatsby-node.js +++ b/packages/gatsby/gatsby-node.js @@ -7,12 +7,15 @@ const SENTRY_USER_CONFIG = ['./sentry.config.js', './sentry.config.ts']; exports.onCreateWebpackConfig = ({ getConfig, actions }, options) => { const enableClientWebpackPlugin = options.enableClientWebpackPlugin !== false; if (process.env.NODE_ENV === 'production' && enableClientWebpackPlugin) { + const deleteSourcemapsAfterUpload = options.deleteSourcemapsAfterUpload === true; actions.setWebpackConfig({ plugins: [ sentryWebpackPlugin({ sourcemaps: { // Only include files from the build output directory assets: ['./public/**'], + // Delete source files after uploading + filesToDeleteAfterUpload: deleteSourcemapsAfterUpload ? ['./public/**/*.map'] : undefined, // Ignore files that aren't users' source code related ignore: [ 'polyfill-*', // related to polyfills diff --git a/packages/gatsby/test/gatsby-node.test.ts b/packages/gatsby/test/gatsby-node.test.ts index 2e80ac03dcaa..006cb6f9e2c0 100644 --- a/packages/gatsby/test/gatsby-node.test.ts +++ b/packages/gatsby/test/gatsby-node.test.ts @@ -1,5 +1,12 @@ +import { sentryWebpackPlugin } from '@sentry/webpack-plugin'; import { onCreateWebpackConfig } from '../gatsby-node'; +jest.mock('@sentry/webpack-plugin', () => ({ + sentryWebpackPlugin: jest.fn().mockReturnValue({ + apply: jest.fn(), + }), +})); + describe('onCreateWebpackConfig', () => { let originalNodeEnv: string | undefined; @@ -12,6 +19,10 @@ describe('onCreateWebpackConfig', () => { process.env.NODE_ENV = originalNodeEnv; }); + afterEach(() => { + jest.clearAllMocks(); + }); + it('sets a webpack config', () => { const actions = { setWebpackConfig: jest.fn(), @@ -36,4 +47,24 @@ describe('onCreateWebpackConfig', () => { expect(actions.setWebpackConfig).toHaveBeenCalledTimes(0); }); + + it('sets sourceMapFilesToDeleteAfterUpload when provided in options', () => { + const actions = { + setWebpackConfig: jest.fn(), + }; + + const getConfig = jest.fn(); + + onCreateWebpackConfig({ actions, getConfig }, { deleteSourcemapsAfterUpload: true }); + + expect(actions.setWebpackConfig).toHaveBeenCalledTimes(1); + + expect(sentryWebpackPlugin).toHaveBeenCalledWith( + expect.objectContaining({ + sourcemaps: expect.objectContaining({ + filesToDeleteAfterUpload: ['./public/**/*.map'], + }), + }), + ); + }); }); diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index 9be1474958bd..c74fe32b93fe 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -64,12 +64,13 @@ export default defineNuxtModule({ if (clientConfigFile || serverConfigFile) { setupSourceMaps(moduleOptions, nuxt); } + nuxt.hooks.hook('nitro:init', nitro => { if (serverConfigFile && serverConfigFile.includes('.server.config')) { - addServerConfigToBuild(moduleOptions, nuxt, serverConfigFile); + addServerConfigToBuild(moduleOptions, nuxt, nitro, serverConfigFile); if (moduleOptions.experimental_basicServerTracing) { - addSentryTopImport(moduleOptions, nuxt); + addSentryTopImport(moduleOptions, nitro); } else { if (moduleOptions.debug) { const serverDirResolver = createResolver(nitro.options.output.serverDir); diff --git a/packages/nuxt/src/vite/addServerConfig.ts b/packages/nuxt/src/vite/addServerConfig.ts index 60f2452cde5b..845228c58b0c 100644 --- a/packages/nuxt/src/vite/addServerConfig.ts +++ b/packages/nuxt/src/vite/addServerConfig.ts @@ -2,6 +2,7 @@ import * as fs from 'fs'; import { createResolver } from '@nuxt/kit'; import type { Nuxt } from '@nuxt/schema'; import { consoleSandbox } from '@sentry/utils'; +import type { Nitro } from 'nitropack'; import type { SentryNuxtModuleOptions } from '../common/types'; /** @@ -13,6 +14,7 @@ import type { SentryNuxtModuleOptions } from '../common/types'; export function addServerConfigToBuild( moduleOptions: SentryNuxtModuleOptions, nuxt: Nuxt, + nitro: Nitro, serverConfigFile: string, ): void { nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => { @@ -29,10 +31,11 @@ export function addServerConfigToBuild( * When the build process is finished, copy the `sentry.server.config` file to the `.output` directory. * This is necessary because we need to reference this file path in the node --import option. */ - nuxt.hook('close', async () => { - const rootDirResolver = createResolver(nuxt.options.rootDir); - const source = rootDirResolver.resolve('.nuxt/dist/server/sentry.server.config.mjs'); - const destination = rootDirResolver.resolve('.output/server/sentry.server.config.mjs'); + nitro.hooks.hook('close', async () => { + const buildDirResolver = createResolver(nitro.options.buildDir); + const serverDirResolver = createResolver(nitro.options.output.serverDir); + const source = buildDirResolver.resolve('dist/server/sentry.server.config.mjs'); + const destination = serverDirResolver.resolve('sentry.server.config.mjs'); try { await fs.promises.access(source, fs.constants.F_OK); @@ -66,10 +69,19 @@ export function addServerConfigToBuild( * This is necessary for environments where modifying the node option `--import` is not possible. * However, only limited tracing instrumentation is supported when doing this. */ -export function addSentryTopImport(moduleOptions: SentryNuxtModuleOptions, nuxt: Nuxt): void { - nuxt.hook('close', async () => { - const rootDirResolver = createResolver(nuxt.options.rootDir); - const entryFilePath = rootDirResolver.resolve('.output/server/index.mjs'); +export function addSentryTopImport(moduleOptions: SentryNuxtModuleOptions, nitro: Nitro): void { + nitro.hooks.hook('close', () => { + // other presets ('node-server' or 'vercel') have an index.mjs + const presetsWithServerFile = ['netlify']; + const entryFileName = + typeof nitro.options.rollupConfig?.output.entryFileNames === 'string' + ? nitro.options.rollupConfig?.output.entryFileNames + : presetsWithServerFile.includes(nitro.options.preset) + ? 'server.mjs' + : 'index.mjs'; + + const serverDirResolver = createResolver(nitro.options.output.serverDir); + const entryFilePath = serverDirResolver.resolve(entryFileName); try { fs.readFile(entryFilePath, 'utf8', (err, data) => {