From 55cf7149d51f372a8536e35b0b35e99fa7697696 Mon Sep 17 00:00:00 2001 From: Hendrik Liebau Date: Wed, 15 Jan 2025 00:34:32 +0100 Subject: [PATCH] Skip client reference manifests for static metadata route handlers --- .../loaders/next-metadata-route-loader.ts | 2 +- .../plugins/flight-client-entry-plugin.ts | 17 +++++--- .../plugins/next-trace-entrypoints-plugin.ts | 40 ++++++++++++------ .../app/favicon.ico | Bin 0 -> 15086 bytes 4 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 test/e2e/app-dir/use-cache-metadata-route-handler/app/favicon.ico diff --git a/packages/next/src/build/webpack/loaders/next-metadata-route-loader.ts b/packages/next/src/build/webpack/loaders/next-metadata-route-loader.ts index b6dae3bbfabcf..be18e806548e9 100644 --- a/packages/next/src/build/webpack/loaders/next-metadata-route-loader.ts +++ b/packages/next/src/build/webpack/loaders/next-metadata-route-loader.ts @@ -41,7 +41,7 @@ const cacheHeader = { revalidate: 'public, max-age=0, must-revalidate', } -type MetadataRouteLoaderOptions = { +export type MetadataRouteLoaderOptions = { // Using separate argument to avoid json being parsed and hit error // x-ref: https://github.com/vercel/next.js/pull/62615 filePath: string diff --git a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts index 7268afdd1a3ec..005a609070bcc 100644 --- a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts +++ b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts @@ -45,6 +45,7 @@ import { getModuleBuildInfo } from '../loaders/get-module-build-info' import { getAssumedSourceType } from '../loaders/next-flight-loader' import { isAppRouteRoute } from '../../../lib/is-app-route-route' import { isMetadataRoute } from '../../../lib/metadata/is-metadata-route' +import type { MetadataRouteLoaderOptions } from '../loaders/next-metadata-route-loader' interface Options { dev: boolean @@ -305,7 +306,12 @@ export class FlightClientEntryPlugin { ).request if (entryRequest.endsWith(WEBPACK_RESOURCE_QUERIES.metadataRoute)) { - entryRequest = getMetadataRouteResource(entryRequest) + const { filePath, isDynamicRouteExtension } = + getMetadataRouteResource(entryRequest) + + if (isDynamicRouteExtension === '1') { + entryRequest = filePath + } } const { clientComponentImports, actionImports, cssImports } = @@ -1110,14 +1116,15 @@ function getModuleResource(mod: webpack.NormalModule): string { } if (mod.resource === `?${WEBPACK_RESOURCE_QUERIES.metadataRoute}`) { - return getMetadataRouteResource(mod.rawRequest) + return getMetadataRouteResource(mod.rawRequest).filePath } return modResource } -function getMetadataRouteResource(request: string): string { - const query = request.split('next-metadata-route-loader?')[1] +function getMetadataRouteResource(request: string): MetadataRouteLoaderOptions { + // e.g. next-metadata-route-loader?filePath=&isDynamicRouteExtension=1!?__next_metadata_route__ + const query = request.split('!')[0].split('next-metadata-route-loader?')[1] - return parse(query).filePath as string + return parse(query) as MetadataRouteLoaderOptions } diff --git a/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts b/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts index 38dba137b1dcc..e331683c92b8d 100644 --- a/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts +++ b/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts @@ -19,6 +19,7 @@ import picomatch from 'next/dist/compiled/picomatch' import { getModuleBuildInfo } from '../loaders/get-module-build-info' import { getPageFilePath } from '../../entries' import { resolveExternal } from '../../handle-externals' +import { isStaticMetadataRoute } from '../../../lib/metadata/is-metadata-route' const PLUGIN_NAME = 'TraceEntryPointsPlugin' export const TRACE_IGNORES = [ @@ -115,6 +116,7 @@ export interface BuildTraceContext { outputPath: string depModArray: string[] entryNameMap: Record + absolutePathByEntryName: Record } chunksTrace?: { action: TurbotraceAction @@ -241,19 +243,28 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance { nodePath.join(outputPath, `${outputPrefix}${entrypoint.name}.js`) ) - if (entrypoint.name.startsWith('app/')) { - // include the client reference manifest - const clientManifestsForEntrypoint = nodePath.join( - outputPath, - outputPrefix, - entrypoint.name.replace(/%5F/g, '_') + - '_' + - CLIENT_REFERENCE_MANIFEST + - '.js' - ) + if (entrypoint.name.startsWith('app/') && this.appDir) { + const appDirRelativeEntryPath = + this.buildTraceContext.entriesTrace?.absolutePathByEntryName[ + entrypoint.name + ]?.replace(this.appDir, '') - if (clientManifestsForEntrypoint !== null) { - entryFiles.add(clientManifestsForEntrypoint) + // Include the client reference manifest in the trace, but not for + // static metadata routes, for which we don't generate those. + if ( + appDirRelativeEntryPath && + !isStaticMetadataRoute(appDirRelativeEntryPath) + ) { + entryFiles.add( + nodePath.join( + outputPath, + outputPrefix, + entrypoint.name.replace(/%5F/g, '_') + + '_' + + CLIENT_REFERENCE_MANIFEST + + '.js' + ) + ) } } @@ -315,6 +326,7 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance { const entryNameMap = new Map() const entryModMap = new Map() const additionalEntries = new Map>() + const absolutePathByEntryName = new Map() const depModMap = new Map() @@ -356,6 +368,7 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance { ) { entryModMap.set(absolutePath, entryMod) entryNameMap.set(absolutePath, name) + absolutePathByEntryName.set(name, absolutePath) } } @@ -441,6 +454,9 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance { appDir: this.rootDir, depModArray: Array.from(depModMap.keys()), entryNameMap: Object.fromEntries(entryNameMap), + absolutePathByEntryName: Object.fromEntries( + absolutePathByEntryName + ), outputPath: compilation.outputOptions.path!, } diff --git a/test/e2e/app-dir/use-cache-metadata-route-handler/app/favicon.ico b/test/e2e/app-dir/use-cache-metadata-route-handler/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4965832f2c9b0605eaa189b7c7fb11124d24e48a GIT binary patch literal 15086 zcmeHOOH5Q(7(R0cc?bh2AT>N@1PWL!LLfZKyG5c!MTHoP7_p!sBz0k$?pjS;^lmgJ zU6^i~bWuZYHL)9$wuvEKm~qo~(5=Lvx5&Hv;?X#m}i|`yaGY4gX+&b>tew;gcnRQA1kp zBbm04SRuuE{Hn+&1wk%&g;?wja_Is#1gKoFlI7f`Gt}X*-nsMO30b_J@)EFNhzd1QM zdH&qFb9PVqQOx@clvc#KAu}^GrN`q5oP(8>m4UOcp`k&xwzkTio*p?kI4BPtIwX%B zJN69cGsm=x90<;Wmh-bs>43F}ro$}Of@8)4KHndLiR$nW?*{Rl72JPUqRr3ta6e#A z%DTEbi9N}+xPtd1juj8;(CJt3r9NOgb>KTuK|z7!JB_KsFW3(pBN4oh&M&}Nb$Ee2 z$-arA6a)CdsPj`M#1DS>fqj#KF%0q?w50GN4YbmMZIoF{e1yTR=4ablqXHBB2!`wM z1M1ke9+<);|AI;f=2^F1;G6Wfpql?1d5D4rMr?#f(=hkoH)U`6Gb)#xDLjoKjp)1;Js@2Iy5yk zMXUqj+gyk1i0yLjWS|3sM2-1ECc;MAz<4t0P53%7se$$+5Ex`L5TQO_MMXXi04UDIU+3*7Ez&X|mj9cFYBXqM{M;mw_ zpw>azP*qjMyNSD4hh)XZt$gqf8f?eRSFX8VQ4Y+H3jAtvyTrXr`qHAD6`m;aYmH2zOhJC~_*AuT} zvUxC38|JYN94i(05R)dVKgUQF$}#cxV7xZ4FULqFCNX*Forhgp*yr6;DsIk=ub0Hv zpk2L{9Q&|uI^b<6@i(Y+iSxeO_n**4nRLc`P!3ld5jL=nZRw6;DEJ*1z6Pvg+eW|$lnnjO zjd|8>6l{i~UxI244CGn2kK@cJ|#ecwgSyt&HKA2)z zrOO{op^o*-