diff --git a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts index db6f9eb66502d..471b1804e7ac3 100644 --- a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts +++ b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts @@ -1,5 +1,6 @@ import type { FlightRouterState } from '../../../../server/app-render/types' import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' +import { DEFAULT_SEGMENT_KEY } from '../../../../shared/lib/segment' import { createRouterCacheKey } from '../create-router-cache-key' export function findHeadInCache( @@ -22,28 +23,22 @@ function findHeadInCacheImpl( // First try the 'children' parallel route if it exists // when starting from the "root", this corresponds with the main page component - if (parallelRoutes.children) { - const [segment, childParallelRoutes] = parallelRoutes.children - const childSegmentMap = cache.parallelRoutes.get('children') - if (childSegmentMap) { - const cacheKey = createRouterCacheKey(segment) - const cacheNode = childSegmentMap.get(cacheKey) - if (cacheNode) { - const item = findHeadInCacheImpl( - cacheNode, - childParallelRoutes, - keyPrefix + '/' + cacheKey - ) - if (item) return item - } - } - } + const parallelRoutesKeys = Object.keys(parallelRoutes).filter( + (key) => key !== 'children' + ) - // if we didn't find metadata in the page slot, check the other parallel routes - for (const key in parallelRoutes) { - if (key === 'children') continue // already checked above + // if we are at the root, we need to check the children slot first + if ('children' in parallelRoutes) { + parallelRoutesKeys.unshift('children') + } + for (const key of parallelRoutesKeys) { const [segment, childParallelRoutes] = parallelRoutes[key] + // If the parallel is not matched and using the default segment, + // skip searching the head from it. + if (segment === DEFAULT_SEGMENT_KEY) { + continue + } const childSegmentMap = cache.parallelRoutes.get(key) if (!childSegmentMap) { continue diff --git a/packages/next/src/lib/metadata/metadata.tsx b/packages/next/src/lib/metadata/metadata.tsx index 9b8c593abec53..1413bc4f11078 100644 --- a/packages/next/src/lib/metadata/metadata.tsx +++ b/packages/next/src/lib/metadata/metadata.tsx @@ -206,9 +206,11 @@ export function createMetadataComponents({ const promise = resolveFinalMetadata() if (serveStreamingMetadata) { return ( - - - + ) } const metadataState = await promise diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 5e9d8da2e616b..9e334353965ed 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -245,6 +245,8 @@ interface ParseRequestHeadersOptions { } const flightDataPathHeadKey = 'h' +const getFlightViewportKey = (requestId: string) => requestId + 'v' +const getFlightMetadataKey = (requestId: string) => requestId + 'm' interface ParsedRequestHeaders { /** @@ -336,30 +338,6 @@ function createNotFoundLoaderTree(loaderTree: LoaderTree): LoaderTree { ] } -function createDivergedMetadataComponents( - Metadata: React.ComponentType, - serveStreamingMetadata: boolean -): { - StaticMetadata: React.ComponentType<{}> - StreamingMetadata: React.ComponentType<{}> | null -} { - function EmptyMetadata() { - return null - } - const StreamingMetadata: React.ComponentType | null = serveStreamingMetadata - ? Metadata - : null - - const StaticMetadata: React.ComponentType<{}> = serveStreamingMetadata - ? EmptyMetadata - : Metadata - - return { - StaticMetadata, - StreamingMetadata, - } -} - /** * Returns a function that parses the dynamic segment and return the associated value. */ @@ -527,14 +505,6 @@ async function generateDynamicRSCPayload( serveStreamingMetadata, }) - const { StreamingMetadata, StaticMetadata } = - createDivergedMetadataComponents(() => { - return ( - // Adding requestId as react key to make metadata remount for each render - - ) - }, serveStreamingMetadata) - flightData = ( await walkTreeWithFlightRouterState({ ctx, @@ -551,9 +521,9 @@ async function generateDynamicRSCPayload( isPossibleServerAction={ctx.isPossibleServerAction} /> {/* Adding requestId as react key to make metadata remount for each render */} - - {StreamingMetadata ? : null} - + + {/* Not add requestId as react key to ensure segment prefetch could result consistently if nothing changed */} + ), injectedCSS: new Set(), @@ -857,14 +827,6 @@ async function getRSCPayload( const preloadCallbacks: PreloadCallbacks = [] - const { StreamingMetadata, StaticMetadata } = - createDivergedMetadataComponents(() => { - return ( - // Not add requestId as react key to ensure segment prefetch could result consistently if nothing changed - - ) - }, serveStreamingMetadata) - const seedData = await createComponentTree({ ctx, loaderTree: tree, @@ -878,7 +840,6 @@ async function getRSCPayload( missingSlots, preloadCallbacks, authInterrupts: ctx.renderOpts.experimental.authInterrupts, - StreamingMetadata, StreamingMetadataOutlet, }) @@ -896,8 +857,9 @@ async function getRSCPayload( statusCode={ctx.res.statusCode} isPossibleServerAction={ctx.isPossibleServerAction} /> - - + + {/* Not add requestId as react key to ensure segment prefetch could result consistently if nothing changed */} + ) @@ -984,16 +946,8 @@ async function getErrorRSCPayload( serveStreamingMetadata: serveStreamingMetadata, }) - const { StreamingMetadata, StaticMetadata } = - createDivergedMetadataComponents( - () => ( - - {/* Adding requestId as react key to make metadata remount for each render */} - - - ), - serveStreamingMetadata - ) + // {/* Adding requestId as react key to make metadata remount for each render */} + const metadata = const initialHead = ( @@ -1003,12 +957,11 @@ async function getErrorRSCPayload( isPossibleServerAction={ctx.isPossibleServerAction} /> {/* Adding requestId as react key to make metadata remount for each render */} - + {process.env.NODE_ENV === 'development' && ( )} - {StreamingMetadata ? : null} - + {metadata} ) @@ -1028,10 +981,7 @@ async function getErrorRSCPayload( const seedData: CacheNodeSeedData = [ initialTree[0], - - {StreamingMetadata ? : null} - - + {metadata} {process.env.NODE_ENV !== 'production' && err ? (