Understanding the Evolution: SSR vs. React Server Components in React 19

The Frontend Dev
4 min readDec 25, 2024

--

With the release of React 19, the conversation around server-side rendering (SSR) has taken a compelling turn, thanks to the enhanced capabilities of React Server Components (RSC). While SSR has long been a cornerstone of optimizing web performance and delivering dynamic content efficiently, RSC introduces a new paradigm that redefines how developers approach server-rendered React applications.

In this blog post, we’ll break down the core differences between these two technologies, highlighting their unique use cases, advantages, and how React 19’s updates make RSC a powerful tool for modern web development. Whether you’re looking to optimize SEO, enhance performance, or streamline user experiences, understanding the distinction between SSR and RSC is key to choosing the right approach for your next project.

The key difference between Server-Side Rendering (SSR) and React Server Components (RSC) lies in how they handle rendering, the client-server interaction, and the nature of their output. Both are powerful tools in React 19, but they serve different purposes.

What is SSR?

SSR (Server-Side Rendering) generates HTML for the entire page on the server for every request. The client receives the fully-rendered HTML, and React hydrates it to add interactivity.

HTML content of the entire page is sent to client after the entire page is rendered Server side, to which React adds interactivity (i.e. Hydration) for users to interact with the page elements.

Characteristics of SSR:

  • Client Hydration: React adds interactivity to the static HTML by attaching event listeners.
  • Full Page Rendering: The entire page is rendered server-side.
  • Data Fetching: Requires all data to be fetched before sending HTML to the client.

Example of SSR:

Using Next.js with SSR:

// pages/index.js
export async function getServerSideProps() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();

return {
props: { data }, // Pass data as props
};
}

export default function Home({ data }) {
return (
<div>
<h1>SSR Example</h1>
<ul>
{data.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
}

How SSR Works:

  1. A request is sent to the server.
  2. The server fetches data and renders the entire page to HTML.
  3. HTML is sent to the client.
  4. React hydrates the page to enable interactivity.

What is RSC?

React Server Components (RSC) allow rendering parts of the React component tree on the server, sending serialized output to the client. Unlike SSR, RSC doesn’t need hydration because the rendered parts are static and do not include client-side JavaScript.

Component A’s content is loaded on UI, while Component B’s HTML content is streamed to the client as soon as its content is completed rendering Server side.

Characteristics of RSC:

  • No Client Hydration: Server-rendered components don’t include JavaScript for interactivity.
  • Partial Tree Rendering: Only specific components are rendered server-side.
  • Streaming Updates: Content can be streamed to the client incrementally.

Streaming — a quick guide

This article from Next.js talks in detail about what Streaming is and more about what are the limitations of SSR.

These steps are sequential and blocking, meaning the server can only render the HTML for a page once all the data has been fetched. And, on the client, React can only hydrate the UI once the code for all components in the page has been downloaded. Source: Next.js

Example of RSC:

Using React 19 with a mix of Server and Client Components:

// Server Component: Greeting.server.js
export default function Greeting({ name }) {
return <h1>Hello, {name} from the server!</h1>; // Runs on the server
}

// Client Component: Counter.client.js
'use client';
import { useState } from 'react';

export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}

// App Component: App.js
import Greeting from './Greeting.server';
import Counter from './Counter.client';

export default function App() {
return (
<div>
<Greeting name="John" />
<Counter />
</div>
);
}

How RSC Works:

  1. Server-rendered components like Greeting are executed on the server.
  2. The server streams the rendered HTML and serialized data to the client.
  3. Client components like Counter are hydrated and made interactive.

Comparison: SSR vs RSC

When to Use Each?

Use SSR when:

  • You need SEO optimization for dynamic pages.
  • You want the entire page rendered with complete interactivity.
  • Content is highly dynamic and changes with every request.

Use RSC when:

  • You want to optimize performance by offloading heavy computation to the server.
  • Certain parts of the UI don’t require interactivity (e.g., static content like blogs or product details).
  • You aim to reduce JavaScript on the client for faster load times.

Want to read more about how Hydration and Streaming work alongside these concepts of SSR and RSC, I wrote a small article about it too!

Sign up to discover human stories that deepen your understanding of the world.

--

--

The Frontend Dev
The Frontend Dev

Written by The Frontend Dev

Hi 👋, I am Shishir. 🔮 Curious Frontend Dev 🎨 Passionate about interactive UX 🎮 Loves gaming & keeping up with dev trends 🏓 Open to collaborations

No responses yet

Write a response