The Battle of Rendering Techniques: A Comprehensive Guide to SSR and CSR

Prachi
Nerd For Tech
Published in
6 min readApr 8, 2023

Understanding SSR

In SSR, the HTML content is generated on the server and sent to the client, while in CSR, the HTML content is generated on the client-side using JavaScript.

Ohh! Okay! But what exactly is “HTML content is generated on the server”??? How can server generate HTML if I am writing my HTML in any frontend framework?? Well! Here is the answer —

Suppose you have a website with a blog page that displays a list of blog posts. Each blog post has a title, description, and an image.
Example code using React and Next.js Framwork —

// pages/blog.js

import React from 'react';
import axios from 'axios';

const Blog = ({ posts }) => {
return (
<div>
<h1>Blog</h1>
<ul>
{posts.map(post => (
<li key={post.id}>
<h2>{post.title}</h2>
<p>{post.description}</p>
<img src={post.image} alt={post.title} />
</li>
))}
</ul>
</div>
);
};

export async function getServerSideProps() {
const data = await axios('https://api.example.com/posts');

return {
props: {
posts: data,
},
};
}

export default Blog;

In this example, we are using the getServerSideProps function provided by Next.js to fetch the blog post data from the server and pass it as props to the Blog component. The server generates the HTML content for the Blog component and sends it to the client. Below is the detailed explanation —

  • When a user navigates to a URL that corresponds to the Blog component, such as example.com/blog,the web browser sends a request to the server for that URL.
  • The server receives this request and uses its routing system to determine what code needs to be executed to generate the content for the requested URL.
  • If you have a React application, the server would execute a special JavaScript file that contains both server-side code and React code.

The JavaScript file that the server executes to generate the HTML content for a React component using SSR may look something like this —

// Import the React library and the Blog component
import React from 'react';
import Blog from './components/Blog';

// Import the data-fetching function for the Blog component
import { getServerSideProps } from './components/Blog';

// Define the function that will execute when the server receives a request for a URL
export async function serverRender(req, res) {
// Fetch the data required for the Blog component using the getServerSideProps function
const { props } = await getServerSideProps();

// Generate the HTML content for the Blog component using the data fetched from the server
const html = React.renderToString(<Blog {...props} />);

// Send the fully-formed HTML page back to the user's browser as the response to the initial request
res.send(`<!DOCTYPE html>
<html>
<head>
<title>My Blog</title>
</head>
<body>
<div id="root">${html}</div>
<script src="/bundle.js"></script>
</body>
</html>`);
}
  • We then define a function (serverRender), which use the getServerSideProps function to fetch the data required for the Blog component.
  • We then pass this data to the Blog component and generate the HTML content for the Blog component using the React.renderToString method, which renders the component to a string.
  • Finally, we send the fully-formed HTML page back to the user’s browser as the response to the initial request. This HTML page includes the rendered HTML for the Blog component, as well as a script tag that loads the JavaScript bundle that includes the client-side code for the React application.

Here’s a simplified example of how the server-side rendering process works:

  1. A user makes a request to the server for the blog page.
  2. The server executes the getServerSideProps function to fetch the blog post data from the server.
  3. The server generates the HTML content for the Blog component using the data fetched by the getServerSideProps function.
  4. The server sends the HTML content to the client.
  5. The client’s browser receives the HTML content and displays it to the user.

Understanding CSR

In CSR, the HTML content is generated on the client-side using JavaScript.
Example code using React and Next.js Framwork —

import React, { useState, useEffect } from 'react';

const Blog = () => {
const [posts, setPosts] = useState([]);

useEffect(() => {
async function fetchData() {
const res = await fetch('https://api.example.com/posts');
const data = await res.json();
setPosts(data);
}

fetchData();
}, []);

return (
<div>
<h1>Blog</h1>
<ul>
{posts.map(post => (
<li key={post.id}>
<h2>{post.title}</h2>
<p>{post.description}</p>
<img src={post.image} alt={post.title} />
</li>
))}
</ul>
</div>
);
};

export default Blog;
  • When the user visits the blog page, the client’s browser fetches the JavaScript code that contains the logic to fetch the blog post data from the server.
  • Once the data is fetched, the JavaScript code dynamically updates the HTML content to display the list of blog posts.

Differences

The main difference between Server-Side Rendering (SSR) and Client-Side Rendering (CSR) is how the web page is rendered and when it becomes viewable to the user.

  • With SSR, the server sends the HTML of the page that’s ready to be viewed to the browser, which means the browser can start rendering the page even before all the JavaScript code is downloaded and executed. This is different from CSR, where the browser receives a pretty empty document with links to your JavaScript, and has to wait for all of it to download and execute before rendering the page.
  • In both cases, React will need to be downloaded and build a virtual DOM, but with SSR, the user can start viewing the page while all of that is happening. In CSR, you need to wait for everything to download and execute, and then move the virtual DOM to the browser DOM for the page to become viewable.
  • An added bonus of SSR is that it can eliminate the blank page flicker that can occur with CSR. This is typically done by sending a loading image in the server response, which is then removed when everything is done loading.

Server-side rendering (SSR) can improve Lighthouse scores in a few ways:

  1. Faster first contentful paint (FCP): With SSR, the server sends a fully-formed HTML page to the user’s browser as the response to the initial request. This means that the browser can start rendering the page immediately, even before the client-side JavaScript has finished downloading and executing. This can lead to a faster FCP, which is a key metric that affects Lighthouse scores.
  2. Improved time to interactive (TTI): By sending a fully-formed HTML page to the user’s browser as the response to the initial request, SSR can reduce the amount of time it takes for the page to become interactive. This is because the browser can start rendering the page immediately and doesn’t have to wait for the client-side JavaScript to finish executing before the page becomes interactive.

However it has some disadvantages too —

  1. The page will render earlier, but the user won’t be able to interact with it until React is done executing. If the user clicks a button too early, nothing will happen.
  2. SSR takes longer to generate the HTML for your page, which slows down TTFB (Time To First Byte).

Conclusion

It’s worth noting that you don’t have to choose between CSR and SSR exclusively. You can also use a hybrid approach where some parts of your application are rendered on the server (SSR), and other parts are rendered on the client (CSR). This approach is called “Server-Side Rendering with Client-Side Hydration” (SSR+CH), and it can help you balance the benefits of CSR and SSR.

Here are some examples of Server-Side Rendering with Client-Side Hydration (SSR+CH):

  1. E-commerce website: Let’s say you have an e-commerce website with a complex product catalog and search functionality. You could use SSR to generate the initial HTML for the product pages and search results pages on the server. When a user clicks on a product or performs a search, the browser can use CSR to fetch the necessary data from the server and update the page without having to reload the entire website.
  2. Social media website: A social media website like Twitter or Facebook could use SSR to generate the initial HTML for the user’s timeline and profile pages on the server. When a user interacts with the website (e.g. likes a post, comments on a post), the browser can use CSR to update the relevant parts of the page without having to reload the entire website.
  3. News website: A news website could use SSR to generate the initial HTML for the article pages on the server. When a user clicks on an article, the browser can use CSR to fetch the necessary data (e.g. comments, related articles) from the server and update the page without having to reload the entire website.

--

--