From b0523a27fe0f13e3ec2f2607a711bac1eff8c13e Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Tue, 23 Jul 2024 15:13:48 +0200 Subject: [PATCH 1/3] feat(nuxt): Setup source maps with vite config --- packages/astro/src/integration/types.ts | 2 +- packages/nuxt/.eslintrc.js | 1 + packages/nuxt/README.md | 22 ++++++-- packages/nuxt/src/common/types.ts | 67 +++++++++++++++++++++++++ packages/nuxt/src/module.ts | 11 ++-- packages/nuxt/src/vite/sourceMaps.ts | 33 ++++++++++++ 6 files changed, 127 insertions(+), 9 deletions(-) create mode 100644 packages/nuxt/src/vite/sourceMaps.ts diff --git a/packages/astro/src/integration/types.ts b/packages/astro/src/integration/types.ts index 6f182427ee47..f51a020bb290 100644 --- a/packages/astro/src/integration/types.ts +++ b/packages/astro/src/integration/types.ts @@ -70,7 +70,7 @@ type SourceMapsOptions = { telemetry?: boolean; /** - * A glob or an array of globs that specify the build artifacts and source maps that will uploaded to Sentry. + * A glob or an array of globs that specify the build artifacts and source maps that will be uploaded to Sentry. * * If this option is not specified, sensible defaults based on your `outDir`, `rootDir` and `adapter` * config will be used. Use this option to override these defaults, for instance if you have a diff --git a/packages/nuxt/.eslintrc.js b/packages/nuxt/.eslintrc.js index c1f55c94aadf..d567b12530d0 100644 --- a/packages/nuxt/.eslintrc.js +++ b/packages/nuxt/.eslintrc.js @@ -14,6 +14,7 @@ module.exports = { files: ['src/vite/**', 'src/server/**'], rules: { '@sentry-internal/sdk/no-optional-chaining': 'off', + '@sentry-internal/sdk/no-nullish-coalescing': 'off', }, }, ], diff --git a/packages/nuxt/README.md b/packages/nuxt/README.md index c75fa334b8a5..68ef80f4162c 100644 --- a/packages/nuxt/README.md +++ b/packages/nuxt/README.md @@ -140,12 +140,24 @@ Add an import flag to the node options, so the file loads before any other impor } ``` -### 5. Vite Setup - -todo: add vite setup - --- ## Uploading Source Maps -todo: add source maps instructions +To upload source maps, you can use the `sourceMapsUploadOptions` option inside the `sentry` options of your +`nuxt.config.ts`: + +```javascript +// nuxt.config.ts +export default defineNuxtConfig({ + modules: ['@sentry/nuxt/module'], + sentry: { + debug: true, + sourceMapsUploadOptions: { + org: 'your-org-slug', + project: 'your-project-slug', + authToken: process.env.SENTRY_AUTH_TOKEN, + }, + }, +}); +``` diff --git a/packages/nuxt/src/common/types.ts b/packages/nuxt/src/common/types.ts index 4b924f81192a..84c68642be02 100644 --- a/packages/nuxt/src/common/types.ts +++ b/packages/nuxt/src/common/types.ts @@ -1,4 +1,71 @@ +import type { Options } from '@sentry/types'; import type { init } from '@sentry/vue'; // Omitting 'app' as the Nuxt SDK will add the app instance in the client plugin (users do not have to provide this) export type SentryNuxtOptions = Omit[0] & object, 'app'>; + +type SourceMapsOptions = { + /** + * Options for the Sentry Vite plugin to customize the source maps upload process. + * + * These options are always read from the `sentry` module options in the `nuxt.config.(js|ts). + * Do not define them in the `sentry.client.config.(js|ts)` or `sentry.server.config.(js|ts)` files. + */ + sourceMapsUploadOptions?: { + /** + * If this flag is `true`, and an auth token is detected, the Sentry integration will + * automatically generate and upload source maps to Sentry during a production build. + * + * @default true + */ + enabled?: boolean; + + /** + * The auth token to use when uploading source maps to Sentry. + * + * Instead of specifying this option, you can also set the `SENTRY_AUTH_TOKEN` environment variable. + * + * To create an auth token, follow this guide: + * @see https://docs.sentry.io/product/accounts/auth-tokens/#organization-auth-tokens + */ + authToken?: string; + + /** + * The organization slug of your Sentry organization. + * Instead of specifying this option, you can also set the `SENTRY_ORG` environment variable. + */ + org?: string; + + /** + * The project slug of your Sentry project. + * Instead of specifying this option, you can also set the `SENTRY_PROJECT` environment variable. + */ + project?: string; + + /** + * If this flag is `true`, the Sentry plugin will collect some telemetry data and send it to Sentry. + * It will not collect any sensitive or user-specific data. + * + * @default true + */ + telemetry?: boolean; + + /** + * A glob or an array of globs that specify the build artifacts and source maps that will be uploaded to Sentry. + * + * If this option is not specified, sensible defaults based on your `outDir`, `rootDir` and `adapter` + * config will be used. Use this option to override these defaults, for instance if you have a + * customized build setup that diverges from Nuxt's defaults. + * + * The globbing patterns must follow the implementation of the `glob` package. + * @see https://www.npmjs.com/package/glob#glob-primer + */ + assets?: string | Array; + }; +}; + +/** + * The SDK options are mostly handled inside the `init` function in separate files (see type `SentryNuxtOptions`). + * Other options, such as the source maps options are added inside the `nuxt.config.ts` to be able to access those options during build time and modify the Vite config. + */ +export type SentryNuxtModuleOptions = Pick & SourceMapsOptions; diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index 9c14abd6feea..4786fe1e4aa9 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -1,9 +1,10 @@ import * as fs from 'fs'; import * as path from 'path'; import { addPlugin, addPluginTemplate, addServerPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'; -import type { SentryNuxtOptions } from './common/types'; +import type { SentryNuxtModuleOptions } from './common/types'; +import { setupSourceMaps } from './vite/sourceMaps'; -export type ModuleOptions = SentryNuxtOptions; +export type ModuleOptions = SentryNuxtModuleOptions; export default defineNuxtModule({ meta: { @@ -14,7 +15,7 @@ export default defineNuxtModule({ }, }, defaults: {}, - setup(_moduleOptions, nuxt) { + setup(moduleOptions, nuxt) { const moduleDirResolver = createResolver(import.meta.url); const buildDirResolver = createResolver(nuxt.options.buildDir); @@ -47,6 +48,10 @@ export default defineNuxtModule({ addServerPlugin(moduleDirResolver.resolve('./runtime/plugins/sentry.server')); } + + if (clientConfigFile || serverConfigFile) { + setupSourceMaps(moduleOptions, nuxt); + } }, }); diff --git a/packages/nuxt/src/vite/sourceMaps.ts b/packages/nuxt/src/vite/sourceMaps.ts new file mode 100644 index 000000000000..22d253ff1772 --- /dev/null +++ b/packages/nuxt/src/vite/sourceMaps.ts @@ -0,0 +1,33 @@ +import type { Nuxt } from '@nuxt/schema'; +import { sentryVitePlugin } from '@sentry/vite-plugin'; +import type { SentryNuxtModuleOptions } from '../common/types'; + +/** + * Setup source maps for Sentry inside the Nuxt module during build time. + */ +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 sentryPlugins = 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, + _metaOptions: { + telemetry: { + metaFramework: 'nuxt', + }, + }, + debug: moduleOptions.debug ?? false, + }); + + viteInlineConfig.plugins = viteInlineConfig.plugins || []; + viteInlineConfig.plugins.push(...sentryPlugins); + + viteInlineConfig.build = viteInlineConfig.build || {}; + viteInlineConfig.build.sourcemap = true; + } + }); +} From ea7899474db448d867f956df7b83f053f00f4213 Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Wed, 24 Jul 2024 11:21:48 +0200 Subject: [PATCH 2/3] review comments --- packages/nuxt/src/common/types.ts | 55 +++++++++++++++++------ packages/nuxt/src/vite/sourceMaps.ts | 23 +++++++++- packages/sveltekit/src/vite/sourceMaps.ts | 4 +- yarn.lock | 37 +++++++-------- 4 files changed, 81 insertions(+), 38 deletions(-) diff --git a/packages/nuxt/src/common/types.ts b/packages/nuxt/src/common/types.ts index 84c68642be02..9ec6b51daa66 100644 --- a/packages/nuxt/src/common/types.ts +++ b/packages/nuxt/src/common/types.ts @@ -1,4 +1,3 @@ -import type { Options } from '@sentry/types'; import type { init } from '@sentry/vue'; // Omitting 'app' as the Nuxt SDK will add the app instance in the client plugin (users do not have to provide this) @@ -51,21 +50,51 @@ type SourceMapsOptions = { telemetry?: boolean; /** - * A glob or an array of globs that specify the build artifacts and source maps that will be uploaded to Sentry. - * - * If this option is not specified, sensible defaults based on your `outDir`, `rootDir` and `adapter` - * config will be used. Use this option to override these defaults, for instance if you have a - * customized build setup that diverges from Nuxt's defaults. - * - * The globbing patterns must follow the implementation of the `glob` package. - * @see https://www.npmjs.com/package/glob#glob-primer + * Options related to sourcemaps */ - assets?: string | Array; + sourcemaps?: { + /** + * A glob or an array of globs that specify the build artifacts and source maps that will be uploaded to Sentry. + * + * If this option is not specified, sensible defaults based on your adapter and nuxt.config.js + * setup will be used. Use this option to override these defaults, for instance if you have a + * customized build setup that diverges from Nuxt's defaults. + * + * The globbing patterns must follow the implementation of the `glob` package. + * @see https://www.npmjs.com/package/glob#glob-primer + */ + assets?: string | Array; + + /** + * A glob or an array of globs that specifies which build artifacts should not be uploaded to Sentry. + * + * @default [] - By default no files are ignored. Thus, all files matching the `assets` glob + * or the default value for `assets` are uploaded. + * + * The globbing patterns follow the implementation of the glob package. (https://www.npmjs.com/package/glob) + */ + ignore?: string | Array; + + /** + * A glob or an array of globs that specifies the build artifacts that should be deleted after the artifact + * upload to Sentry has been completed. + * + * @default [] - By default no files are deleted. + * + * The globbing patterns follow the implementation of the glob package. (https://www.npmjs.com/package/glob) + */ + filesToDeleteAfterUpload?: string | Array; + }; }; }; /** - * The SDK options are mostly handled inside the `init` function in separate files (see type `SentryNuxtOptions`). - * Other options, such as the source maps options are added inside the `nuxt.config.ts` to be able to access those options during build time and modify the Vite config. + * Build options for the Sentry module. These options are used during build-time by the Sentry SDK. */ -export type SentryNuxtModuleOptions = Pick & SourceMapsOptions; +export type SentryNuxtModuleOptions = SourceMapsOptions & { + /** + * Enable debug functionality of the SDK during build-time. + * Enabling this will give you, for example, logs about source maps. + */ + debug: boolean; +}; diff --git a/packages/nuxt/src/vite/sourceMaps.ts b/packages/nuxt/src/vite/sourceMaps.ts index 22d253ff1772..3518c45409e0 100644 --- a/packages/nuxt/src/vite/sourceMaps.ts +++ b/packages/nuxt/src/vite/sourceMaps.ts @@ -10,11 +10,16 @@ export function setupSourceMaps(moduleOptions: SentryNuxtModuleOptions, nuxt: Nu const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {}; if ((sourceMapsUploadOptions.enabled ?? true) && viteInlineConfig.mode !== 'development') { - const sentryPlugins = sentryVitePlugin({ + 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', @@ -24,7 +29,21 @@ export function setupSourceMaps(moduleOptions: SentryNuxtModuleOptions, nuxt: Nu }); viteInlineConfig.plugins = viteInlineConfig.plugins || []; - viteInlineConfig.plugins.push(...sentryPlugins); + 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.build = viteInlineConfig.build || {}; viteInlineConfig.build.sourcemap = true; diff --git a/packages/sveltekit/src/vite/sourceMaps.ts b/packages/sveltekit/src/vite/sourceMaps.ts index 4eda112eed31..7081e09e1c5d 100644 --- a/packages/sveltekit/src/vite/sourceMaps.ts +++ b/packages/sveltekit/src/vite/sourceMaps.ts @@ -108,8 +108,8 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug // Modify the config to generate source maps config: config => { - const sourceMapsPreviouslyEnabled = !config.build?.sourcemap; - if (debug && sourceMapsPreviouslyEnabled) { + const sourceMapsPreviouslyNotEnabled = !config.build?.sourcemap; + if (debug && sourceMapsPreviouslyNotEnabled) { // eslint-disable-next-line no-console console.log('[Source Maps Plugin] Enabeling source map generation'); if (!mergedOptions.sourcemaps?.filesToDeleteAfterUpload) { diff --git a/yarn.lock b/yarn.lock index 5c6f6c6c75a7..72d28fc8f600 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5973,15 +5973,6 @@ semver "^7.3.5" tar "^6.1.11" -"@nestjs/common@^10.3.10": - version "10.3.10" - resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-10.3.10.tgz#d8825d55a50a04e33080c9188e6a5b03235d19f2" - integrity sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg== - dependencies: - uid "2.0.2" - iterare "1.2.1" - tslib "2.6.3" - "@nestjs/common@^10.3.7": version "10.3.7" resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-10.3.7.tgz#38ab5ff92277cf1f26f4749c264524e76962cfff" @@ -5991,16 +5982,13 @@ iterare "1.2.1" tslib "2.6.2" -"@nestjs/core@^10.3.10": +"@nestjs/common@^8.0.0 || ^9.0.0 || ^10.0.0": version "10.3.10" - resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-10.3.10.tgz#508090c3ca36488a8e24a9e5939c2f37426e48f4" - integrity sha512-ZbQ4jovQyzHtCGCrzK5NdtW1SYO2fHSsgSY1+/9WdruYCUra+JDkWEXgZ4M3Hv480Dl3OXehAmY1wCOojeMyMQ== + resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-10.3.10.tgz#d8825d55a50a04e33080c9188e6a5b03235d19f2" + integrity sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg== dependencies: uid "2.0.2" - "@nuxtjs/opencollective" "0.3.2" - fast-safe-stringify "2.1.1" iterare "1.2.1" - path-to-regexp "3.2.0" tslib "2.6.3" "@nestjs/core@^10.3.3": @@ -6015,6 +6003,18 @@ path-to-regexp "3.2.0" tslib "2.6.2" +"@nestjs/core@^8.0.0 || ^9.0.0 || ^10.0.0": + version "10.3.10" + resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-10.3.10.tgz#508090c3ca36488a8e24a9e5939c2f37426e48f4" + integrity sha512-ZbQ4jovQyzHtCGCrzK5NdtW1SYO2fHSsgSY1+/9WdruYCUra+JDkWEXgZ4M3Hv480Dl3OXehAmY1wCOojeMyMQ== + dependencies: + uid "2.0.2" + "@nuxtjs/opencollective" "0.3.2" + fast-safe-stringify "2.1.1" + iterare "1.2.1" + path-to-regexp "3.2.0" + tslib "2.6.3" + "@nestjs/platform-express@^10.3.3": version "10.3.3" resolved "https://registry.yarnpkg.com/@nestjs/platform-express/-/platform-express-10.3.3.tgz#c1484d30d1e7666c4c8d0d7cde31cfc0b9d166d7" @@ -31918,7 +31918,7 @@ tslib@2.6.2, tslib@^2.6.2: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tslib@2.6.3: +tslib@2.6.3, tslib@^2.2.0: version "2.6.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== @@ -31933,11 +31933,6 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.2.tgz#1b6f07185c881557b0ffa84b111a0106989e8338" integrity sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA== -tslib@^2.2.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" - integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" From 74ee38981e7404727a3605ffb87943a986cdee89 Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Wed, 24 Jul 2024 11:30:26 +0200 Subject: [PATCH 3/3] fix type error --- packages/nuxt/src/common/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/common/types.ts b/packages/nuxt/src/common/types.ts index 9ec6b51daa66..0187e83170a7 100644 --- a/packages/nuxt/src/common/types.ts +++ b/packages/nuxt/src/common/types.ts @@ -96,5 +96,5 @@ export type SentryNuxtModuleOptions = SourceMapsOptions & { * Enable debug functionality of the SDK during build-time. * Enabling this will give you, for example, logs about source maps. */ - debug: boolean; + debug?: boolean; };