Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(nextjs): Exclude SDK from Edge runtime bundles #6683

Merged
merged 1 commit into from Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/nextjs/src/config/loaders/proxyLoader.ts
Expand Up @@ -9,6 +9,7 @@ type LoaderOptions = {
pagesDir: string;
pageExtensionRegex: string;
excludeServerRoutes: Array<RegExp | string>;
isEdgeRuntime: boolean;
};

/**
Expand All @@ -22,8 +23,14 @@ export default async function proxyLoader(this: LoaderThis<LoaderOptions>, userC
pagesDir,
pageExtensionRegex,
excludeServerRoutes = [],
isEdgeRuntime,
} = 'getOptions' in this ? this.getOptions() : this.query;

// We currently don't support the edge runtime
if (isEdgeRuntime) {
return userCode;
}

// Get the parameterized route name from this page's filepath
const parameterizedRoute = path
// Get the path of the file insde of the pages directory
Expand Down
18 changes: 2 additions & 16 deletions packages/nextjs/src/config/templates/apiProxyLoaderTemplate.ts
Expand Up @@ -23,7 +23,7 @@ type NextApiModule = (
}
// CJS export
| NextApiHandler
) & { config?: PageConfig & { runtime?: string } };
) & { config?: PageConfig };

const userApiModule = origModule as NextApiModule;

Expand Down Expand Up @@ -53,21 +53,7 @@ export const config = {
},
};

// This is a variable that Next.js will string replace during build with a string if run in an edge runtime from Next.js
// v12.2.1-canary.3 onwards:
// https://github.com/vercel/next.js/blob/166e5fb9b92f64c4b5d1f6560a05e2b9778c16fb/packages/next/build/webpack-config.ts#L206
// https://edge-runtime.vercel.sh/features/available-apis#addressing-the-runtime
declare const EdgeRuntime: string | undefined;

let exportedHandler;

if (typeof EdgeRuntime === 'string') {
exportedHandler = userProvidedHandler;
} else {
exportedHandler = userProvidedHandler ? Sentry.withSentryAPI(userProvidedHandler, '__ROUTE__') : undefined;
}

export default exportedHandler;
export default userProvidedHandler ? Sentry.withSentryAPI(userProvidedHandler, '__ROUTE__') : undefined;

// Re-export anything exported by the page module we're wrapping. When processing this code, Rollup is smart enough to
// not include anything whose name matchs something we've explicitly exported above.
Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs/src/config/types.ts
Expand Up @@ -137,7 +137,7 @@ export type BuildContext = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
defaultLoaders: any;
totalPages: number;
nextRuntime?: 'nodejs' | 'edge';
nextRuntime?: 'nodejs' | 'edge'; // Added in Next.js 12+
};

/**
Expand Down
32 changes: 30 additions & 2 deletions packages/nextjs/src/config/webpack.ts
Expand Up @@ -85,6 +85,13 @@ export function constructWebpackConfigFunction(
// Add a loader which will inject code that sets global values
addValueInjectionLoader(newConfig, userNextConfig, userSentryOptions);

if (buildContext.nextRuntime === 'edge') {
// eslint-disable-next-line no-console
console.warn(
'[@sentry/nextjs] You are using edge functions or middleware. Please note that Sentry does not yet support error monitoring for these features.',
);
}

if (isServer) {
if (userSentryOptions.autoInstrumentServerFunctions !== false) {
const pagesDir = newConfig.resolve?.alias?.['private-next-pages'] as string;
Expand All @@ -102,6 +109,7 @@ export function constructWebpackConfigFunction(
pagesDir,
pageExtensionRegex,
excludeServerRoutes: userSentryOptions.excludeServerRoutes,
isEdgeRuntime: buildContext.nextRuntime === 'edge',
},
},
],
Expand Down Expand Up @@ -305,7 +313,15 @@ async function addSentryToEntryProperty(

// inject into all entry points which might contain user's code
for (const entryPointName in newEntryProperty) {
if (shouldAddSentryToEntryPoint(entryPointName, isServer, userSentryOptions.excludeServerRoutes, isDev)) {
if (
shouldAddSentryToEntryPoint(
entryPointName,
isServer,
userSentryOptions.excludeServerRoutes,
isDev,
buildContext.nextRuntime === 'edge',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l: Only thing I'd like to see here is the equality check extracted into a helper func, but nbd.

)
) {
addFilesToExistingEntryPoint(newEntryProperty, entryPointName, filesToInject);
} else {
if (
Expand Down Expand Up @@ -432,7 +448,13 @@ function shouldAddSentryToEntryPoint(
isServer: boolean,
excludeServerRoutes: Array<string | RegExp> = [],
isDev: boolean,
isEdgeRuntime: boolean,
): boolean {
// We don't support the Edge runtime yet
if (isEdgeRuntime) {
return false;
}

// On the server side, by default we inject the `Sentry.init()` code into every page (with a few exceptions).
if (isServer) {
const entryPointRoute = entryPointName.replace(/^pages/, '');
Expand Down Expand Up @@ -529,7 +551,13 @@ export function getWebpackPluginOptions(
stripPrefix: ['webpack://_N_E/'],
urlPrefix,
entries: (entryPointName: string) =>
shouldAddSentryToEntryPoint(entryPointName, isServer, userSentryOptions.excludeServerRoutes, isDev),
shouldAddSentryToEntryPoint(
entryPointName,
isServer,
userSentryOptions.excludeServerRoutes,
isDev,
buildContext.nextRuntime === 'edge',
),
release: getSentryRelease(buildId),
dryRun: isDev,
});
Expand Down
15 changes: 0 additions & 15 deletions packages/nextjs/src/index.client.ts
Expand Up @@ -2,7 +2,6 @@ import { RewriteFrames } from '@sentry/integrations';
import { configureScope, init as reactInit, Integrations } from '@sentry/react';
import { BrowserTracing, defaultRequestInstrumentationOptions, hasTracingEnabled } from '@sentry/tracing';
import { EventProcessor } from '@sentry/types';
import { logger } from '@sentry/utils';

import { nextRouterInstrumentation } from './performance/client';
import { buildMetadata } from './utils/metadata';
Expand Down Expand Up @@ -31,26 +30,12 @@ export { BrowserTracing };
// Treeshakable guard to remove all code related to tracing
declare const __SENTRY_TRACING__: boolean;

// This is a variable that Next.js will string replace during build with a string if run in an edge runtime from Next.js
// v12.2.1-canary.3 onwards:
// https://github.com/vercel/next.js/blob/166e5fb9b92f64c4b5d1f6560a05e2b9778c16fb/packages/next/build/webpack-config.ts#L206
// https://edge-runtime.vercel.sh/features/available-apis#addressing-the-runtime
declare const EdgeRuntime: string | undefined;

const globalWithInjectedValues = global as typeof global & {
__rewriteFramesAssetPrefixPath__: string;
};

/** Inits the Sentry NextJS SDK on the browser with the React SDK. */
export function init(options: NextjsOptions): void {
if (typeof EdgeRuntime === 'string') {
// If the SDK is imported when using the Vercel Edge Runtime, it will import the browser SDK, even though it is
// running the server part of a Next.js application. We can use the `EdgeRuntime` to check for that case and make
// the init call a no-op. This will prevent the SDK from crashing on the Edge Runtime.
__DEBUG_BUILD__ && logger.log('Vercel Edge Runtime detected. Will not initialize SDK.');
return;
}

applyTunnelRouteOption(options);
buildMetadata(options, ['nextjs', 'react']);
options.environment = options.environment || process.env.NODE_ENV;
Expand Down
11 changes: 0 additions & 11 deletions packages/nextjs/src/index.server.ts
Expand Up @@ -30,12 +30,6 @@ const globalWithInjectedValues = global as typeof global & {

const domain = domainModule as typeof domainModule & { active: (domainModule.Domain & Carrier) | null };

// This is a variable that Next.js will string replace during build with a string if run in an edge runtime from Next.js
// v12.2.1-canary.3 onwards:
// https://github.com/vercel/next.js/blob/166e5fb9b92f64c4b5d1f6560a05e2b9778c16fb/packages/next/build/webpack-config.ts#L206
// https://edge-runtime.vercel.sh/features/available-apis#addressing-the-runtime
declare const EdgeRuntime: string | undefined;

// Exporting this constant means we can compute it without the linter complaining, even if we stop directly using it in
// this file. It's important that it be computed as early as possible, because one of its indicators is seeing 'build'
// (as in the CLI command `next build`) in `process.argv`. Later on in the build process, everything's been spun out
Expand All @@ -51,11 +45,6 @@ export function init(options: NextjsOptions): void {
logger.enable();
}

if (typeof EdgeRuntime === 'string') {
__DEBUG_BUILD__ && logger.log('Vercel Edge Runtime detected. Will not initialize SDK.');
return;
}

__DEBUG_BUILD__ && logger.log('Initializing SDK...');

if (sdkAlreadyInitialized()) {
Expand Down