
- Next.js - Home
- Next.js - Overview
- Next.js - Project Setup
- Next.js - Folder Structure
- Next.js - App Router
- Next.js - Page Router
- Next.js Features
- Next.js - Pages
- Next.js - Data Fetching
- Next.js - ISR
- Next.js - Static File Serving
- Next.js - Pre-Rendering
- Next.js - Partial Pre Rendering
- Next.js - Server Side Rendering
- Next.js - Client Side Rendering
- Next.js Routing
- Next.js - Routing
- Next.js - Nested Routing
- Next.js - Dynamic Routing
- Next.js - Parallel Routing
- Next.js - Imperative Routing
- Next.js - Shallow Routing
- Next.js - Intercepting Routes
- Next.js - Redirecting Routes
- Next.js - Navigation and Linking
- Next.js Configuration
- Next.js - TypeScript
- Next.js - Environment Variables
- Next.js - File Conventions
- Next.js - ESLint
- Next.js API & Backend
- Next.js - API Routes
- Next.js - Dynamic API Routes
- Next.js - Route Handlers
- Next.js - API MiddleWares
- Next.js - Response Helpers
- Next.js API Reference
- Next.js - CLI Commands
- Next.js - Functions
- Next.js - Directives
- Next.js - Components
- Next.js - Image Component
- Next.js - Font Component
- Next.js - Head Component
- Next.js - Form Component
- Next.js - Link Component
- Next.js - Script Component
- Next.js Styling & SEO
- Next.js - CSS Support
- Next.js - Global CSS Support
- Next.js - Meta Data
- Next.js Advanced Topics
- Next.js - Error Handling
- Next.js - Server Actions
- Next.js - Fast Refresh
- Next.js - Internationalization
- Next.js - Authentication
- Next.js - Session Management
- Next.js - Authorization
- Next.js - Caching
- Next.js - Data Caching
- Next.js - Router Caching
- Next.js - Full Route Caching
- Next.js - Request Memoization
- Next.js Performance Optimization
- Next.js - Optimizations
- Next.js - Image Optimization
- Next.js - Lazy Loading
- Next.js - Font Optimization
- Next.js - Video Optimization
- Next.js - Script Optimization
- Next.js - Memory Optimization
- Next.js - Using OpenTelemetry
- Next.js - Package Bundling Optimization
- Next.js Testing
- Next.js - Testing
- Next.js - Testing with Jest
- Next.js - Testing with Cypress
- Next.js - Testing with Vitest
- Next.js - Testing with Playwright
- Next.js Debugging & Deployment
- Next.js - Debugging
- Next.js - Deployment
- Next.js Useful Resources
- Next.js - Interview Questions
- Next.js - Quick Guide
- Next.js - Useful Resources
- Next.js - Discussion
Next.js - Server Side Rendering(SSR)
Server-Side Rendering(SSR) is a performance optimization technique used in Next.js, where HTML is generated on the server for each request. In this chapter, we will learn what is server-side-rendering, how to implement it and difference between client-side rendering and server-side rendering.
What is Server Side Rendering?
Server-Side Rendering (SSR) is a feature in Next.js, where the server processes a request and sends a fully rendered HTML page to the client. In Server-Side Rendering, the HTML page is generated on each request. So the browser doesnt have to wait for JavaScript to execute before displaying content. This make page load faster and visible to search engines.
In the other words, Server-Side Rendering ensures dynamic contents of a webpage is fetched and rendered on the server before being sent to the client.
How Server Side Rendering Works?
When a user requests a page, the server:
- Fetches necessary data for the page.
- Generates the HTML content dynamically based on the data.
- Sends the fully rendered HTML page to the user's browser.
This process ensures that users get a fully loaded page as soon as possible, which is beneficial for SEO and performance-critical applications.
Implement Server Side Rendering
Server Side Rendering can be implemented using the `getServerSideProps()` function. See the code below:
export async function getServerSideProps() { // Fetch data from API const response = await fetch('https://link/to/api'); const data = await response.json(); // Pass data as prop to the page component return { props: { data } }; } export default function Page({ data }) { return ( <div> <h1>Server-Side Rendered Data</h1> <ul> {data.map((item) => ( <li key={item.id}>{item.title}</li> ))} </ul> </div> ); }
Example Without Server Side Rendering
The example below shows client side rendering method. Here data is fetched and rendered on the user's browser. This can cause a delay in displaying data until the JavaScript is fully executed. In the code, you can see that we added a loading component, until API data is fetched from server.
'use client'; // Define as Client Component import { useState, useEffect } from 'react'; export default function CSRPage() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const fetchData = async () => { try { const response = await fetch('https://link/to/api'); const json = await response.json(); setData(json); } catch (error) { console.error('Error fetching data:', error); } finally { setLoading(false); } }; fetchData(); }, []); return ( <div> <h1>{loading ? 'Loading...' : 'Client-Side Rendered Page'}</h1> {!loading && data && ( <ul> {data.map((item) => ( <li key={item.id}>{item.title}</li> ))} </ul> )} </div> ); }
Output
In the output you can see that loading component is displayed until API data ready to display.

Example With Server Side Rendering
In the code below, we improved above component using server side rendering. Here even though we added a loading bar, it is not visible in output as the API data fetched and displayed quickly.
export default async function SSRPage() { let loading = false; const response = await fetch('https://link/to/api'); const data = await response.json(); loading = true; // Stop the loading spinner return ( <div> <h1> {loading ? 'Loading...' : 'Server-Side Rendered Page'} </h1> <ul> {data.slice(0, 5).map((todo: { id: number; title: string }) => ( <li key={todo.id}>{todo.title}</li> ))} </ul> </div> ); }
Output
The output visible instantly without any loading, because of server-side rendering.
