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_, 16 October 2023: 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

  • Hide Next.js Pages with Metadata Robots

    Prevent search engines from indexing specific Next.js pages using metadata robots

  • shadcn/ui

    Copy-paste React UI components built with Tailwind CSS and Radix primitives.

  • Efferd

    Pre-built, responsive shadcn/ui blocks and layouts for React applications

  • Spell UI

    Refined, copy-paste React and Tailwind CSS components with micro-interactions

  • Above-the-Fold Deferred Rendering Pattern

    Performance pattern for deferring below-the-fold components to accelerate perceived page load.

  • Cult UI

    Open-source animated UI components and blocks built for shadcn/ui projects

Updated