Search

PythonReactSEOPDF
GitHub Skill

nextjs-rendering-strategies

SSG, SSR, ISR, Streaming, and Partial Prerendering (PPR).

HoangNguyen0403☆ 143 Repository stars48 Repository forks

Installation

Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.

View source ↗Guides

Skill instructions

Rendering Strategies (App Router)

Priority: P0 (CRITICAL)

Understanding how Next.js renders content determines performance and cost.

Strategy Selection Matrix (Scaling & Cost)

Strategy Ideal For Data Freshness Performance (TTFB) Scaling Risk
SSG Marketing, Docs, Blogs Build Time Instant (CDN) None
ISR E-commerce, CMS Periodic (e.g., 60s) Instant (CDN) Low (Background Rebuilds)
SSR Dashboards, Auth Gates Real-Time (Request) Slow (Waits for Server) Critical (1 Request = 1 Compute)
PPR Personalized Apps Hybrid Instant (Shell) Medium (Streaming Holes)

Scaling Patterns

1. The "Static Shell" Pattern (Preferred)
  • Goal: Make most of the page Static to hit the CDN cache.
  • Pattern:
    • Render the generic layout (Logo, Footer, Navigation) as Static.
    • Wrap personalized/slow components (User Profile, Cart Count, Recommendations) in <Suspense>.
  • Result: TTFB (Time to First Byte) is near-instant (~50ms) because the shell is cached. User perception is fast, even if DB is slow.
2. Avoiding "SSR Waterfalls"
  • Problem: In naive SSR, the server waits for every fetch to finish before sending any HTML.
    • Scenario: DB Call (200ms) + Auth Check (100ms) + 3rd Party API (500ms) = Blank screen for 800ms.
  • Solution:
    • Move slow fetches down the component tree into Suspense boundaries.
    • Do not await everything in the root page.tsx.

1. Static Rendering (SSG) - Default

  • Behavior: Routes are rendered at build time.

  • Usage: Marketing pages, Blogs, Documentation.

  • Dynamic Routes: Use generateStaticParams to generate static pages for dynamic paths (e.g., /blog/[slug]).

    export async function generateStaticParams() {
      const posts = await getPosts();
      return posts.map((post) => ({ slug: post.slug }));
    }
    

2. Dynamic Rendering (SSR)

  • Behavior: Routes are rendered at request time.
  • Triggers:
    • Using Dynamic Functions: cookies(), headers(), searchParams.
    • Using Dynamic Fetch: fetch(..., { cache: 'no-store' }).
    • Explicit Config: export const dynamic = 'force-dynamic'.

3. Streaming (Suspense)

  • Problem: SSR blocks the entire page until all data is ready.

  • Solution: Wrap slow components in <Suspense>. Next.js instantly sends the initial HTML (static shell) and streams the slow content later.

    <Suspense fallback={<Skeleton />}>
      <SlowDashboard />
    </Suspense>
    

4. Incremental Static Regeneration (ISR)

  • Behavior: Update static content after build time without rebuilding the entire site.
  • Time-based: export const revalidate = 3600; (in layout/page) or { next: { revalidate: 3600 } } (in fetch).
  • On-Demand: revalidatePath('/posts') via Server Actions or Webhooks.

5. Partial Prerendering (PPR) - Experimental

  • Concept: Combines Static shell + Dynamic holes.
  • Config: export const experimental_ppr = true.
  • Behavior: The build generates a static shell for the route (served instantly from Edge), and dynamic parts stream in.

Runtime Configuration

  • Node.js (Default): Full Node.js API support.
  • Edge: export const runtime = 'edge'. Limited API, starts instantly, lower cost.

Examples

Read the usage examples in the source repository.

View source ↗

Source history

Indexed on
2026-01-20
Index updated
2026-01-26
Branch
main

Index and sync dates describe this directory. View the source repository for code history.

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!