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 db6f9eb66502d9..0c601d2c0051b2 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
@@ -22,27 +22,16 @@ 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]
const childSegmentMap = cache.parallelRoutes.get(key)
if (!childSegmentMap) {
diff --git a/packages/next/src/lib/metadata/metadata.tsx b/packages/next/src/lib/metadata/metadata.tsx
index 9b8c593abec534..1413bc4f110780 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 eece06cacbdeaa..1fabc8fcafab17 100644
--- a/packages/next/src/server/app-render/app-render.tsx
+++ b/packages/next/src/server/app-render/app-render.tsx
@@ -242,6 +242,8 @@ interface ParseRequestHeadersOptions {
}
const flightDataPathHeadKey = 'h'
+const getFlightViewportKey = (requestId: string) => requestId + 'v'
+const getFlightMetadataKey = (requestId: string) => requestId + 'm'
interface ParsedRequestHeaders {
/**
@@ -333,30 +335,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.
*/
@@ -524,14 +502,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,
@@ -548,9 +518,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(),
@@ -854,14 +824,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,
@@ -875,7 +837,6 @@ async function getRSCPayload(
missingSlots,
preloadCallbacks,
authInterrupts: ctx.renderOpts.experimental.authInterrupts,
- StreamingMetadata,
StreamingMetadataOutlet,
})
@@ -893,8 +854,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 */}
+
)
@@ -981,16 +943,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 = (
@@ -1000,12 +954,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}
)
@@ -1025,10 +978,7 @@ async function getErrorRSCPayload(
const seedData: CacheNodeSeedData = [
initialTree[0],
-
- {StreamingMetadata ? : null}
-
-
+ {metadata}
{process.env.NODE_ENV !== 'production' && err ? (
preloadCallbacks: PreloadCallbacks
authInterrupts: boolean
- StreamingMetadata: React.ComponentType | null
StreamingMetadataOutlet: React.ComponentType
}): Promise {
return getTracer().trace(
@@ -76,7 +75,6 @@ async function createComponentTreeInternal({
missingSlots,
preloadCallbacks,
authInterrupts,
- StreamingMetadata,
StreamingMetadataOutlet,
}: {
loaderTree: LoaderTree
@@ -91,7 +89,6 @@ async function createComponentTreeInternal({
missingSlots?: Set
preloadCallbacks: PreloadCallbacks
authInterrupts: boolean
- StreamingMetadata: React.ComponentType | null
StreamingMetadataOutlet: React.ComponentType | null
}): Promise {
const {
@@ -388,7 +385,6 @@ async function createComponentTreeInternal({
// Resolve the segment param
const actualSegment = segmentParam ? segmentParam.treeSegment : segment
- const metadata = StreamingMetadata ? : undefined
// Use the same condition to render metadataOutlet as metadata
const metadataOutlet = StreamingMetadataOutlet ? (
@@ -511,7 +507,6 @@ async function createComponentTreeInternal({
missingSlots,
preloadCallbacks,
authInterrupts,
- StreamingMetadata: isChildrenRouteKey ? StreamingMetadata : null,
// `StreamingMetadataOutlet` is used to conditionally throw. In the case of parallel routes we will have more than one page
// but we only want to throw on the first one.
StreamingMetadataOutlet: isChildrenRouteKey
@@ -694,12 +689,6 @@ async function createComponentTreeInternal({
actualSegment,
{pageElement}
- {/*
- * The order here matters since a parent might call findDOMNode().
- * findDOMNode() will return the first child if multiple children are rendered.
- * But React will hoist metadata into which breaks scroll handling.
- */}
- {metadata}
{layerAssets}
diff --git a/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx b/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx
index 5dffcc577c69ba..d90beba53fcd54 100644
--- a/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx
+++ b/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx
@@ -202,7 +202,6 @@ export async function walkTreeWithFlightRouterState({
getMetadataReady,
preloadCallbacks,
authInterrupts: experimental.authInterrupts,
- StreamingMetadata: null,
StreamingMetadataOutlet,
}
)
diff --git a/test/e2e/esm-externals/app/client/page.js b/test/e2e/esm-externals/app/client/page.js
index ba89668ed45734..f24644af006a48 100644
--- a/test/e2e/esm-externals/app/client/page.js
+++ b/test/e2e/esm-externals/app/client/page.js
@@ -6,8 +6,8 @@ import World3 from 'app-cjs-esm-package/entry'
export default function Index() {
return (
-
+
Hello {World1}+{World2}+{World3}
-
+
)
}
diff --git a/test/e2e/esm-externals/app/server/page.js b/test/e2e/esm-externals/app/server/page.js
index 1a60cabec1618d..cf273aaaa9179b 100644
--- a/test/e2e/esm-externals/app/server/page.js
+++ b/test/e2e/esm-externals/app/server/page.js
@@ -4,8 +4,8 @@ import World3 from 'app-cjs-esm-package/entry'
export default function Page() {
return (
-
+
Hello {World1}+{World2}+{World3}
-
+
)
}
diff --git a/test/e2e/esm-externals/esm-externals.test.ts b/test/e2e/esm-externals/esm-externals.test.ts
index dc6d8271296699..9dc981eb3d9895 100644
--- a/test/e2e/esm-externals/esm-externals.test.ts
+++ b/test/e2e/esm-externals/esm-externals.test.ts
@@ -28,15 +28,13 @@ describe('esm-externals', () => {
it('should return the correct SSR HTML', async () => {
const $ = await next.render$(url)
- const body = $('body > div > div').html()
+ const body = $('body p').html()
expect(normalize(body)).toEqual(expectedHtml)
})
it('should render the correct page', async () => {
const browser = await next.browser(url)
- expect(await browser.elementByCss('body > div').text()).toEqual(
- expectedText
- )
+ expect(await browser.elementByCss('body p').text()).toEqual(expectedText)
})
})
@@ -54,13 +52,13 @@ describe('esm-externals', () => {
it('should return the correct SSR HTML', async () => {
const $ = await next.render$(url)
- const body = $('body > div').html()
+ const body = $('body > p').html()
expect(normalize(body)).toEqual(expectedHtml)
})
it('should render the correct page', async () => {
const browser = await next.browser(url)
- expect(await browser.elementByCss('body > div').text()).toEqual(
+ expect(await browser.elementByCss('body > p').text()).toEqual(
expectedText
)
})
diff --git a/test/e2e/esm-externals/pages/ssg.js b/test/e2e/esm-externals/pages/ssg.js
index fff2c7fbb6ebe7..b1c438f8820c66 100644
--- a/test/e2e/esm-externals/pages/ssg.js
+++ b/test/e2e/esm-externals/pages/ssg.js
@@ -13,8 +13,8 @@ export async function getStaticProps() {
export default function Index({ worlds }) {
return (
-
+
Hello {World1}+{World2}+{World3}+{worlds}
-
+
)
}
diff --git a/test/e2e/esm-externals/pages/ssr.js b/test/e2e/esm-externals/pages/ssr.js
index e937db62b3586c..a7a6350d6f5047 100644
--- a/test/e2e/esm-externals/pages/ssr.js
+++ b/test/e2e/esm-externals/pages/ssr.js
@@ -13,8 +13,8 @@ export function getServerSideProps() {
export default function Index({ worlds }) {
return (
-
+
Hello {World1}+{World2}+{World3}+{worlds}
-
+
)
}
diff --git a/test/e2e/esm-externals/pages/static.js b/test/e2e/esm-externals/pages/static.js
index 34fb44743670c6..523919c09cc970 100644
--- a/test/e2e/esm-externals/pages/static.js
+++ b/test/e2e/esm-externals/pages/static.js
@@ -7,8 +7,8 @@ const worlds = 'World+World+World'
export default function Index() {
return (
-
+
Hello {World1}+{World2}+{World3}+{worlds}
-
+
)
}