Performance: Streaming with Suspense
Streaming with Suspense improves page load speed by sending HTML chunks progressively, reducing time to first meaningful paint.
Jump into concepts and practice - no test required
import { Suspense } from 'react'; export default function Page() { return ( <Suspense fallback={<Loading />}> <AsyncComponent /> </Suspense> ); }
export default function Page() { const data = fetchDataSync(); return <MainComponent data={data} />; }
| Pattern | DOM Operations | Reflows | Paint Cost | Verdict |
|---|---|---|---|---|
| Synchronous full render | Single large DOM update | 1 large reflow | High paint cost | [X] Bad |
| Streaming with Suspense | Multiple small DOM updates | Multiple small reflows | Lower paint cost | [OK] Good |
Suspense in Next.js streaming?Suspense is used to wrap components that may take time to load, showing a fallback UI meanwhile.Suspense in a Next.js component?Suspense component requires a fallback prop with a React node, and must wrap the child component properly.<Suspense fallback="Loading..."><MyComponent /></Suspense> correctly uses fallback="Loading..." and properly closes the Suspense tag.import { Suspense } from 'react';
function SlowComponent() {
return Data loaded;
}
export default function Page() {
return (
Loading...}>
);
}SlowComponent is synchronous and returns <div>Data loaded</div> immediately without throwing a promise, so Suspense does not trigger fallback.import { Suspense } from 'react';
export default function Page() {
return (
<div>
<Suspense fallback="Loading...">
<SlowComponent />
</Suspense>
</div>
);
}
function SlowComponent() {
throw new Promise(resolve => setTimeout(resolve, 1000));
return <div>Loaded</div>;
}return <div>Loaded</div> after throw is unreachable because the throw executes first.Suspense allows each to show its own fallback independently.<Suspense fallback="Loading A..."><ComponentA /></Suspense><Suspense fallback="Loading B..."><ComponentB /></Suspense> wraps each component separately with distinct fallbacks, enabling independent streaming. <Suspense fallback="Loading A and B..."><ComponentA /><ComponentB /></Suspense> shares one fallback for both, so they load together. <ComponentA /><ComponentB /> without Suspense has no fallback. <Suspense fallback="Loading..."><ComponentA /></Suspense><ComponentB fallback="Loading B..." /> incorrectly uses fallback on a component.