React Server Components: Paradigm Shift with Next.JS

Quick Summary:

React Server Components (RSCs) are finally out with full support with Next.js 13. Blurring the lines between React client-side rendering and React service-side rendering, React redefines how developers approach building user interfaces. Let’s catch up on What is React Server Component and when and why you should adopt it for your project.

React Server Components (RSCs) were first introduced in December 2020, inviting the React development community to contribute via RFCs. After generating significant interest and discussion, RSCs were officially released to the public on February 23, 2023, and are now the default option in Next.js 13.

In this duration, there has already been a lot of speculation, testing, and analysis done by many of the top React experts to understand how to adapt to this paradigm shift and what benefits it brings to the table.

The goal of this blog today is to adapt to the mental shift in how we think about building React apps. We will focus on understanding the React Component Architecture, differences between client-side React, server-side React, and React Server Components, and other such aspects to give you a holistic view of React components.

Differences between CSR vs SSR vs RSC

If you are familiar with React’s component architecture, you would know that any React element tree renders the ‘Parent’ components, which render its Child components. With React Server Component, you can render some of the components on the server and others on the client or browser.

So, how do we differentiate between Server and Client components?

Differentiating between server and client components comes through the extensions – ‘.server.js’ and ‘.client.js’, respectively. Files with basic ‘.js’ extension are shared components that can work on both – the server and client-side depending on where it is imported.

Here is a list of some standard server-side, client-side, and shared components for your reference:

Server-Side Components (.server.js) Client Side Components (.client.js) Shared Components (.js)
Page Layouts Header Navigation Menu
SEO/Meta Tags Footer Search Box
Initial Data Fetching Forms Blog Post List
User Authentication Buttons Notifications
Caching Mechanism Modals/Popups Loading Indicators
PDF Generation Chart/Graphs User Profile
Sitemaps Animations Pagination
RSS Feeds Audio/Video Players
Image Carousels

What is Client Side React (CSR)?

React has traditionally focused on client-side rendering for building dynamic and highly interactive UI for frontend development. Hence, all React Components were referred to as ‘client components’ since they all used to run in the browser.

What does this do?

Whenever users visit a React-based website, their browser downloads all the code needed for all React components. It then constructs the React element tree and renders it to the Document Object Model – DOM. This process allows React to develop interactive and creative user interfaces on the client side.

Why Client Side React works well:

  • Fast and interactive UI
  • Promotes Code Reusability with Composable Components
  • Describes what the UI should look like
  • Can be deployed without dependence on servers

What are the downfalls of Client-Side React Rendering?

  • Slower Initial Load Time – The browser must download and parse JS bundles before it is reflected on the UI. This raises the issue of the user seeing a blank screen till the process is completed.
  • SEO Bottlenecks – Since the browser handles both JavaScript and HTML, there is no static HTML file, which means bots would have to execute JS to index the content.
  • Resource-Intensive – Since CSR depends on the client’s server to handle and manage JavaScript bundles, it could be resource-intensive on mobile devices or less powerful computers. It could also lead to battery drainage on mobile/laptops.

What is Server-Side Rendering with React (SSR)?

SSR or Server Side React is a method that enables developers to render React on the server instead of the client’s browser. It generates the server’s HTML file and sends the pre-rendered HTML file to the client’s browser. SSR is achieved using the ReactDOMServer module that renders the React app to an HTML String. This string is then sent to the client and inserted in the DOM.

What does this do?

It allows the client to render the app without needing to download/execute any JavaScript file. This results in several benefits and certain drawbacks as well.

Why Server Side React works well:

  • Faster Page Load – SSR helps improve the initial page loading time issue of client-side React. It renders the app on the server before sending it to the client, significantly improving page loading times.
  • Improved Performance – SSR reduces the amount of JavaScript files needed to be downloaded and executed by the client. This reduces the effort and computational effort the client would have to make. Hence, server side rendering React apps work better even on low-spec devices.
  • SEO Improvements – React Server-Side Rendering helps boost the SEO of React apps by making them more crawlable and indexable by search engines.

What are the downfalls of Server-Side React Rendering?

  • Obscure Separation of Concern – This can confuse the separation of concerns between client and server responsibilities in the codebase.
  • Complex Setup – Requires configuring and running a Node.js server for handling re-rendering requirements.
  • Hydration for Interactivity – To achieve interactivity in your server-side React apps

What are React Server Components?

React Server Components are React components that run only on the server. This newly introduced method allows developers to leverage server- and client-side rendering together.

What does this do?

This allows React developers to render React components on the server or the client, depending on the requirements. So, for instance, for initial page load, server-side rendering is more beneficial. Hence, we can use server-side React, but for adding interactivity elements for users, we can resort to client-side React.

Why does the React Server Component work well?

  • Improved Performance – Avoids re-hydration and batch updates server-side for better initial page load times.
  • Scalability – Creating isolated environments makes scaling server resources easier.
  • Interactivity – Scaling server resources is more accessible since updates are streamed from servers.
  • Improved SEO – Search Engine Crawlers can quickly parse fully rendered HTML markup generated by components.

What are the downfalls of React Server Components?

  • Streaming Complexity – Requires proper planning for handling dynamic content updates
  • Browser Compatibility – Limited support for legacy browsers
  • Code Maintenance – Heavier code monitoring and auditing required.
  • Learning Curve – This is still a new shift in paradigm; not all developers would be accustomed to it.

💡Why is RSC also called ‘Zero-Bundle React Server Components’?

Zero-Bundle RSC refers to eliminating the need to bundle React Server Components in the client-side JS bundle.

Why does this matter?

Doing so can reduce the initial bundle size and improve React performance significantly. The motivation behind zero-bundle RSC is to take full advantage of the server’s capabilities and serve them to the client. It also adds 0 Kb to the client’s bundle size.

Tabular Comparison between Client-Side vs Server-Side React vs React Server Component

Feature SSR CSR RSC
Initial Load Speed Fastest (pre-rendered HTML) Slow (requires browser to download JS) Fast (pre-rendered HTML with granular client-side activity)
Client-Side Interactivity Limited through Post-Hydration Full Control Granular Control through Client-Side Hydration
Browser Compatibility High High Poor
SEO Great Poor Great
Data Fetching on Server Yes No Yes
Accessibility Good Depends on Implementation Good
Load on the Server Moderate Light Moderate
Setup Complexity High Low High
Route-Handling Server-Side Routing Client-Side Routing Server-Side Routing
PWA Limited Support Full Support Limited Support
Caching Strategies Efficient Efficient Efficient
Initial HTML Size Large Small Small
Common Frameworks Next.js, Nuxt.js, Express CRA-based, Create-React-App Next.js

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

Hire ReactJS Developers

Next.js Framework Transition from SSR to RSC

React has been a client-side library from its inception. However, the team behind React is actively trying to shift some of its rendering processes to the backend. This is a monumental change as React is no longer just a client-facing UI library; server-side rendering means there needs to be a server. During May 2023, React introduced better support for React Server Components with React 18 and Next.js 13. React Server-Side Components will now be officially pre-configured for Next.js 13 and above versions.

What is Next.js, and Limitations of the SSR Approach?

Next.js is one of the most widely used server-side rendering frameworks for React. Since it is a server-side implementation, developers can pre-render pages to static HTML format using methods such as getInitialProps and getServerSideProps.

While this approach does work, it requires context switching between server and client-side components of the React app. This could result in hydration mismatches between the server-rendered HTML and client-rendered UI, resulting in bugs.

From a scalability point of view, scaling and maintaining performance became challenging as React apps built with Next.js started growing in size and traffic. All these requests went through the Node.js server, and there was no code sharing between client and server environments since they were written separately.

Introduction of RSC in Next.js and Benefits

As we discussed, Next.js 13 announced built-in support for React Server Components in their Next.JS 13.4 official document. One of the key benefits that makes React Server Component stand out from its predecessors is the unified programming model. The same component can run on the client or the server without context switching. 

Benefits of RSC over SSR for React

  • Developers don’t need to use getIntitialProps or getServerSideProps lifecycle methods for pre-rendering. RSC is capable of handling server rendering automatically.
  • Unified Programming – shared components can easily run on server and client platforms.
  • Individual components can run on the server, allowing granular adoption.
  • Isolated environments of React Server Components improve scaling potential.
  • Chances of Hydration Mismatches are reduced to zero.
  • Improved app bundle size since code is kept on the server.

React Server Components – How to Use Server Components and Client Components Together?

Your app will likely combine client and server components working together. Sticking strictly to the client side would result in slow first-page content loading and other performance issues. In contrast, an entirely server-side path leads to less interactivity or introducing heavy third-party integrations to achieve them.

To understand how to utilize Client Side React with Server Components React optimally, we need to clear a fundamental concept before moving forward.

  • Server components can import and render client components.
  • Client components cannot render server components in it.
  • You will have to pass the server component as a prop for using server components in the client component.

Hence, you should always have server components at the root of the component tree and the client components at the edges or leaf level. Server components can handle all data-fetching activities at the root, and client components can handle user interactions.

Use Case: Comparison of React Server Side Rendering to React Server Component for Real-Time Commenting System

Problem Statement: Let’s assume we are building a real-time commenting system for a blog or social media app. The users should be able to post comments, which should appear in real time for all viewers on that page.

SSR Approach to Real-Time Commenting System

The traditional SSR approach will ask the server to generate the initial HTML content. Real-time updates are usually implemented on the client-side JavaScript.

Let’s look at the code implementation with the SSR approach:

// CommentList.js
import React, { useEffect, useState } from 'react';
function CommentList() {
  const [comments, setComments] = useState([]);
  // Simulate real-time updates
  useEffect(() => {
    const socket = new WebSocket('ws://example.com/comments');
    socket.onmessage = (event) => {
      const newComment = JSON.parse(event.data);
      setComments((prevComments) => [...prevComments, newComment]);
    };
    return () => {
      socket.close();
    };
  }, []);
  return (
    <div>
      {comments.map((comment) => (
        <div key={comment.id}>{comment.text}</div>
      ))}
    </div>
  );
}
export default CommentList;

As you can tell from the code, we had to take the ‘CommentList’ component from client-side JavaScript functions – useEffect and useState to handle real-time updates. We also introduced web sockets to listen for new comments and append them to the list when we receive them.

Challenges with SSR Implementation

Here are the challenges of SSR implementations for fetching and displaying new comments with client-side dependency:

  1. Delayed Updates: Real-time updates could be delayed as the client would take time to establish a websocket connection and wait for new comments.
  2. SEO concerns and Initial Load: The initial page load content will come from server-generated HTML. Since comments are added via JavaScript on the client side, they won’t be visible to the search engine, which would impact SEO.
  3. Complexity: Implementing client-server communication and real-time updates using websockets can be complicated and could result in coarse code that is harder to maintain.

How is the RSC Implementation a Better Fix?

The best thing about React Server Components is that it isn’t intended to replace client- or server-side rendering. But to combine both advantages without bearing the significant trade-offs of sticking to one.

Keeping that in mind, for our real-time commenting system, React can use RSC to allow parts of the component tree to run on the server while maintaining real-time updates.

Let’s look at the code implementation with the RSC approach:

We will start by creating two separate files – CommentList.server.js and CommentList.client.js.

Create CommentList.server.js List

// CommentList.server.js
import React from 'react';
import { ServerDataContext, CommentServerContext } from './context';
function CommentList() {
  // Access server data and comments
  const serverData = React.useContext(ServerDataContext);
  const comments = React.useContext(CommentServerContext);
  // Render comments
  return (
    <div>
      {comments.map((comment) => (
        <div key={comment.id}>{comment.text}</div>
      ))}
    </div>
  );
}
export default CommentList;

Create CommentList.client.js List

// CommentList.client.js
import React from 'react';
import { CommentServerContext } from './context';
 
function CommentList() {
  // Use client context for real-time updates
  const [comments, setComments] = React.useContext(CommentServerContext);
  // Render comments
  return (
    <div>
      {comments.map((comment) => (
        <div key={comment.id}>{comment.text}</div>
      ))}
    </div>
  );
}
export default CommentList;

As discussed earlier, we can split the CommentList component into two files – CommentList.server.js and CommentList.client.js. We have now divided the code into client and server-side components.

Now, we can access server data and render the initial comments in the server components, which the search bots can crawl. This leads to improved React SEO while maintaining a faster initial loading time. In the client component, we can use client context to handle real-time updates without adding complexity or compromising on SEO.

Wrapping up!

React Server Components with Next.js is a step forward in the right direction. Remember, Server Components aren’t meant to replace client-side React or server-side React but to improve the communication between the two further, providing end users to gain the benefit of both, while reducing the trade-offs that came with following only server-side rendering or client-side rendering in React.

Cutting Costs but
NOT Cutting Quality

that’s how we roll! 🚀

Hire Web Developers

This post was last modified on December 18, 2023 11:36 am

Saurabh Barot: Saurabh Barot, the CTO at Aglowid IT Solutions, holds over a decade of experience in web, mobile, data engineering, Salesforce, and cloud computing. Renowned for his strategic vision and leadership, Saurabh excels in overseeing technology strategy, managing data infrastructure, and leading cross-functional teams to drive innovation. Starting with web and mobile application projects, his expertise extends to Big Data, ETL processes, CRM systems, and cloud infrastructure, making him a pivotal force in aligning technology initiatives with business goals and ensuring the company stays at the forefront of technological advancements.
Related Post