sentry-javascript icon indicating copy to clipboard operation
sentry-javascript copied to clipboard

`@apm-js-collab` is included in the `@sentry/nextjs` bundle when Pino integration is not enabled

Open jordanthornquest opened this issue 2 months ago • 11 comments

Is there an existing issue for this?

  • [x] I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
  • [x] I have reviewed the documentation https://docs.sentry.io/
  • [x] I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nextjs

SDK Version

10.25.0

Framework Version

Next 15.5.6 & React 19.2.0

Link to Sentry event

No response

Reproduction Example/SDK Setup

next.config.ts:

const nextConfig: NextConfig = {
  webpack(config, { webpack }) {
    // Configuration for Sentry tree-shaking
    config.plugins.push(
      new webpack.DefinePlugin({
        __SENTRY_DEBUG__: false,
        __SENTRY_TRACING__: false,
        __RRWEB_EXCLUDE_IFRAME__: true,
        __RRWEB_EXCLUDE_SHADOW_DOM__: true,
        __SENTRY_EXCLUDE_REPLAY_WORKER__: true,
      }),
    );

    return config;
  },
}

const bundledNextConfig = bundleAnalyzer(nextConfig);

export default withSentryConfig(bundledNextConfig, {
  disableLogger: true,
  project: process.env.NEXT_PUBLIC_SENTRY_PROJECT,
  silent: !process.env.CI,
});

sentry.edge.config.ts

import * as Sentry from "@sentry/nextjs";

Sentry.init({
  debug: false,
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  sendDefaultPii: true,
  tracesSampleRate: 1.0,
});

sentry.server.config.ts

import * as Sentry from "@sentry/nextjs";

Sentry.init({
  debug: false,
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  sendDefaultPii: true,
  tracesSampleRate: 1.0,
});

src/instrumentation.ts

import * as Sentry from "@sentry/nextjs";

export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    await import("../sentry.server.config");
  }

  if (process.env.NEXT_RUNTIME === "edge") {
    await import("../sentry.edge.config");
  }
}

export const onRequestError = Sentry.captureRequestError;

src/app/global-error.tsx

"use client";

import * as Sentry from "@sentry/nextjs";
import NextError from "next/error";
import { useEffect } from "react";

export default function GlobalError({
  error,
}: {
  error: Error & { digest?: string };
}) {
  useEffect(() => {
    Sentry.captureException(error);
  }, [error]);

  return (
    <html lang="en">
      <body>
        {/* `NextError` is the default Next.js error page component. Its type
        definition requires a `statusCode` prop. However, since the App Router
        does not expose status codes for errors, we simply pass 0 to render a
        generic error message. */}
        <NextError statusCode={0} />
      </body>
    </html>
  );
}

src/app/layout.tsx

import * as Sentry from "@sentry/nextjs";

export function generateMetadata(): Metadata {
  return {
    other: {
      ...Sentry.getTraceData(),
    },
  };
}

// Layout function...

Steps to Reproduce

  1. Create a Next project using @sentry/nextjs 10.12.0
  2. Run ANALYZE=true npm run build
  3. Update @sentry/nextjs to 10.25.0
  4. Run ANALYZE=true npm run build

Expected Result

Bundle size should match or be similar to bundle size prior to updating.

Actual Result

Bundle size has increased, and includes @apm-js-collab, despite the Pino integration not being used.

Image Image

Additional Context

Tip: React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it.

jordanthornquest avatar Nov 13 '25 16:11 jordanthornquest

JS-1160

linear[bot] avatar Nov 13 '25 16:11 linear[bot]

I reproduced the issue, I will investigate and try to come up with a fix.

logaretm avatar Nov 14 '25 14:11 logaretm

You can add this to your next.config.js for now as a workaround as long as you are not using pino:

const nextConfig: NextConfig = {
  webpack(config, { webpack, isServer }) {
    // ...
    if (isServer) {
      config.externals = config.externals || [];
      config.externals.push({
        '@apm-js-collab/tracing-hooks': '@apm-js-collab/tracing-hooks'
      });
    }
    return config;
  },
}

We could probably check if we could add it for the user, I will run a few tests.

logaretm avatar Nov 14 '25 22:11 logaretm

This worked! Looks like there's still an additional bundle size growth from Sentry between the two versions, but it's much smaller than before.

10.12.0:

Image Image Image

10.25.0:

Image Image Image

jordanthornquest avatar Nov 15 '25 00:11 jordanthornquest

I checked to see if we could add it to externals ourselves but that breaks the Pino integration, I can't get it to be tree-shaken either. I will check with the team and see what we can do.

For now, if the workaround is working for you then continue to use it.

logaretm avatar Nov 17 '25 08:11 logaretm

Seems like we can get pino to work as well by externalizing it with serverExternalPackages, I will see if we could include this by default in Next.js or if it is a fundamental issue to be resolved in node-core.

logaretm avatar Nov 18 '25 15:11 logaretm

You can add this to your next.config.js for now as a workaround as long as you are not using pino:

I'm facing the exact same situation.

I applied the externals workaround mentioned above to my next.config.js, and it successfully reduced the bundle size significantly (verified via bundle-analyzer) 👍

Configuration used:

const nextConfig: NextConfig = {  
  webpack(config, { webpack, isServer }) {  
    // ...  
    if (isServer) {  
      config.externals = config.externals || [];  
      config.externals.push({  
        '@apm-js-collab/tracing-hooks': '@apm-js-collab/tracing-hooks'  
      });  
    }  
    return config;  
  },  
}

The Problem: While this works perfectly in the local environment, it breaks the Sign-in functionality after deploying to Vercel. The runtime throws a MODULE_NOT_FOUND error, indicating that the externalized module is missing from the serverless function environment.

Error Log (Vercel):

Error: Cannot find module '@apm-js-collab/tracing-hooks' 
Require stack: 
- /var/task/.next/server/app/(auth)/sign-in/[[...sign-in]]/page.js
- /var/task/node_modules/.pnpm/[email protected]_.../node_modules/next/dist/compiled/next-server/server.runtime.prod.js
- /var/task/___next_launcher.cjs
- /opt/rust/nodejs.js
    at <unknown> (../../opt/rust/nodejs.js:2:13528) 
    at Function.zr (../../opt/rust/nodejs.js:2:13906) 
    at Ue.e.<computed>.Be._load (../../opt/rust/nodejs.js:2:13498) 
    at 81756 (.next/server/app/(auth)/sign-in/[[...sign-in]]/page.js:2:8619) { 
  code: 'MODULE_NOT_FOUND', 
  requireStack: [Array] 
} 

Environment:

  • Next.js: 15.5.6
  • React: 19.2.0
  • Platform: Vercel
  • @sentry/nextjs: 10.26.0
  • @clerk/nextjs: 6.35.2

It seems that by marking it as external, Vercel's output file tracing excludes it from the deployment build. Has anyone found a way to keep the bundle size small while ensuring this module is available on Vercel? 👀

stone-lyl avatar Nov 24 '25 06:11 stone-lyl

@stone-lyl Thanks for posting this, it seems to be rather a deep issue. Do you or one of your dependencies use pino? also what's your sentry configs are looking like?

indicating that the externalized module is missing from the serverless function environment

That's probably what happened, but externalizing should keep them out of the bundle for routes and server components, the tracing should still resolve it if it is in the node_modules. I'm curious to see if it is caused by pnpm since there seems to be issues related to it when it comes to externalizing.

Could you make a quick reproduction that shows this when deployed on Vercel?

I will discuss with the team the possibility of dropping this dependency entirely, given that it is only needed for Pino < 9.7

logaretm avatar Nov 24 '25 08:11 logaretm

Could you make a quick reproduction that shows this when deployed on Vercel?

Hi @logaretm , Thanks for getting back to me! Here's the reproduction you requested. (You just need to click "Sign in" and log in with your Google account. That way, you’ll be able to reproduce the issue.):

🔗 Repository: https://github.com/stone-lyl/reproduce-sentry-issue1819/tree/main
🚀 Vercel Deployment: https://reproduce-sentry-issue1819-git-main-stone-3724s-projects.vercel.app

About Pino Usage

No, neither my project nor any of my dependencies use Pino. This is a completely fresh Next.js 15 project with minimal dependencies. You can verify this by checking the package.json in the repo—the only major dependencies are:

  • @sentry/nextjs ~~(v10.25.0)~~ (10.26.0)
  • next ~~(v15.0.3)~~ (v15.5.6)
  • react / react-dom (v19.2.0)
  • @clerk/nextjs (v6.35.2 for authentication)

Sentry Configuration

sentry.client.config.ts:

import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  integrations: [
    Sentry.replayIntegration(),
  ],
  tracesSampleRate: 1,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  debug: false,
});

sentry.server.config.ts:

import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  tracesSampleRate: 1,
  debug: false,
});

instrumentation.ts:

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    await import('./sentry.server.config');
  }
  if (process.env.NEXT_RUNTIME === 'edge') {
    await import('./sentry.edge.config');
  }
}

About the pnpm Issue

You're absolutely right about pnpm potentially causing issues with externalization! I am indeed using pnpm as my package manager.

The Reproduction

The repo is deployed on Vercel and demonstrates the issue. The build succeeds, but @apm-js-collab/tracing-hooks gets bundled even though Pino isn't being used. You can inspect the Vercel deployment logs and serverless function bundles to see this behavior.

Thanks for considering dropping this dependency for Pino < 9.7! That would definitely help reduce bundle size for projects not using Pino. 🙏

stone-lyl avatar Nov 27 '25 14:11 stone-lyl

Many thanks, I will take a look and report back.

logaretm avatar Nov 27 '25 15:11 logaretm

@stone-lyl I took a look at your demo, thanks a lot for providing it! I did confirm my suspicion, when deploying the app with pnpm as the package manager, I get the error you described that results in 500s across the board.

I tried using yarn as a package manager and the deployment works as expected, so it must be an externalization issue with pnpm.

I believe this should be fixed in https://github.com/vercel/next.js/pull/86375, but still I will see about excluding it from the bundle with the rest of the team given that pino wouldn't work in that case which isn't what we want.

logaretm avatar Dec 01 '25 10:12 logaretm