Skip to content

Commit

Permalink
feat(nextjs): Future-proof Next.js config options overriding (#13586)
Browse files Browse the repository at this point in the history
The logic in this PR is slightly intense but all it does is check for
the Next.js version and if we are on a version that included [this
change](vercel/next.js#68853) which stabilized
`instrumentation.ts` we no longer inject the
`experimental.instrumentationHook` option in `next.config.js`.

This is necessary because otherwise Next.js prints scary warnings and
users may be confused why.
  • Loading branch information
lforst authored Sep 4, 2024
1 parent 63863cd commit c4f68d8
Showing 1 changed file with 70 additions and 13 deletions.
83 changes: 70 additions & 13 deletions packages/nextjs/src/config/withSentryConfig.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable complexity */
import { isThenable, parseSemver } from '@sentry/utils';

import * as fs from 'fs';
Expand Down Expand Up @@ -47,6 +48,7 @@ function getFinalConfigObject(
incomingUserNextConfigObject: NextConfigObject,
userSentryOptions: SentryBuildOptions,
): NextConfigObject {
// TODO(v9): Remove this check for the Sentry property
if ('sentry' in incomingUserNextConfigObject) {
// eslint-disable-next-line no-console
console.warn(
Expand All @@ -71,21 +73,10 @@ function getFinalConfigObject(
}
}

// We need to enable `instrumentation.ts` for users because we tell them to put their `Sentry.init()` calls inside of it.
if (incomingUserNextConfigObject.experimental?.instrumentationHook === false) {
// eslint-disable-next-line no-console
console.warn(
'[@sentry/nextjs] You turned off the `instrumentationHook` option. Note that Sentry will not be initialized if you did not set it up inside `instrumentation.ts`.',
);
}
incomingUserNextConfigObject.experimental = {
instrumentationHook: true,
...incomingUserNextConfigObject.experimental,
};
const nextJsVersion = getNextjsVersion();

// Add the `clientTraceMetadata` experimental option based on Next.js version. The option got introduced in Next.js version 15.0.0 (actually 14.3.0-canary.64).
// Adding the option on lower versions will cause Next.js to print nasty warnings we wouldn't confront our users with.
const nextJsVersion = getNextjsVersion();
if (nextJsVersion) {
const { major, minor } = parseSemver(nextJsVersion);
if (major !== undefined && minor !== undefined && (major >= 15 || (major === 14 && minor >= 3))) {
Expand All @@ -99,10 +90,76 @@ function getFinalConfigObject(
} else {
// eslint-disable-next-line no-console
console.log(
"[@sentry/nextjs] The Sentry SDK was not able to determine your Next.js version. If you are using Next.js 15 or greater, please add `experimental.clientTraceMetadata: ['sentry-trace', 'baggage']` to your Next.js config to enable pageload tracing for App Router.",
"[@sentry/nextjs] The Sentry SDK was not able to determine your Next.js version. If you are using Next.js version 15 or greater, please add `experimental.clientTraceMetadata: ['sentry-trace', 'baggage']` to your Next.js config to enable pageload tracing for App Router.",
);
}

// From Next.js version (15.0.0-canary.124) onwards, Next.js does no longer require the `experimental.instrumentationHook` option and will
// print a warning when it is set, so we need to conditionally provide it for lower versions.
if (nextJsVersion) {
const { major, minor, patch, prerelease } = parseSemver(nextJsVersion);
const isFullySupportedRelease =
major !== undefined &&
minor !== undefined &&
patch !== undefined &&
major >= 15 &&
((minor === 0 && patch === 0 && prerelease === undefined) || minor > 0 || patch > 0);
const isSupportedV15Rc =
major !== undefined &&
minor !== undefined &&
patch !== undefined &&
prerelease !== undefined &&
major === 15 &&
minor === 0 &&
patch === 0 &&
prerelease.startsWith('rc.') &&
parseInt(prerelease.split('.')[1] || '', 10) > 0;
const isSupportedCanary =
minor !== undefined &&
patch !== undefined &&
prerelease !== undefined &&
major === 15 &&
minor === 0 &&
patch === 0 &&
prerelease.startsWith('canary.') &&
parseInt(prerelease.split('.')[1] || '', 10) >= 124;

if (!isFullySupportedRelease && !isSupportedV15Rc && !isSupportedCanary) {
if (incomingUserNextConfigObject.experimental?.instrumentationHook === false) {
// eslint-disable-next-line no-console
console.warn(
'[@sentry/nextjs] You turned off the `experimental.instrumentationHook` option. Note that Sentry will not be initialized if you did not set it up inside `instrumentation.(js|ts)`.',
);
}
incomingUserNextConfigObject.experimental = {
instrumentationHook: true,
...incomingUserNextConfigObject.experimental,
};
}
} else {
// If we cannot detect a Next.js version for whatever reason, the sensible default is to set the `experimental.instrumentationHook`, even though it may create a warning.
if (
incomingUserNextConfigObject.experimental &&
'instrumentationHook' in incomingUserNextConfigObject.experimental
) {
if (incomingUserNextConfigObject.experimental.instrumentationHook === false) {
// eslint-disable-next-line no-console
console.warn(
'[@sentry/nextjs] You set `experimental.instrumentationHook` to `false`. If you are using Next.js version 15 or greater, you can remove that option. If you are using Next.js version 14 or lower, you need to set `experimental.instrumentationHook` in your `next.config.(js|mjs)` to `true` for the SDK to be properly initialized in combination with `instrumentation.(js|ts)`.',
);
}
} else {
// eslint-disable-next-line no-console
console.log(
"[@sentry/nextjs] The Sentry SDK was not able to determine your Next.js version. If you are using Next.js version 15 or greater, Next.js will probably show you a warning about the `experimental.instrumentationHook` being set. To silence Next.js' warning, explicitly set the `experimental.instrumentationHook` option in your `next.config.(js|mjs|ts)` to `undefined`. If you are on Next.js version 14 or lower, you can silence this particular warning by explicitly setting the `experimental.instrumentationHook` option in your `next.config.(js|mjs)` to `true`.",
);
incomingUserNextConfigObject.experimental = {
instrumentationHook: true,
...incomingUserNextConfigObject.experimental,
};
}
}

if (process.env.TURBOPACK && !process.env.SENTRY_SUPPRESS_TURBOPACK_WARNING) {
// eslint-disable-next-line no-console
console.warn(
Expand Down

0 comments on commit c4f68d8

Please sign in to comment.