Next.js Streaming and Suspense
Updated on
Modern web applications often fetch data from multiple sources. Sometimes these data requests take time, which can slow down page loading.
In traditional applications, the browser waits until all data is ready before rendering the page. This causes slower initial loading.
Next.js 16 solves this problem using:
- Streaming
- React Suspense
With streaming, parts of a page can appear immediately, while slower sections load later. This improves performance and user experience.
What is Streaming in Next.js?
Streaming means sending parts of the page to the browser as soon as they are ready, instead of waiting for the entire page to load.
In Next.js 16, you can use streaming to render components as soon as their data is available. This allows users to see content faster, even if some parts of the page are still loading.
Traditional Approach
Fetch all data → Render page → Send to browser
Streaming rendering:
Render fast components → Send to browser → Load slower components later
This allows users to see content earlier.
Implementing Streaming in Next.js
In Next.js App Router, streaming is enabled by default for pages and layouts. To add loading UI, create a loading.js file in your route directory.
Example loading.js
export default function Loading() {
return <div>Loading...</div>
}
This loading component will automatically be shown while the page is streaming.
For more granular control, use Suspense boundaries around specific components that may load slowly.
What is Suspense?
Suspense is a React feature that allows you to display a fallback UI while waiting for something to load.
Example fallback UI:
- Loading spinner
- Skeleton UI
- Loading text
Suspense works perfectly with streaming.
Suspense Example
Here is an example of how to use Suspense with a Server Action:
import { Suspense } from "react"
export default function Page() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<p>Loading data...</p>}>
<Users />
</Suspense>
</div>
)
}
If the Users component takes time to load, the fallback content will appear first.
Suspense with Data Fetching
Suspense can also be used with data fetching to display a loading state while data is being retrieved.
async function Users() {
const res = await fetch("https://api.example.com/users")
const users = await res.json()
return (
<ul>
{users.map((user: any) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)
}
export default function Page() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<p>Loading users...</p>}>
<Users />
</Suspense>
</div>
)
}
Code Flow:
- Page loads immediately
- Fallback UI appears
- Data loads
- UI updates automatically
Benefits of Streaming and Suspense
Streaming and Suspense provide several advantages for modern web applications:
- Faster Initial Page Load: Users see content immediately instead of waiting for all data.
- Improved User Experience: Loading states prevent blank screens and provide feedback.
- Better Perceived Performance: Progressive loading makes apps feel faster.
- Reduced Time to Interactive: Critical content loads first, improving Core Web Vitals.
- Graceful Degradation: Fallback UIs handle slow or failed requests elegantly.
Best Practices
Follow these best practices when implementing streaming and suspense:
- Use loading.js files in Next.js App Router for automatic loading UI.
- Wrap slow-loading components with Suspense boundaries.
- Provide meaningful fallback content (skeletons, spinners, or placeholders).
- Avoid wrapping the entire page in a single Suspense boundary.
- Test loading states thoroughly to ensure good user experience.
- Consider using React's cache() or unstable_cache() for data fetching optimization.
Streaming vs Traditional Rendering
Streaming allows you to display content as it becomes available, rather than waiting for all content to load before displaying anything.
This results in faster perceived performance and a better user experience.
Whereas traditional rendering waits for all content to load before displaying anything.
Both approaches have their use cases depending on the specific requirements of your application.
| Feature | Traditional Rendering | Streaming |
|---|---|---|
| Page Load | Wait for all data | Show partial content |
| Speed | Slower | Faster |
| User experience | Worse | Better |
| Loading UI | Delayed | Immediate |