`@apm-js-collab` is included in the `@sentry/nextjs` bundle when Pino integration is not enabled
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
- Create a Next project using
@sentry/nextjs10.12.0 - Run
ANALYZE=true npm run build - Update
@sentry/nextjsto10.25.0 - 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.
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.
I reproduced the issue, I will investigate and try to come up with a fix.
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.
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:
10.25.0:
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.
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.
You can add this to your
next.config.jsfor 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 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
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. 🙏
Many thanks, I will take a look and report back.
@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.