Skip to content

Commit f0a6bb4

Browse files
authored
[metadata] skip head cache in default slot (#78206)
1 parent ee579bf commit f0a6bb4

File tree

14 files changed

+118
-0
lines changed

14 files changed

+118
-0
lines changed

packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { FlightRouterState } from '../../../../server/app-render/types'
22
import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime'
3+
import { DEFAULT_SEGMENT_KEY } from '../../../../shared/lib/segment'
34
import { createRouterCacheKey } from '../create-router-cache-key'
45

56
export function findHeadInCache(
@@ -33,6 +34,11 @@ function findHeadInCacheImpl(
3334

3435
for (const key of parallelRoutesKeys) {
3536
const [segment, childParallelRoutes] = parallelRoutes[key]
37+
// If the parallel is not matched and using the default segment,
38+
// skip searching the head from it.
39+
if (segment === DEFAULT_SEGMENT_KEY) {
40+
continue
41+
}
3642
const childSegmentMap = cache.parallelRoutes.get(key)
3743
if (!childSegmentMap) {
3844
continue

test/e2e/app-dir/metadata-streaming-parallel-routes/app/layout.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ export default function Root({ children }: { children: ReactNode }) {
1414
{`to /parallel-routes-default`}
1515
</Link>
1616
<br />
17+
18+
<Link href="/parallel-routes-no-children" id="to-no-children">
19+
{`to /parallel-routes-no-children`}
20+
</Link>
21+
<br />
1722
</div>
1823
{children}
1924
</body>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Page() {
2+
return 'default @bar'
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function Page() {
2+
return <p id="bar-page">test-page @bar - 1</p>
3+
}
4+
5+
export const metadata = {
6+
title: 'first page - @bar',
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default function Layout({ children }) {
2+
return (
3+
<div>
4+
<h2>@bar Layout</h2>
5+
<div id="bar-children">{children}</div>
6+
</div>
7+
)
8+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Page() {
2+
return 'page @bar'
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function Page() {
2+
return <p id="bar-page">test-page @bar - 2</p>
3+
}
4+
5+
export const metadata = {
6+
title: 'second page - @bar',
7+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Page() {
2+
return 'default @foo'
3+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default function Layout({ children }) {
2+
return (
3+
<div>
4+
<h2>@foo Layout</h2>
5+
<div id="foo-children">{children}</div>
6+
</div>
7+
)
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Page() {
2+
return 'no-bar @foo'
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Page() {
2+
return 'page @foo'
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Page() {
2+
return 'test-page @foo'
3+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { connection } from 'next/server'
2+
import Link from 'next/link'
3+
4+
// skip rendering children
5+
export default function Layout({ bar, foo }) {
6+
return (
7+
<div>
8+
<h1>Parallel Routes Layout - No Children</h1>
9+
10+
<Link href="/parallel-routes-no-children/first" id="to-no-children-first">
11+
{`to /parallel-routes-no-children/first`}
12+
</Link>
13+
<br />
14+
<Link
15+
href="/parallel-routes-no-children/second"
16+
id="to-no-children-second"
17+
>
18+
{`to /parallel-routes-no-children/second`}
19+
</Link>
20+
<br />
21+
22+
<div id="foo-slot">{foo}</div>
23+
<div id="bar-slot">{bar}</div>
24+
</div>
25+
)
26+
}
27+
28+
export async function generateMetadata() {
29+
await connection()
30+
await new Promise((resolve) => setTimeout(resolve, 300))
31+
return {
32+
title: 'parallel-routes-default layout title',
33+
}
34+
}

test/e2e/app-dir/metadata-streaming-parallel-routes/metadata-streaming-parallel-routes.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,29 @@ describe('app-dir - metadata-streaming', () => {
5757
expect($('title').length).toBe(1)
5858
expect($('body title').text()).toBe('parallel-routes-default layout title')
5959
})
60+
61+
it('should change metadata when navigating between two pages under a slot when children is not rendered', async () => {
62+
// first page is /parallel-routes-no-children/first,
63+
// second page is /parallel-routes-no-children/second
64+
// navigating between them should change the title metadata
65+
const browser = await next.browser('/parallel-routes-no-children/first')
66+
await retry(async () => {
67+
expect(await browser.elementByCss('title').text()).toBe(
68+
'first page - @bar'
69+
)
70+
})
71+
// go to second page
72+
await browser
73+
.elementByCss('[href="/parallel-routes-no-children/second"]')
74+
.click()
75+
// wait for navigation to finish
76+
await retry(async () => {
77+
expect(await browser.elementByCss('#bar-page').text()).toBe(
78+
'test-page @bar - 2'
79+
)
80+
})
81+
expect(await browser.elementByCss('title').text()).toBe(
82+
'second page - @bar'
83+
)
84+
})
6085
})

0 commit comments

Comments
 (0)