Fetch in sibling components
Give each Server Component its own fetch so the fetches overlap.
From vercel-react-best-practices, rule server-parallel-fetching.
Same two fetches, two trees
Press Render page, then drag a toolbar latency.
Parent awaits firstBad
0 msserver time
<Page>async<Sidebar>async
900 msSibling componentsGood
0 msserver time
<Page>sync<Header>async<Sidebar>async
500 msasync function Header() {
const data = await fetchHeader()
return <div>{data}</div>
}
async function Sidebar() {
const items = await fetchSidebarItems()
return <nav>{items.map(renderItem)}</nav>
}
export default function Page() {
return (
<div>
<Header />
<Sidebar />
</div>
)
}
Move the await into Header
Drag the highlighted line into Header, or press Enter.
page.tsxWaterfall
// new component
async function Header() {
drop the await here
return <div>{header}</div>
}
export default async function Page() {
return (
<div>
<div>{header}</div>
<Sidebar />
</div>
)
}
Press to move this line between Page and Header.
Server timelineSidebar is async
900 msserver time
The children-prop variant
Press Render page. Only the header await moves.
Layout awaits itselfBad
0 msserver time
<Page>sync<Layout>async- children
<Sidebar>
await fetchHeader(); return childrenRenders <Header />Good
0 msserver time
<Page>sync<Layout>sync<Header>async- children
<Sidebar>
return <><Header />{children}</>function Layout({ children }: { children: ReactNode }) {
return (
<div>
<Header />
{children}
</div>
)
}
export default function Page() {
return (
<Layout>
<Sidebar />
</Layout>
)
}
Why it matters, pros and cons
Why it matters
A parent's await blocks its children. Siblings cost the slowest fetch, not the sum.
Pros
- Latency is max, not sum
- Each component owns its data
- Each sibling can stream behind Suspense
Cons
- Real dependencies still wait; start that promise early
- Duplicate sibling fetches need
React.cache - One consumer of both?
Promise.allis simpler