Introduction to Server Side Rendering

In modern web development, performance, SEO, and user experience are three key factors that define the success of a web application. While React is powerful for building fast and dynamic client-side applications, it relies on client-side rendering (CSR) by default. This means that HTML is generated in the browser, not on the server, which can negatively affect SEO and initial load times.

To overcome these limitations, Server-Side Rendering (SSR) was introduced — and Next.js became the most popular framework for implementing it efficiently. In this detailed post, we’ll explore what SSR is, how Next.js enables it, and how to build optimized, SEO-friendly, and fast web applications using Next.js.


What Is Server-Side Rendering (SSR)?

Server-Side Rendering (SSR) is the process of rendering web pages on the server instead of in the browser. When a user requests a page, the server generates the complete HTML content and sends it to the client.

This approach ensures that users see meaningful content faster, and search engines can easily crawl the rendered HTML for indexing.

How SSR Differs from CSR (Client-Side Rendering)

AspectClient-Side Rendering (CSR)Server-Side Rendering (SSR)
RenderingHappens in the browserHappens on the server
SEODifficult for search enginesExcellent for SEO
PerformanceSlower first loadFaster initial load
ComplexitySimple setupRequires server configuration

Why Server-Side Rendering Matters

React by itself focuses on building UI components but doesn’t include rendering strategies. In CSR, the browser downloads a blank HTML shell and executes JavaScript to render the page. This delays the time before users see content.

SSR, on the other hand, pre-renders pages on the server and sends them to the client fully populated with HTML.

Benefits of SSR

  1. Faster First Contentful Paint (FCP) – Users see content quicker.
  2. Better SEO – Search engines can index server-rendered HTML easily.
  3. Improved Social Media Previews – Meta tags and Open Graph data are available for crawlers.
  4. Enhanced Performance on Slow Networks – Reduced reliance on client-side computation.
  5. Better Caching and CDN Support – HTML can be cached and served globally.

Why Next.js for Server-Side Rendering

Next.js, built on top of React, is a framework that provides hybrid rendering capabilities — you can use static site generation (SSG), client-side rendering (CSR), and server-side rendering (SSR) in the same app.

Next.js abstracts the complexity of SSR and offers an intuitive API to handle routing, data fetching, and rendering.

Key Features of Next.js

  1. Automatic Server-Side Rendering
    Pages are pre-rendered by default.
  2. File-based Routing System
    Each file in the /pages directory automatically becomes a route.
  3. Built-in API Routes
    You can create backend endpoints without setting up a separate server.
  4. Optimized Image Handling
    Next.js provides automatic image optimization.
  5. Static Generation and Incremental Static Regeneration (ISR)
    Combine SSR with static site benefits.

Setting Up a Next.js Project

You can create a new Next.js app using the following commands:

npx create-next-app@latest my-next-app
cd my-next-app
npm run dev

This starts a development server at http://localhost:3000.

By default, Next.js renders pages under the /pages directory.

Example structure:

my-next-app/
  pages/
index.js
about.js
public/ styles/ package.json

Each file inside pages/ becomes a route in your application.


How Server-Side Rendering Works in Next.js

When a user visits a Next.js page, the framework executes the page’s logic on the server, fetches data if needed, and renders HTML. The fully-rendered page is then sent to the client, where React hydrates it to make it interactive.

The life cycle looks like this:

  1. Request comes to the server.
  2. The server runs the React code and generates HTML.
  3. The server sends the HTML and minimal JavaScript to the browser.
  4. React hydrates the HTML, making it interactive.

Implementing SSR with getServerSideProps

In Next.js, any page can use getServerSideProps() to enable server-side rendering.

This function runs on the server before rendering the page and provides data as props to the component.

Example:

export async function getServerSideProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
  const data = await res.json();

  return {
props: { post: data },
}; } export default function PostPage({ post }) { return (
<div>
  <h1>{post.title}</h1>
  <p>{post.body}</p>
</div>
); }

When you visit this page, Next.js runs getServerSideProps on the server, fetches the data, and sends HTML with the rendered post content to the client.


Differences Between SSR and SSG

Next.js supports multiple rendering strategies. Here’s how SSR differs from SSG (Static Site Generation):

FeatureSSRSSG
Data FetchingOn every requestAt build time
PerformanceSlightly slowerFaster (pre-built)
Use CaseDynamic data (e.g., dashboards)Static content (e.g., blogs)

Example: Dynamic SSR Page

You can use route parameters with SSR.

export async function getServerSideProps(context) {
  const { id } = context.params;
  const res = await fetch(https://jsonplaceholder.typicode.com/posts/${id});
  const post = await res.json();

  return {
props: { post },
}; } export default function Post({ post }) { return (
<article>
  <h1>{post.title}</h1>
  <p>{post.body}</p>
</article>
); }

For dynamic routes, create a file named [id].js in the /pages directory.


Caching and Performance in SSR

Since SSR fetches data on every request, performance optimization is crucial.

Techniques to Optimize SSR

  1. Caching Responses – Cache API responses using Redis or Vercel’s Edge Caching.
  2. Use HTTP Headers – Set Cache-Control headers for static resources.
  3. Reduce API Calls – Batch or prefetch data where possible.
  4. Edge Rendering – Use Next.js Middleware or Edge Functions for faster rendering closer to the user.

Example header:

res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate');

This allows caching for 60 seconds and serving stale data while revalidating in the background.


Handling Authentication with SSR

Authentication is one of the most common use cases for SSR. You can check cookies or tokens in getServerSideProps before rendering the page.

Example:

export async function getServerSideProps(context) {
  const { req } = context;
  const token = req.cookies.auth;

  if (!token) {
return {
  redirect: {
    destination: '/login',
    permanent: false,
  },
};
} return {
props: { user: { name: 'John Doe' } },
}; }

This ensures that only authenticated users can access certain pages.


SSR vs CSR Performance Comparison

MetricSSRCSR
First Load TimeFasterSlower
SEO SupportExcellentLimited
Dynamic DataSupportedSupported
InteractivityAfter hydrationImmediate
ComplexityHigherLower

SSR provides a better initial experience, while CSR may perform better for highly interactive, data-heavy apps after initial load.


Combining SSR and Client-Side Rendering

Sometimes, not all data needs to be rendered on the server. You can combine SSR for critical data and CSR for secondary data using hooks like useEffect.

Example:

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

export default function HybridPage({ criticalData }) {
  const [extraData, setExtraData] = React.useState(null);

  React.useEffect(() => {
fetch('/api/extra')
  .then(res => res.json())
  .then(data => setExtraData(data));
}, []); return (
<div>
  <h1>Critical Data</h1>
  <p>{criticalData.message}</p>
  <h2>Extra Data</h2>
  {extraData && <p>{extraData.details}</p>}
</div>
); }

This hybrid rendering pattern improves performance while maintaining interactivity.


Deploying SSR Applications

Next.js makes deployment straightforward. You can deploy SSR apps to platforms like Vercel, Netlify, or custom Node.js servers.

Deploying to Vercel

  1. Push your project to GitHub.
  2. Go to vercel.com.
  3. Import your repository.
  4. Vercel automatically detects Next.js and configures SSR.

Deploying to a Custom Node.js Server

Create a custom server file:

const { createServer } = require('http');
const next = require('next');

const app = next({ dev: process.env.NODE_ENV !== 'production' });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  createServer((req, res) => handle(req, res)).listen(3000, () => {
console.log('Server running on http://localhost:3000');
}); });

Run with:

node server.js

SEO Optimization with SSR

One of the biggest advantages of SSR is its SEO friendliness. Since content is pre-rendered on the server, crawlers like Google can easily index it.

Best Practices for SEO with SSR

  1. Use the <Head> component from next/head to manage meta tags.
  2. Include structured data (JSON-LD) for rich search results.
  3. Optimize URLs and use descriptive routes.

Example:

import Head from 'next/head';

export default function BlogPost({ post }) {
  return (
&lt;&gt;
  &lt;Head&gt;
    &lt;title&gt;{post.title}&lt;/title&gt;
    &lt;meta name="description" content={post.excerpt} /&gt;
  &lt;/Head&gt;
  &lt;article&gt;
    &lt;h1&gt;{post.title}&lt;/h1&gt;
    &lt;p&gt;{post.body}&lt;/p&gt;
  &lt;/article&gt;
&lt;/&gt;
); }

Debugging and Troubleshooting SSR

Common Issues

  1. API Calls Failing – Ensure URLs are absolute and accessible from the server.
  2. Hydration Errors – Avoid rendering mismatched content between server and client.
  3. Long Server Response Time – Optimize data fetching and caching.

Debugging Tips

  • Use console.log() in getServerSideProps for server logs.
  • Use next build && next start to simulate production.
  • Monitor performance with Next.js Analytics or Chrome DevTools.

When to Use SSR

Use SSR in the following scenarios:

  1. Dynamic Data – Pages with content that changes frequently.
  2. SEO-Critical Pages – Blogs, e-commerce product pages, and landing pages.
  3. Personalized Content – Pages that vary by user or session.

Avoid SSR for static or rarely changing pages (use SSG instead).


When Not to Use SSR

SSR is not always ideal. It adds server load and complexity. Avoid it for:

  1. Highly Interactive Dashboards – CSR might be faster after initial load.
  2. Static Marketing Pages – Use SSG.
  3. Apps with Minimal SEO Needs – SPAs can suffice.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *