Next.js Server-Side Rendering - Complete Implementation Guide
Mahesh Waghmare 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>;
}
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>;
}
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.
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 →