Server-Side Rendering (SSR) and Client-Server Rendering (CSR) are very popular rendering techniques in web development. You hear them more often when discussing libraries and frameworks like React.js, Vue.js, Next.js, etc.
In this article, learn what SSR and CSR mean. Also, you will discover some examples using Javascript, React.js, and Next.js and explanation of the pros and cons of using these concepts.
Prerequisites
- Ensure that you have NodeJs runtime installed on your local machine.
- Basic understanding of HTML and JavaScript. Learn more about HTML and JavaScript in this tutorial.
- Basic understanding of React.js and the Next.js React framework. Learn more about React in this tutorial.
- Basic knowledge of Node.js runtime.
What is Rendering?
First, what is Rendering? It is the conversion of a code into the web page users see on their browsers. The two prominent rendering techniques that dominate web development are SSR and CSR. Each of these offers unique advantages and caters to specific web development needs. In CSR, most of the rendering happens on the client, i.e., on a browser with Javascript. In SSR, the rendering happens on a server. An example is using any backend technology like Node.js, PHP, etc.
This article aims to teach and let you know about the ins and outs of SSR and CSR by marking the key differences, usefulness, and drawbacks known to them and to select the one that will be optimal for their specific web development projects.
Let us dive deep into how server-side and client-side rendering works. Let's begin with SSR.
Understanding Rendering in Web Development
Rendering determines how the HTML, CSS, and JavaScript of a web page are processed to produce a viewable page. The two main rendering approaches are server-side rendering (SSR) and client-side rendering (CSR). With SSR, the server generates the full HTML content for each page and sends it to the browser, so users see content quickly. CSR involves the browser receiving a minimal HTML file and using JavaScript to render content dynamically.
Importance of Choosing the Right Rendering Approach
Selecting the suitable rendering method affects your application's performance, search engine optimization (SEO), and user experience. SSR can provide faster initial page loads and better SEO since content is immediately available for search engines to crawl. CSR offers greater interactivity and smoother transitions within the application after the initial load.
Understanding the trade-offs between SSR and CSR helps you align the rendering strategy with your project's specific needs. Factors such as content type, performance requirements, SEO considerations, use of a headless CMS, and target audience should influence your decision.
How Server Side Rendering (SSR) Works
An HTTP request is made to the server, which processes the requests and generates the content(which can be HTML, JSON, or other formats). The content generated, along with the necessary Javascript, is then sent back to the client's browser.
In Server-Side Rendering (SSR), the initial response may be a pre-rendered HTML page that gets enhanced by JavaScript on the client side.
Benefits and Drawbacks of Server-Side Rendering (SSR)
One major benefit of server-side rendering is the page loading speed. This is a very important criterion for user experience.
Considering this, we can see that in SSR, the heavy lifting is taken care of on the server. This then reduces the workload on the browser(client) as there is little to no work left for the browser. It is ready to use on the fly.
The benefits of SSR are below:
- Improved SEO: This makes it easy for search engines to crawl and index your website content because it is already rendered in HTML. This is particularly crucial for sites with dynamic content.
- Fast Page Load: SSR sends a fully rendered page to the browser, which is quickly rendered and displayed to the users on the browser.
- Consistency in Content Delivery and Better Accessibility: SSR ensures that all users receive the same content regardless of device or browser capabilities.
The drawbacks of SSR are:
- Increased server load: Leaving the bulk of the rendering solely for the server can be resource-intensive, especially for websites with high dynamic content
- Slower updates: Changes to content do not automatically render/show on the page. It requires a full page reload, potentially impacting user experience. This also makes the page less interactive. This leaves a bland user experience.
Server-Side Rendering (SSR) Code Example 1
Create a new folder of your choice and give it any name. Inside it, create a file called server.js
and add the following code:
1const http = require("http");
2
3function renderHomePage(data) {
4 return `
5 <!DOCTYPE html>
6 <html lang="en">
7 <head>
8 <meta charset="UTF-8">
9 <title>SSR Example</title>
10 </head>
11 <body>
12 <h1>Welcome!</h1>
13 <p>This content is pre-rendered on the server.</p>
14 <p>Data from server: ${JSON.stringify(data)}</p>
15 </body>
16 </html>
17 `;
18}
19
20const server = http.createServer((req, res) => {
21 const data = { message: "Hello from the server!" };
22 const htmlContent = renderHomePage(data);
23 res.writeHead(200, { "Content-Type": "text/html" });
24 res.write(htmlContent);
25 res.end();
26});
27
28server.listen(3000, () => console.log("Server listening on port 3000"));
The code for this example can be found on GitHub here. The Node.js server code above demonstrates the following:
- HTTP Server Setup: Uses Node.js HTTP module to create a server.
- Rendering: Renders HTML content for the home page with server data.
- Handling Request: Responds to incoming HTTP requests with the rendered HTML content.
- Server Startup: Starts the server listening on port 3000.
The above code snippet is an example of SSR. In this example, everything that the client's web browser will display has been pre-rendered on the server.
Now spin up the server by running the command below:
#This starts or runs the node server above
node server
Open your browser and enter the application URL: http://localhost:3000. Here is the output of the above code sample when we run the command above.
A good way to check that the content on the web page was server-side rendered is to check the "View page source". Do this by right-clicking on the page and then clicking the "View Page Source" option. Here is what it looks like when we check for the example code above.
The image above clearly shows that the content on the client was rendered on the server side.
Another way to determine whether the content of your page is SSR or CSR is by inspecting the "Network" tab of your browser's developer tools. By navigating to the "Network" tab and refreshing the page, you can observe the requests and responses between your browser and the server. Then, you can examine the server's response by selecting the "Preview" or "Response" tab for a specific request.
Here's what it looks like when we check the preview tab for the above example:
NOTE: The "Preview" tab shows data that is served on the server localhost, so from the above image, all of the content is being rendered on the server.
Server-Side Rendering Code Example 2: Demonstrating Server-Side Rendering with Next.js
Next.js Components rendered on the server side are called server components. The first time Next.js renders a component, it pre-renders it from the server. Moreover, all components from Next.js 13 and above are server-side rendered by default.
1const Products = () => {
2 const frontend = ["React", "Vue", "Angular", "Next JS"];
3 return (
4 <div>
5 <h1>React App</h1>
6 <h2>Products Page</h2>
7 <p>{frontend.join(", ")}</p>
8 </div>
9 );
10};
11
12export default Products;
The code for this example can be found on GitHub here.
The code above is very similar to React.js, but in this case, it is rendered by default on the server side. Here's what the page looks like on the browser:
We can confirm this by checking the "Response" tab in our "Network" tab in Chrome developer tools.
We can see that everything on the page is server-side rendered.
How Client-Side Rendering (CSR) Works
An HTTP request is made to the server. The server receives the request and responds by sending the client a bunch of JavaScript-bundled files. The client then proceeds to process the JavaScript. The processed JavaScript modifies the DOM and renders the final HTML for the client's users.
In simple terms, CSR is when your website or web application renders HTML in the browser by processing JavaScript.
However, there's a common misconception about client-side rendering. While it's true that the client plays a significant role in rendering, it doesn't handle the entire rendering process. Instead, in client-side rendering, the client handles the bulk of the rendering work, leaving minimal or no rendering tasks for the server.
Benefits and Drawbacks of CSR
The Benefits of CSR include:
- Better User Experience: With CSR, users get real-time updates within the application without total page reloads
- Reduced Server load: The server in CSR only handles data fetching; it does not handle page rendering. This makes it more efficient and capable when the website or web app has a lot of users.
The Drawbacks of CSR include:
- Search Engine Optimization (SEO) issues: Search engines will have a hard time indexing dynamically generated content by javascript
- Slower initial load time for complex applications: Complex apps may have a delayed initial page load time since the browser must first download and run JavaScript to show content.
- Dependency on Javascript: The website or web application may not operate correctly if JavaScript is deactivated or has problems.
Client-Side Rendering Code Example 1: Using CSR in an HTML File
Create a new folder with the name client-side-rendering
. Inside it, create a file index.html
and add the following code:
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="UTF-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6 <title>CSR</title>
7 </head>
8 <body>
9 <h1>Javascript Application</h1>
10 <h4>Built with Client-Side Rendering (CSR)</h4>
11 <script src="./script.js"></script>
12 </body>
13</html>
The code for the example above can be found on GitHub here.
Next, create another new file script.js
and add the following code:
1// script.js
2const body = document.querySelector("body");
3
4const data = ["React", "Vue", "NextJS"];
5
6body.innerHTML += `<p>${data.join(", ")}</p>`;
The code for the example above can be found on GitHub here.
The above example is a case of CSR. The <h1>
Javascript Application </h1>
and <h4>
built with Client-Side Rendering (CSR) </h4>
come from the server; the script.js
file is downloaded from the server, but then the client will then have to execute the code in the script.js
file which renders the data array content React, Vue and NextJS on the page.
Here is a picture of the outcome of the above code sample:
Let us proceed to check if it is CSR rendered by checking the “View page source” of the page.
Here's a pictorial example of how the page source looks like:
We can see that the content of the title
, h1
, and h4
elements comes from the server. The data array content is then loaded and executed from the script.js
file and displayed on the page. The data array content is then loaded and executed from the script.js
file and displayed on the page.
Client-Side Rendering Code Example 2: CSR in a React App Component
1const App = () => {
2 const frontend = ["React", "Vue", "Angular", "Next JS"];
3 return (
4 <div>
5 <h1>React App</h1>
6 <h2>Products Page</h2>
7 <p>{frontend.join(", ")}</p>
8 </div>
9 );
10};
11
12export default App;
The code for this example can be found on GitHub here.
The App
component in this example is rendered on the client side to form the HTML in the picture below:
NOTE The whole content of the App component is rendered on the client side. We can confirm this by using any of the methods mentioned above to check whether your code is Client-Side or Server-side rendered.
In the screenshot above, the server only renders the <title>
tag as indicated. Other content, such as the page's body, is loaded from a script file, represented by the image referenced on line 21
in the Response tab.
Client-Side Rendering Code Example: Demonstrating Client-Side Rendering with NextJS
Next.js components that are rendered on the client side are called Client components. Client Components enable you to add client-side interactivity. They are pre-rendered on the server and hydrated on the client.
Hydration in Next.js client components ensures that the server-rendered HTML is seamlessly converted into interactive React components on the client side, enabling dynamic user experiences.
Let's look at this component below:
1"use client";
2import { useState } from "react";
3
4const Counter = () => {
5 const [count, setCount] = useState(0);
6
7 const handleButtonClick = () => {
8 setCount(count + 1);
9 };
10 return (
11 <div>
12 <p>You clicked {count} times</p>
13 <button onClick={handleButtonClick}>Click Me</button>
14 </div>
15 );
16};
17export default Counter;
The code for this example can be found on GitHub here.
The Counter
Component can initially be mistaken for a Server Component. But since it has buttons, listens for clicks (the onClick event listener), and uses hooks like useState()
, it must become a client Component to work well on the user's browser.
We make it a Client Component by adding the "use client"
directive at the top of the file, as seen in the Counter
Component above. Next.js will throw an error if you do not use the "use client"
directive.
SSR Vs CSR: Choosing Between Server-Side Rendering and Client-Side Rendering
Here are some key features to know before choosing between SSR or CSR.
Feature | SSR (Server-Side Rendering) | CSR (Client-Side Rendering) |
---|---|---|
SEO | Generally better. Search engines can easily get pre-rendered HTML content on the server, leading to better organic ranking. | Potentially requires additional SEO work. Search engines might have difficulty indexing dynamically generated content by Javascript. This requires additional SEO methods and strategies. |
Initial Load Time | Users see the content almost instantly as the server delivers a fully rendered HTML page. This is beneficial for content-heavy sites and users with slower internet connections. | The initial page load might be slower as the browser needs to download and execute JavaScript before displaying content. Development Complexity |
Development Complexity | Requires server-side code maintenance to handle data fetching and HTML generation for each request. | It focuses on client-side JavaScript code, which can be complex for highly interactive applications but simplifies server logic. |
Server-Side Rendering Use Cases
Should you use SSR? You might not need it. You should consider using SSR if your project needs the following:
- SEO is your top priority.
- Most of the site is static, i.e., It does not have a lot of dynamic content.
- Content-heavy websites with a lot of text-based information, e.g., new articles, blogs, etc
- SEO-critical applications where high search engine ranking is crucial, e.g., E-commerce stores.
- Social media previews where you want the content readily available for sharing platforms to scrape the data easily.
Client Side Rendering Use Cases
Should you use CSR? Consider CSR if your project prioritizes the following:
- Highly interactive interfaces: CSR excels at creating dynamic and responsive user experiences with smooth interactions and minimal page reloads.
- Real-time updates: If your application requires constant updates, CSR allows for immediate data fetching and display
- Single-page applications(SPAs): CSR is the foundation for SPAs, offering a seamless user experience without full page reloads, often leading to a faster-perceived performance
- Applications with a lot of user-generated content: Since the initial server response might be lighter, CSR can be efficient for user-driven content like social media feeds
- Mobile applications: The focus on client-side rendering can potentially reduce server load and bandwidth usage, benefiting mobile users.
Hybrid Approach (Combining SSR and CSR)
While SSR and CSR have strengths, sometimes a website or web app might have sections with conflicting needs or priorities. For example, while the blog section of a website might prioritize SEO and static content, the main news feed prioritizes real-time updates and user interaction. In such cases, a purely SSR or CSR approach might not be ideal for the entire application.
This is where hybrid approaches come into play. Hybrid approaches combine SSR and CSR techniques, rendering different parts of the application using the most suitable technique or method. This allows websites and web applications to leverage the strengths of both techniques, which, in the case of our previous example above, will improve SEO faster initial load time from SSR and enhance user experience and real-time updates from CSR.
Hybrid Approach Example
Imagine an e-commerce website with a blog section and product pages. Content in the blog section is primarily static, focusing on SEO. SSR would be a good choice for this section; this is because pre-rendered HTML content from the server would ensure a faster initial load for users and better searchability by search engines.
On the other hand, the Product pages must have dynamic interactions like product filtering, adding items(products) to the carts, and user reviews. CSR shines here. Handling these interactions on the client side with Javascript makes the user experience smoother, with faster responses and fewer full-page reloads.
Frameworks like Next.js and Nuxt.js offer functionalities like selective rendering and code-splitting to facilitate these hybrid approaches. Selective rendering allows developers to choose which components are rendered on the server and which are fetched by the client-side JavaScript. Code-splitting further optimizes performance by loading only the necessary JavaScript code for each page section.
While hybrid approaches offer flexibility and performance boosts, it's important to acknowledge and notice the added complexity involved. Managing both server-side and client-side rendering techniques requires more development effort than using a single rendering technique. The decision to use a hybrid approach depends on the project's specific needs; thus, developers should be ready for the complexity it will introduce.
Conclusion
We have explored the two main techniques for rendering web pages: Server-Side Rendering (SSR) and Client-Side Rendering (CSR). SSR excels at delivering pre-rendered HTML content, which speeds up the initial load time and improves SEO. CSR shines in creating and crafting dynamic and interactive user experiences with real-time updates and dynamic content.
The decision to use either SSR or CSR will depend on your project's specific needs. SSR might be a better fit if SEO and initial load time are top priorities. However, the CSR approach is more appropriate for highly interactive applications or those requiring real-time updates.
Several frameworks, like React with Next.js or Vue.js with Nuxt.js, simplify working with SSR and CSR. These frameworks allow developers to optimize performance and user experience by combining the best of both rendering techniques.
Factors to Consider When Choosing a Rendering Approach
When deciding between SSR and CSR, several factors can influence your choice.
Project Requirements
Your project's specific needs play a significant role in selecting a rendering approach. If your site relies heavily on content that needs to be visible quickly, SSR might be beneficial. SSR can provide faster initial page loads and is ideal for content-heavy websites where SEO is a priority.
Consider the performance requirements of your audience. If users are on slower networks or low-powered devices, SSR can offer a better experience. Alternatively, if building a highly interactive or single-page application (SPA), CSR might be more suitable, enabling richer user experiences with smooth interactions after the initial load.
Team Expertise
The skills and experience of your development team are important. Implementing CSR often requires proficiency in JavaScript frameworks like React or Angular. SSR might be more familiar to teams with experience in traditional server-side technologies.
Technology Stack Compatibility
Compatibility with your current technology stack is crucial. Modern frameworks like Next.js offer the flexibility to use both SSR and CSR. Integrating with a headless CMS like Strapi is feasible, allowing you to render pages effectively and improve content management. Headless CMSs are frontend agnostic, enabling developers to use any frontend framework for the presentation layer, supporting omnichannel content delivery and simplifying management with benefits like enhanced performance and scalability.
Consider future scalability and maintenance of your application. Frameworks supporting both SSR and CSR can offer flexibility as your project evolves.
Additional/Related Resources
- Rendering React SSR with Deno and Deno Deploy
- Build a blog with Nuxt (Vue.js), Strapi and Apollo
- Learn Next.js by building a real-life project: Epic Next.js 14 Tutorial Series
Emore Ogheneyoma Lawrence is a Frontend React JS Developer and Technical Writer passionate about building user-centric products and contributing to open-source projects. He enjoys creating intuitive user interfaces and sharing his knowledge by writing about his learnings on his frontend developer journey.