From bb20466a7b0ce7c555fad6a9ac28186838eff2c0 Mon Sep 17 00:00:00 2001 From: Ziyad Date: Thu, 11 Jul 2024 01:48:29 +0300 Subject: [PATCH] fix(nextjs): Support automatic instrumentation for app directory with page extensions (#12858) --- .../src/config/loaders/wrappingLoader.ts | 2 +- packages/nextjs/src/config/webpack.ts | 19 +++++++------- packages/nextjs/test/config/loaders.test.ts | 25 +++++++++++++++++++ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/packages/nextjs/src/config/loaders/wrappingLoader.ts b/packages/nextjs/src/config/loaders/wrappingLoader.ts index a0d953d8315b..955268fb304b 100644 --- a/packages/nextjs/src/config/loaders/wrappingLoader.ts +++ b/packages/nextjs/src/config/loaders/wrappingLoader.ts @@ -182,7 +182,7 @@ export default function wrappingLoader( const componentTypeMatch = path.posix .normalize(path.relative(appDir, this.resourcePath)) - .match(/\/?([^/]+)\.(?:js|ts|jsx|tsx)$/); + .match(/\/?([^/.]+)(?:\..*)?\.(?:js|ts|jsx|tsx)$/); if (componentTypeMatch && componentTypeMatch[1]) { let componentType: ServerComponentContext['componentType']; diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 4002db18f295..2e1a180e6319 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -147,12 +147,12 @@ export function constructWebpackConfigFunction( ); }; - const possibleMiddlewareLocations = ['js', 'jsx', 'ts', 'tsx'].map(middlewareFileEnding => { - return path.join(middlewareLocationFolder, `middleware.${middlewareFileEnding}`); - }); const isMiddlewareResource = (resourcePath: string): boolean => { const normalizedAbsoluteResourcePath = normalizeLoaderResourcePath(resourcePath); - return possibleMiddlewareLocations.includes(normalizedAbsoluteResourcePath); + return ( + normalizedAbsoluteResourcePath.startsWith(middlewareLocationFolder) && + !!normalizedAbsoluteResourcePath.match(/[\\/]middleware(\..*)?\.(js|jsx|ts|tsx)$/) + ); }; const isServerComponentResource = (resourcePath: string): boolean => { @@ -163,7 +163,7 @@ export function constructWebpackConfigFunction( return ( appDirPath !== undefined && normalizedAbsoluteResourcePath.startsWith(appDirPath + path.sep) && - !!normalizedAbsoluteResourcePath.match(/[\\/](page|layout|loading|head|not-found)\.(js|jsx|tsx)$/) + !!normalizedAbsoluteResourcePath.match(/[\\/](page|layout|loading|head|not-found)(?:\..*)?\.(?:js|jsx|tsx)$/) ); }; @@ -172,7 +172,7 @@ export function constructWebpackConfigFunction( return ( appDirPath !== undefined && normalizedAbsoluteResourcePath.startsWith(appDirPath + path.sep) && - !!normalizedAbsoluteResourcePath.match(/[\\/]route\.(js|jsx|ts|tsx)$/) + !!normalizedAbsoluteResourcePath.match(/[\\/]route(?:\..*)?\.(?:js|jsx|ts|tsx)$/) ); }; @@ -285,10 +285,9 @@ export function constructWebpackConfigFunction( } if (appDirPath) { - const hasGlobalErrorFile = ['global-error.js', 'global-error.jsx', 'global-error.ts', 'global-error.tsx'].some( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - globalErrorFile => fs.existsSync(path.join(appDirPath!, globalErrorFile)), - ); + const hasGlobalErrorFile = fs + .readdirSync(appDirPath) + .some(file => file.match(/^global-error(?:\..*)?\.(?:js|ts|jsx|tsx)$/)); if ( !hasGlobalErrorFile && diff --git a/packages/nextjs/test/config/loaders.test.ts b/packages/nextjs/test/config/loaders.test.ts index c2aaf0c9a707..6ccc701949f1 100644 --- a/packages/nextjs/test/config/loaders.test.ts +++ b/packages/nextjs/test/config/loaders.test.ts @@ -14,6 +14,7 @@ import { import { materializeFinalWebpackConfig } from './testUtils'; const existsSyncSpy = jest.spyOn(fs, 'existsSync'); +jest.spyOn(fs, 'readdirSync').mockReturnValue([]); const lstatSyncSpy = jest.spyOn(fs, 'lstatSync'); type MatcherResult = { pass: boolean; message: () => string }; @@ -96,6 +97,10 @@ describe('webpack loaders', () => { resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/pages/testPage.tsx', expectedWrappingTargetKind: 'page', }, + { + resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/pages/testPage.custom.tsx', + expectedWrappingTargetKind: 'page', + }, { resourcePath: './src/pages/testPage.tsx', expectedWrappingTargetKind: 'page', @@ -133,6 +138,10 @@ describe('webpack loaders', () => { resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/middleware.js', expectedWrappingTargetKind: 'middleware', }, + { + resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/middleware.custom.js', + expectedWrappingTargetKind: 'middleware', + }, { resourcePath: './src/middleware.js', expectedWrappingTargetKind: 'middleware', @@ -162,10 +171,26 @@ describe('webpack loaders', () => { resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/pages/api/nested/testApiRoute.js', expectedWrappingTargetKind: 'api-route', }, + { + resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/pages/api/nested/testApiRoute.custom.js', + expectedWrappingTargetKind: 'api-route', + }, + { + resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/app/nested/route.ts', + expectedWrappingTargetKind: 'route-handler', + }, + { + resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/app/nested/route.custom.ts', + expectedWrappingTargetKind: 'route-handler', + }, { resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/app/page.js', expectedWrappingTargetKind: 'server-component', }, + { + resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/app/page.custom.js', + expectedWrappingTargetKind: 'server-component', + }, { resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/app/nested/page.js', expectedWrappingTargetKind: 'server-component',