Next.js Server-Side Rendering - Complete Implementation Guide

Mahesh Mahesh Waghmare
4 min read

Next.js provides multiple rendering strategies: Server-Side Rendering (SSR), Static Site Generation (SSG), and Incremental Static Regeneration (ISR). Understanding when and how to use each is crucial for optimal performance.

This guide covers all Next.js rendering methods with practical examples.

Rendering Overview

Next.js supports multiple rendering strategies:

Server-Side Rendering (SSR):

  • Renders on each request
  • Always up-to-date
  • Slower than static
  • Use for dynamic content

Static Site Generation (SSG):

  • Pre-renders at build time
  • Fastest performance
  • Use for static content

Incremental Static Regeneration (ISR):

  • Static with revalidation
  • Best of both worlds
  • Use for frequently updated content

Client-Side Rendering (CSR):

  • Renders in browser
  • Use for interactive content

Server Components

App Router (Next.js 13+)

Server Components by Default:

// app/page.tsx - Server Component
export default async function Page() {
  const data = await fetch('https://api.example.com/data');
  const json = await data.json();
  
  return <div>{json.title}</div>;
}

Client Components:

'use client';

import { useState } from 'react';

export default function ClientComponent() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
Advertisement

Data Fetching Methods

fetch() with Caching

// Cached (default)
const data = await fetch('https://api.example.com/data');

// Revalidate every 60 seconds
const data = await fetch('https://api.example.com/data', {
  next: { revalidate: 60 }
});

// No cache
const data = await fetch('https://api.example.com/data', {
  cache: 'no-store'
});

getServerSideProps (Pages Router)

export async function getServerSideProps(context) {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();
  
  return {
    props: { data }
  };
}

SSR Implementation

App Router SSR

// app/posts/[id]/page.tsx
export default async function PostPage({ params }) {
  const post = await fetch(`https://api.example.com/posts/${params.id}`, {
    cache: 'no-store'
  }).then(res => res.json());
  
  return (
    <article>
      <h1>{post.title}</h1>
      <div>{post.content}</div>
    </article>
  );
}

Pages Router SSR

// pages/posts/[id].tsx
export async function getServerSideProps({ params }) {
  const post = await fetch(`https://api.example.com/posts/${params.id}`)
    .then(res => res.json());
  
  return {
    props: { post }
  };
}

export default function PostPage({ post }) {
  return (
    <article>
      <h1>{post.title}</h1>
      <div>{post.content}</div>
    </article>
  );
}

SSG and ISR

Static Generation

App Router:

// app/posts/[id]/page.tsx
export async function generateStaticParams() {
  const posts = await fetch('https://api.example.com/posts').then(res => res.json());
  return posts.map(post => ({ id: post.id.toString() }));
}

export default async function PostPage({ params }) {
  const post = await fetch(`https://api.example.com/posts/${params.id}`).then(res => res.json());
  return <article>{post.title}</article>;
}

ISR with Revalidation:

export const revalidate = 60; // Revalidate every 60 seconds

export default async function Page() {
  const data = await fetch('https://api.example.com/data', {
    next: { revalidate: 60 }
  }).then(res => res.json());
  
  return <div>{data.title}</div>;
}
Advertisement

Best Practices

1. Choose Right Strategy

  • SSG: Static content, blog posts
  • SSR: Dynamic, user-specific content
  • ISR: Frequently updated, but can be static
  • CSR: Highly interactive content

2. Optimize Data Fetching

  • Use caching appropriately
  • Minimize database queries
  • Use CDN for static assets

3. Error Handling

export default async function Page() {
  try {
    const data = await fetch('https://api.example.com/data');
    if (!data.ok) throw new Error('Failed to fetch');
    return <div>{data.title}</div>;
  } catch (error) {
    return <div>Error loading data</div>;
  }
}

Conclusion

Next.js SSR provides:

  • Multiple rendering strategies for different needs
  • Server Components for optimal performance
  • Flexible data fetching with caching
  • ISR for best performance and freshness

Key Points:

  • Use SSG for static content
  • Use SSR for dynamic content
  • Use ISR for frequently updated content
  • Choose strategy based on content type
  • Optimize data fetching

Understanding Next.js rendering strategies enables you to build fast, scalable applications.

Advertisement
Mahesh Waghmare

Written by Mahesh Waghmare

I bridge the gap between WordPress architecture and modern React frontends. Currently building tools for the AI era.

Follow on Twitter

Read Next