Skip to content

Commit

Permalink
fix(nextjs): Exclude SDK from Edge runtime bundles (#6683)
Browse files Browse the repository at this point in the history
  • Loading branch information
lforst authored Jan 9, 2023
1 parent 1b4d9da commit 7316b85
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 45 deletions.
7 changes: 7 additions & 0 deletions packages/nextjs/src/config/loaders/proxyLoader.ts
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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',
)
) {
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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

0 comments on commit 7316b85

Please sign in to comment.