Skip to content

Commit 38aba99

Browse files
author
Luca Forstner
committed
ref(nextjs): Apply uncaught exception fix (#6138) only when middleware is configured
1 parent 8073954 commit 38aba99

File tree

4 files changed

+27
-10
lines changed

4 files changed

+27
-10
lines changed

packages/nextjs/src/config/loaders/prefixLoader.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,24 @@ import { LoaderThis } from './types';
55

66
type LoaderOptions = {
77
distDir: string;
8+
hasMiddleware: boolean;
89
};
910

1011
/**
1112
* Inject templated code into the beginning of a module.
1213
*/
1314
export default function prefixLoader(this: LoaderThis<LoaderOptions>, userCode: string): string {
1415
// We know one or the other will be defined, depending on the version of webpack being used
15-
const { distDir } = 'getOptions' in this ? this.getOptions() : this.query;
16+
const { distDir, hasMiddleware } = 'getOptions' in this ? this.getOptions() : this.query;
1617

1718
const templatePath = path.resolve(__dirname, '../templates/prefixLoaderTemplate.js');
1819
// make sure the template is included when runing `webpack watch`
1920
this.addDependency(templatePath);
2021

21-
// Fill in the placeholder
22+
// Fill in placehoolders
2223
let templateCode = fs.readFileSync(templatePath).toString();
2324
templateCode = templateCode.replace('__DIST_DIR__', distDir.replace(/\\/g, '\\\\'));
25+
templateCode = templateCode.replace('__HAS_MIDDLEWARE__', hasMiddleware ? 'true' : 'false');
2426

2527
return `${templateCode}\n${userCode}`;
2628
}

packages/nextjs/src/config/templates/prefixLoaderTemplate.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
declare const __HAS_MIDDLEWARE__: boolean;
2+
13
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
24
(global as any).__rewriteFramesDistDir__ = '__DIST_DIR__';
5+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
6+
(global as any).__hasMiddleware__ = __HAS_MIDDLEWARE__;
37

48
// We need this to make this file an ESM module, which TS requires when using `isolatedModules`, but it doesn't affect
59
// the end result - Rollup recognizes that it's a no-op and doesn't include it when building our code.

packages/nextjs/src/config/webpack.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ export function constructWebpackConfigFunction(
5858
}
5959

6060
if (isServer) {
61+
const pagesDir = newConfig.resolve?.alias?.['private-next-pages'] as string;
62+
63+
const middlewareJsPath = path.join(pagesDir, '..', 'middleware.js');
64+
const middlewareTsPath = path.join(pagesDir, '..', 'middleware.ts');
65+
66+
const hasMiddleware = fs.existsSync(middlewareJsPath) || fs.existsSync(middlewareTsPath);
67+
6168
newConfig.module = {
6269
...newConfig.module,
6370
rules: [
@@ -72,6 +79,7 @@ export function constructWebpackConfigFunction(
7279
loader: path.resolve(__dirname, 'loaders/prefixLoader.js'),
7380
options: {
7481
distDir: userNextConfig.distDir || '.next',
82+
hasMiddleware,
7583
},
7684
},
7785
],
@@ -80,8 +88,6 @@ export function constructWebpackConfigFunction(
8088
};
8189

8290
if (userSentryOptions.autoInstrumentServerFunctions !== false) {
83-
const pagesDir = newConfig.resolve?.alias?.['private-next-pages'] as string;
84-
8591
// Default page extensions per https://github.com/vercel/next.js/blob/f1dbc9260d48c7995f6c52f8fbcc65f08e627992/packages/next/server/config-shared.ts#L161
8692
const pageExtensions = userNextConfig.pageExtensions || ['tsx', 'ts', 'jsx', 'js'];
8793
const pageExtensionRegex = pageExtensions.map(escapeStringForRegex).join('|');

packages/nextjs/src/index.server.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ export { captureUnderscoreErrorException } from './utils/_error';
1919
// because or SSR of next.js we can only use this.
2020
export { ErrorBoundary, showReportDialog, withErrorBoundary } from '@sentry/react';
2121

22-
type GlobalWithDistDir = typeof global & { __rewriteFramesDistDir__: string };
22+
type GlobalWithBuildTimeConfiguration = typeof global & {
23+
__rewriteFramesDistDir__: string;
24+
__hasMiddleware__: boolean;
25+
};
2326
const domain = domainModule as typeof domainModule & { active: (domainModule.Domain & Carrier) | null };
2427

2528
// Exporting this constant means we can compute it without the linter complaining, even if we stop directly using it in
@@ -104,7 +107,7 @@ function addServerIntegrations(options: NextjsOptions): void {
104107

105108
// This value is injected at build time, based on the output directory specified in the build config. Though a default
106109
// is set there, we set it here as well, just in case something has gone wrong with the injection.
107-
const distDirName = (global as GlobalWithDistDir).__rewriteFramesDistDir__ || '.next';
110+
const distDirName = (global as GlobalWithBuildTimeConfiguration).__rewriteFramesDistDir__ || '.next';
108111
// nextjs always puts the build directory at the project root level, which is also where you run `next start` from, so
109112
// we can read in the project directory from the currently running process
110113
const distDirAbsPath = path.resolve(process.cwd(), distDirName);
@@ -118,10 +121,12 @@ function addServerIntegrations(options: NextjsOptions): void {
118121
});
119122
integrations = addOrUpdateIntegration(defaultRewriteFramesIntegration, integrations);
120123

121-
const nativeBehaviourOnUncaughtException = new Integrations.OnUncaughtException();
122-
integrations = addOrUpdateIntegration(nativeBehaviourOnUncaughtException, integrations, {
123-
_options: { exitEvenIfOtherHandlersAreRegistered: false },
124-
});
124+
if ((global as GlobalWithBuildTimeConfiguration).__hasMiddleware__) {
125+
const nativeBehaviourOnUncaughtException = new Integrations.OnUncaughtException();
126+
integrations = addOrUpdateIntegration(nativeBehaviourOnUncaughtException, integrations, {
127+
_options: { exitEvenIfOtherHandlersAreRegistered: false },
128+
});
129+
}
125130

126131
if (hasTracingEnabled(options)) {
127132
const defaultHttpTracingIntegration = new Integrations.Http({ tracing: true });

0 commit comments

Comments
 (0)