import { Suspense } from "react";
export default function Page() {
return (
<main>
<Header />
<Suspense fallback={<ReviewsSkeleton />}>
<Reviews /> {/* slow async Server Component */}
</Suspense>
</main>
);
}
Streaming means the server sends HTML in chunks as each part becomes ready, instead of all at once. loading.tsx and <Suspense> mark which parts can arrive later.
Without streaming, the server waits for all data before it sends any HTML. So the slowest query decides when the user sees anything.
With streaming, the page shell and the fast parts arrive first. Slow parts arrive later, as they finish.
loading.tsx is a shortcut. It wraps the whole page in a Suspense boundary (a wrapper that shows a fallback while the content inside is loading). So the layout and a skeleton show at once on navigation.
<Suspense fallback={...}> gives finer control. Wrap individual async Server Components in it. Each boundary streams on its own.
Benefits:
- Better TTFB (Time To First Byte: how soon the first byte of the response arrives).
- Better FCP (First Contentful Paint: when the first text or image appears).
- Users can interact with parts that are already hydrated, meaning React has attached their event handlers.
Content that matters for SEO is still part of the HTML stream, so search engines see it.
- Streaming sends HTML in chunks instead of waiting for all data.
loading.tsxwraps the whole page in a Suspense boundary.- Smaller
<Suspense>boundaries each stream on their own. - Streaming improves TTFB and FCP and lets users interact sooner.