Skip to content

@sentry/nextjs bundles the whole Pages Router runtime (next/router, ~87 KB raw / 36 KB gzip) into every App Router app #24032

Description

@AlbertoMihai98

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nextjs

SDK Version

10.72.0 (measured); the import chain is unchanged in 10.73.0 and on develop

Framework Version

Next 16.3.3, App Router only (no pages/ directory), Turbopack

Link to Sentry event

No response

Reproduction Example/SDK Setup

// instrumentation-client.ts
import * as Sentry from '@sentry/nextjs';

Sentry.init({ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN });

export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;

Nothing else is needed: any App Router app that calls init() reproduces it. The app has no pages/ directory and no import of next/router anywhere.

Steps to Reproduce

  1. npx create-next-app@latest (App Router), add @sentry/nextjs and the instrumentation-client.ts above.
  2. next build --experimental-analyze (or any other bundle analysis).
  3. Open the chunk that contains the SDK client (the one with the [@sentry/nextjs] init warnings).

Expected Result

An App Router app downloads no Pages Router code. The SDK already decides at runtime which router it is on (routing/nextRoutingInstrumentation.ts: !WINDOW.document.getElementById('__NEXT_DATA__')), so the Pages Router branch is never taken on App Router.

Actual Result

The SDK client chunk carries the whole Pages Router client runtime: next/dist/shared/lib/router/router.js, next/dist/compiled/path-to-regexp, next/dist/client/route-loader.js, next/dist/client/script.js, sorted-routes.js, route-regex.js, prepare-destination.js, ... 52 modules from next, 87.2 KB raw / 35.6 KB gzip in our app (Turbopack analyzer, Next 16.3.3).

Sentry client chunk (App Router, __SENTRY_TRACING__ compiled to false) raw of which next (Pages Router runtime)
@sentry/nextjs 10.72.0 as published 168.4 KB 87.2 KB (52 modules)
with next/router imported on demand (see below) 82 KB 0 - the runtime lands in an async chunk that an App Router app never requests

It is there with tracing enabled and after compiling tracing out: the import is static, so no bundler can drop it.

Root cause - packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts:

import RouterImport from 'next/router';

const Router: typeof RouterImport = RouterImport.events
  ? RouterImport
  : (RouterImport as unknown as { default: typeof RouterImport }).default;

reached statically through client/index.ts -> browserTracingIntegration.ts -> routing/nextRoutingInstrumentation.ts -> routing/pagesRouterRoutingInstrumentation.ts. Router is used in exactly one place, pagesRouterInstrumentNavigation (Router.events.on('routeChangeStart', ...)); the pageload half only reads __NEXT_DATA__ and __BUILD_MANIFEST. next declares no sideEffects, and the app/pages decision is made at runtime, so the module and everything next/router pulls in stay in every client bundle.

Why the SDK's own size gate cannot see it: .size-limit.js measures @sentry/nextjs (client) with ignore: ['next/router', 'next/constants'].

Additional Context

What I measured before proposing a fix (same app, same analyzer, patching the installed build):

  • Moving the module-scope interop (RouterImport.events ? ...) into a function changes nothing: the cost is the static import at module-graph level, not the getter access.
  • Replacing the static import with import('next/router') inside pagesRouterInstrumentNavigation moves the Pages Router runtime into an async chunk: Sentry chunk 168.4 -> 82 KB raw on our App Router app. On a Pages Router app the routeChangeStart listener is registered once that import settles; the router module is already part of the framework runtime there. A minimal Pages Router app built with both Turbopack and webpack, pageload and mount-time router.replace() navigation spans included, is in the PR that follows.
  • window.next.router.events (no next/router at all) was considered and rejected: Next marks instance.events as "never documented ... remove the following major version".

Priority

React with 👍 to help prioritize this issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions