Server-Side Rendering with React: A Complete Guide

React Server Side Rendering

Quick Summary:

Server-side rendering renders React components on the server and sends markups to the clients for faster initial loads and better SEO. The client app then hydrates the HTML to make it fully interactive. SSR improves performance and SEO for React apps when the initial page load time matters.

React stands out as a widely used JavaScript library for constructing user interfaces. In its default mode of operation, React applications perform rendering on the client-side, where the entire application loads within the user’s browser, and the React components dynamically produce the HTML content. However, for some use cases like SEO, initial page load performance, and integrating with server-side rendered apps, it can be useful to render React components on the server.

The process of rendering React components on the server prior to transmitting the resulting markup to the client is known as server-side rendering (SSR). Next.js, a widely adopted React UI framework, simplifies the creation of applications with server-side rendering capabilities.

In this extensive tutorial, we will delve deeply into the world of server-side rendering using Next.js. We’ll cover key concepts, benefits, main features from of Next.js, along with the challenges and more. Let’s get started!

What is React Server-Side Rendering?

Server-side rendering (SSR) involves the pre-rendering of web pages on the server before delivering the fully prepared HTML markup to the client. In the context of SSR, when a user initiates a page request, the server executes all the necessary code for that page, crafts the entire HTML content, and transmits it to the client.

The client browser then hydrates the static HTML by attaching event listeners and making it interactive. SSR improves the performance of web apps by sending fully rendered pages on the initial request, allowing the site to show useful content sooner.

It also helps with SEO since search engines can crawl and index the site’s content much easier. Overall, server-side rendering generates HTML on the server for faster initial loads and better SEO before the client app takes over and makes the page fully interactive.

Now that you are clear about what server-side rendering is, let’s see how it works.

How Server-Side Rendering Works?

Here is a high-level overview of how SSR works in React:

  1. On the initial request to load the page, the server runs the React rendering code and generates the HTML markup.
  2. The server sends the fully rendered HTML to the client.
  3. React then bootstraps the client-side app to hydrate the static HTML. Event handlers are attached and the page becomes interactive.
  4. Subsequent navigation within the React app works normally via client-side routing and component rendering.

With SSR, the first page load is faster and SEO-friendly. After the initial load, the client app takes over and provides a smooth Single Page Application (SPA) experience.

To understand it better we have converted the process in the pictorial format.

Using Server-Side Rendering in React

To gain a comprehensive understanding of how Next.js leverages server-side rendering (SSR), let’s delve into a practical use case and explore its specific applications.

An E-Commerce Website

E-commerce sites often have many product and category pages that need to be frequently updated with the latest inventory and pricing. These dynamic pages also need to be easily accessible to search engines and users.

Building an e-commerce website with Next.js and its server-side rendering capabilities can be very useful in this case. It allows pre-generating the HTML for each page on the server rather than client-side. This makes it faster to serve the pages and easier for search crawlers to index the constantly changing content.

By handling the initial rendering on the server, Next.js can ensure the latest product data and prices are always reflected in the served HTML. The pages can then hydrate on the client for interactivity. Overall, leveraging server-side rendering in Next.js is an effective way to build SEO-friendly e-commerce sites with frequently updating content that needs to be rapidly indexed.

Technical Case-Study: An E-commerce site using Next.js

Let’s see how we can implement server-side rendering in Next.js for an e-commerce website.

Prerequisite you need :

  • Installed Node.js
  • Visual Studio Code

Step1: Create a new project

Initially you need to generate the next.js app by using the following command in your terminal (with Admin Rights):

  1. npx create-next-app [name-of-your-app]
  2. cd [name-of-your-app]

Step 2: Add dependencies

Next, you’ll need to install the dependencies mentioned below using the following command. Generally, when you create the project, dependencies are installed by default. Run the following command in command prompt.

  1. npm install react react-dom next

At this point of time your package.json file looks like this

{
"name": "demo",
   "version": "0.1.0",
   "private": true,
   "scripts": {
     "dev": "next dev",
     "build": "next build",
     "start": "next start",
     "lint": "next lint"
   },
   "dependencies": {
     "@types/node": "20.6.2",
     "@types/react": "18.2.22",
     "@types/react-dom": "18.2.7",
     "autoprefixer": "10.4.15",
     "eslint": "8.49.0",
     "eslint-config-next": "13.4.19",
     "next": "13.4.19",
     "postcss": "8.4.30",
     "react": "18.2.0",
     "react-dom": "18.2.0",
     "tailwindcss": "3.3.3",
     "typescript": "5.2.2"
   }
}

Please note that the packages version mentioned above, as they were used when this guide was created.

Step 3: Environment Configuration

Now let’s define an environment variable to be stored in local environment variable file, which stores configuration settings which can be used across different environment.

Setting up an environment variable for your project involves the creation of a file named ‘.env.local’ at the project’s root directory. In this file, you should include a line resembling the following:”

  1. API_URL=http://localhost:3000

It’s crucial to emphasize that the ‘.env.local’ file should not be included in your source control system, as it might contain confidential data like database access details or API keys.

Instead, a recommended practice is to generate a template file named ‘.env.example,’ which includes generic or placeholder values for your environment variables. You can then commit this template file to your source control. Subsequently, team members can duplicate this template and insert the actual values for their specific environment variables.

Step 4: Create a new page

Next.js adopts a routing system based on files, implying that each page in your application is represented by a file within the “pages” directory. Creating a new page is as straightforward as crafting a new file in this directory, naming it according to your desired URL path. For instance, if you want to generate a page showcasing a list of products, you can simply create a file named “pages/products/index.js.”

Inside this file, you have the freedom to define a React component, which will be rendered when a user accesses the “/products” URL path. Here’s an illustrative example of such a component, which fetches a collection of products from an API and presents them in a list format:

function ProductsPage() {
  const [products, setProducts] = useState([]);
  useEffect(() => {
    async function fetchProducts() {
      const res = await fetch("/api/products");
      const products = await res.json();
      setProducts(products);
    }
    fetchProducts();
  }, []);

  return (
    <div>
      <h1>Matilde powered by Aglowid</h1>
      <ul>
        {products.map((product) => (
          <li key={product.id}>{product.name}</li>
        ))}
      </ul>
    </div>
  );
}
export default ProductsPage;

Step 5: Create an API end-point

To retrieve the product list, we’ve utilized an API endpoint located at “/api/products.” Next.js simplifies the process of crafting serverless API endpoints through its built-in API routing system.

To establish an API endpoint, all you need to do is craft a new file within the “pages/api” directory. For instance, if you intend to create an API endpoint that provides a list of products, you can generate a file named “pages/api/products.js.”

Within this file, you can define a function that executes when a user requests the API endpoint. For the sake of this guide, we will employ an illustrative function that fetches a list of products from a simulated API:

const products = [
  { id: 1, name: "Double Chain Necklace" },
  { id: 2, name: "Ring" },
  { id: 3, name: "Bracelet" },
];
export default function handler(req, res) {
  res.status(200).json(products);
}

Step 6: Use Server-side Rendering

By default, Next.js employs client-side rendering (CSR) for page rendering, which implies that JavaScript code gets executed within the user’s browser. To transition to server-side rendering (SSR), you’ll need to adjust your page component by incorporating a special function called `getServerSideProps`.

The `getServerSideProps` function serves as a server-side operation that takes place prior to page rendering. Its purpose is to facilitate data retrieval from APIs or databases and deliver that data as props to the page component.

Here’s a revised version of the “pages/products/index.js” file, demonstrating the utilization of `getServerSideProps` to obtain the product list directly from the server:


import { useState } from "react";
function ProductsPage({ products }) {
  const [loading, setLoading] = useState(false);
  return (
    <div>
      <h1>Products</h1>
      <ul>
        {products.map((product) => (
          <li key={product.id}>{product.name}</li>
        ))}
      </ul>
    </div>
  );
}
export async function getServerSideProps() {
  const res = await fetch(`${process.env.API_URL}/api/products`);
  const products = await res.json();
  return { props: { products } };
}
export default ProductsPage;

Take note that we have moved the useState hook for the loading state outside of the getServerProps functions, since it needs to be initialized on the client as well.

Step 7: Start the deployment server

Start the development server using the following command in the terminal.

  1. npm run dev

Or you can also start it using NPM scripts in the VS Code and start dev server in the NPM Script.

This will start the local development server at http://localhost:3000/

Step 8: Test the application

You can now test the application on http://localhost:3000/products

When you examine the page source using your browser, you’ll notice that the HTML markup incorporates the product list, signifying that the page was actually generated on the server.

Well done! You’ve now gained the expertise to implement server-side rendering within a Next.js application.

Amplify Your In-House Expertise with
Aglowid’s Seasoned ReactJS Specialists

Hire ReactJS Developers

Benefits of React Server-Side Rendering

Server-side rendering offers several benefits for web applications and websites. It enhances performance, user experience, and search engine optimization, which is crucial for better visibility and faster loading times. P.S. by following React performance optimization tips, you can maximize the advantages of server-side rendering. Here are some of the key benefits of using server-side rendering.

  • Faster Initial Page Load: Eliminates extra roundtrips to fetch JavaScript and JSON data. HTML is fully rendered on server. This leads to better user experience.
  • Consistent first paint – Browser starts rendering HTML faster leading to more consistent first paint timings across pages.
  • Works without JavaScript – The HTML rendered on server allows the page to work without client-side JavaScript. Graceful degradation.
  • Integration with server-side code – Can utilize existing backend code written in Python, Ruby, etc to render components.
  • Security: SSR can help prevent certain types of security vulnerabilities, such as Cross-Site Scripting (XSS) attacks, by reducing the need for dynamic JavaScript execution on the client side.
  • Improved Time-to-Interactive (TTI): While SSR improves initial load times, it also contributes to a quicker Time-to-Interactive (TTI) because the HTML sent by the server is already hydrated with data and event listeners. This means users can interact with the page sooner.

Apart from these benefits Server-side rendering provides 2 key benefits that are SEO & Performance with these there are also trade-offs with it.

SEO & Performance Benefits

Here are the SEO benefits and performance benefits, while using server-side rendering (SSR) with React apps:

SEO Benefits

  • Allows search engine crawlers to index content better as they can parse static HTML rendered on the server
  • Results in higher search rankings and visibility
  • Avoids empty body issues for crawlers when React app boots up

Performance Benefits

  • Faster initial page load speed as complete HTML is sent from server
  • Reduces time-to-interactive as HTML can hydrate faster than re-rendering on client
  • More consistent performance without relying on client device capabilities
  • Ability to leverage CDN caching of rendered HTML

In summary, SSR improves SEO and performance but requires extra effort to manage server-client architecture and prevent mismatches.

Each coin has two sides and server-side rendering is no different. SSR provides various benefits but it also has certain limitations. Let’s look at the limitations of SSR.

Challenges of Server-Side Rendering in React

While server-side rendering (SSR) offers numerous benefits, it also comes with its own set of challenges and complexities that developers need to address. Here are some of the common challenges associated with SSR:

  • Complex setup – SSR requires configuring a server to handle the rendering in addition to the client app, so the setup is more complex compared to client-only apps.
  • Vendor libraries – Some third-party libraries may need special handling to work with SSR. They may depend on browser APIs and need workarounds.
  • Repeated logic – Some code needs to be run on both server and client, leading to repetition. The same data loading logic needs to exist in two places.
  • Server load – Rendering on the server can consume significant CPU and memory resources at scale. Needs to be optimized to prevent overloading servers.
  • Session management – Managing user sessions and state across server and client can be tricky. Cookies and session stores need to be synced.
  • Data mismatches – If data on server is stale compared to client, it can cause mismatches after client-side rendering begins.
  • Debugging – Debugging SSR code can be harder because bugs might only occur on client or server.
  • Caching – Proper caching needs to be implemented so repeated requests don’t keep hitting the servers.
  • Streaming – Server-streamed responses are more complex to handle and parse on the client side.

Server-Side Rendering vs Client-Side Rendering: Which one to choose?

Server-Side Rendering (SSR) and Client-Side Rendering (CSR) are contrasting methods for the way web pages are presented to users. They define how a webpage is prepared and exhibited on your screen, whether on a computer or a mobile device. In simple terms, SSR implies that the rendering process happens on the server, whereas CSR indicates that it takes place on your local device. When you’re in the process of constructing a website, one of the pivotal decisions to make is whether to opt for server-side or client-side rendering. Here are benefits and limitations of each to make an informed decision on when to choose each approach:

Server-Side Rendering

When you create content for your website on the server and then send it to users’ browsers, this process is known as server-side rendering, or SSR. Search engines can view and evaluate the content on your website before presenting it to consumers, which is a major SEO benefit of this strategy. The drawback of SSR is that users might have to wait longer for their browsers to load the page. This delay could make the user experience seem sluggish on poorer internet connections or with expensive data plans.

Pros:

  • Better SEO as search engines can crawl fully rendered HTML
  • Faster initial page load
  • More consistent performance on server
  • Allows server access for auth checks

Cons:

  • More complex setup and architecture
  • Repeated logic on server and client
  • Scalability concerns at high traffic

Use Cases:

  • Marketing sites where SEO is critical
  • Apps where initial load time matters
  • Frequently changing data
  • Transitioning legacy sites to React

Client-Side Rendering

Client-Side Rendering (CSR) is a technique where a webpage loads relatively sparsely in the browser when it first loads. It offers a basic CSS style set along with an HTML framework. But as fast as feasible, typically in a matter of seconds, the remaining content is retrieved from the server and neatly incorporated into this initial HTML framework. This strategy makes sure that visitors to your website won’t run into blank areas or wait for information to load. Because CSR enables faster and more effective browsing in situations where users have slower internet connections or data prices are an issue, its benefits are especially clear to see.

Pros:

  • Simpler architecture with no server component
  • Faster page transitions after initial load
  • Easier debugging with code in one place

Cons:

  • Lower initial page SEO and load performance
  • Relies on client capabilities and connectivity

Use Cases:

  • Simple apps with few pages
  • Apps where interactivity is more critical than first load
  • Apps that rarely need re-crawling by search engines

In summary, SSR provides SEO and performance benefits but with added complexity, while CSR is simpler and fits most interactive web apps well. Evaluate your priorities and needs to determine if SSR is worthwhile

Cutting Costs but
NOT Cutting Quality

that’s how we roll! 🚀

Hire Web Developers

Is Server-side rendering superior?

Server-side rendering provides SEO, initial load speed, and consistent server performance benefits, but adds complexity in development, debugging, and infrastructure scaling. It is well-suited for marketing sites, legacy transitions, and frequently changing data, but modern interactive apps often don’t require SSR’s complexity and can adopt client-side rendering for its simplicity, lower costs, and smooth post-load user experience.

This post was last modified on March 21, 2024 4:19 pm

Saurabh Barot: Saurabh Barot, CTO at Aglowid IT Solutions, brings over a decade of expertise in web, mobile, data engineering, Salesforce, and cloud computing. Known for his strategic leadership, he drives technology initiatives, oversees data infrastructure, and leads cross-functional teams. His expertise spans across Big Data, ETL processes, CRM systems, and cloud infrastructure, ensuring alignment with business goals and keeping the company at the forefront of innovation.
Related Post