diff --git a/packages/nuxt/src/runtime/plugins/sentry.client.ts b/packages/nuxt/src/runtime/plugins/sentry.client.ts index 6d03b3cd9625..c27f6de11e05 100644 --- a/packages/nuxt/src/runtime/plugins/sentry.client.ts +++ b/packages/nuxt/src/runtime/plugins/sentry.client.ts @@ -1,5 +1,5 @@ -import { getClient, GLOBAL_OBJ } from '@sentry/core'; -import { browserTracingIntegration, vueIntegration } from '@sentry/vue'; +import { getClient, GLOBAL_OBJ, setRouteProvider } from '@sentry/core'; +import { browserTracingIntegration, createVueRouteProvider, vueIntegration } from '@sentry/vue'; import { defineNuxtPlugin, isNuxtError } from 'nuxt/app'; import type { GlobalObjWithIntegrationOptions } from '../../client/vueIntegration'; import { reportNuxtError } from '../utils'; @@ -35,6 +35,18 @@ export default defineNuxtPlugin({ name: 'sentry-client-integrations', dependsOn: ['sentry-client-config'], async setup(nuxtApp) { + // Registered outside the tracing guard, because route parameterization should not depend on + // tracing: anything that needs a route name (bfcache metrics, web vitals) can resolve one even + // when tracing is tree-shaken away. Nuxt installs the router before its plugins run, so unlike + // `@sentry/vue` this can read it straight off `nuxtApp`. + const client = getClient(); + if (client && '$router' in nuxtApp) { + setRouteProvider( + createVueRouteProvider(() => nuxtApp.$router), + client, + ); + } + // This evaluates to true unless __SENTRY_TRACING__ is text-replaced with "false", in which case everything inside // will get tree-shaken away if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) {