Development · Tip
How loading.jsx Works with Suspense in Next.js
Route-level loading.jsx vs granular React Suspense boundaries in Next.js App Router.
This tip explains the behavioral difference between route-level loading files and granular React Suspense boundaries in the Next.js App Router. A route-level loading.jsx holds the entire page until all asynchronous server components finish resolving data. Wrapping individual server components in their own Suspense boundaries allows faster components to stream in independently with skeleton fallbacks.
How it works
Setup (app/test/page.jsx):
```jsx
async function ServerComponent1() {
await fetch(...) // 500ms;
return // ...
}
async function ServerComponent2() {
await fetch(...) // 1000ms;
return // ...
}
export function Page() {
return (
<div>
<ServerComponent1 />
<ServerComponent2 />
</div>
);
}
```
1) With only an app/test/loading.jsx exporting `function Loading() { return <div>Loading...</div> }`, the whole page shows "Loading..." until BOTH fetches complete — the fastest component is blocked by the slowest.
2) To stream per component, wrap each in its own Suspense boundary with a skeleton fallback:
```jsx
export function Page() {
return (
<div>
<Suspense fallback={<Skeleton />}>
<ServerComponent1 />
</Suspense>
<Suspense fallback={<Skeleton />}>
<ServerComponent2 />
</Suspense>
</div>
);
}
```
Result: Component 1 (500ms) renders as soon as it resolves while Component 2 still shows a skeleton; no more full-page loading.jsx wait.
What it's for
- Prevent slow data fetches from blocking faster components on the same route
- Implement streaming skeleton UI states for individual Next.js Server Components
- Choose between route-level loading screens and granular component fallbacks
Key points
- Illustrates the default behavior of Next.js App Router loading.jsx files
- Shows why route-level fallbacks wait on the slowest asynchronous fetch
- Demonstrates wrapping individual server components in React Suspense boundaries
- Provides sample code comparing route-level loading to component-level streaming
Pricing
Free
Details
- Type
- Tip
- Category
- Development
- Topic
- React & Next.js
- Open source
- No
- Platforms
- Web
- For
- Next.js and React developers building with the App Router
- Tags
- nextjs, react, suspense, streaming, webdev
Why it was saved
- @asidorenko_: Shows the difference between a route-level loading.jsx (whole page waits for the slowest fetch) and per-component Suspense boundaries (each component streams in independently with its own skeleton fallback).
Related
Prevent search engines from indexing specific Next.js pages using metadata robots
Copy-paste React UI components built with Tailwind CSS and Radix primitives.
Pre-built, responsive shadcn/ui blocks and layouts for React applications
Refined, copy-paste React and Tailwind CSS components with micro-interactions
Performance pattern for deferring below-the-fold components to accelerate perceived page load.
Open-source animated UI components and blocks built for shadcn/ui projects
Updated