Understanding SSR with Hydration: Pros, Cons, and Scenarios for Software Architects

I'm currently experimenting with various frontend rendering and hydration techniques. While client-side rendering (CSR) with Angular(JS) and React was the recent trend, SSR is making a comeback.

Let's delve into SSR including client-side hydration with this blog post.

See also my previous blog post about frontend architecture 👇

Which web frontend architecture fits best?
This post will help you find the right web frontend architecture that best fits your specific quality goals.

Key Terminologies Explained

Before diving in, let's clarify some essential terms:

  • Rendering: Combining templates and data to create web content.
  • Hydration: Enhancing server-rendered HTML with client-side interactivity.

What is "Rendering" in Frontend?

In frontend development, "rendering" refers to the process of combining a template (markup) with data to generate the content for a web page or web app view. This essential step creates the visual representation that users view with on their browsers.

What is "Hydration" in Frontend?

"Hydration" is a technique associated with server-side rendering (SSR) and involves transforming a server-rendered HTML document into a fully interactive web application on the client side.

An initial server side rendered HTML file is not interactive yet. JavaScript code must be executed to attach event listeners, initialize state, and make the page dynamic. The process of adding this interactivity to the static HTML is called "hydration."

SSR with Hydration Architectural Overview

Let's explore the architectural overview of SSR (Server-Side Rendering) with Hydration in a frontend architecture. This approach is often referred to as isomorphic because the codebase can run both on the server and the client.

In this architecture, the initial rendering takes place on the server, typically using Node.js or a similar runtime. Here’s how it works:

The client (browser) requests the web app (1).

This request triggers the server to perform the initial rendering of the view. During this process, the server might fetch some data. The rendering to string on the server with React can be done as follows (2):

  const html = renderToString(
      <App />
  );

Rendering to string server side with React

The server then sends back the initial rendered static view along with the JavaScript bundle (usually a Single Page Application framework) and styling assets (3).

The client (browser) reads the static HTML and loads the JavaScript bundle.

With the JavaScript bundle loaded, the browser can 'hydrate' the web app on the client side. Hydration involves attaching event handlers to the existing DOM elements and restoring the application state (4).

Here’s an example of the hydration

import { hydrateRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

const domNode = document.getElementById('root');

hydrateRoot(
  domNode,
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

Through this process, the static HTML is transformed into a Single Page Application (SPA). This means that the DOM structure is reused, event handlers are attached to the DOM elements, and the application state is restored on the client. The web app are able to act as a SPA.

Optionally, the SPA can make additional HTTP requests and render the results on the client side (5).

In which scenario is SSR with hydration ideal?

💡
SEO Optimization: Ensures that the initial content is easily crawled and indexed by search engines, improving visibility and search ranking.

Fast Initial Load: Server-side rendering provides a fully-formed HTML document to the client, resulting in a quicker perceived load time.

Enhanced User Experience: Hydration enables rich interactivity and dynamic content updates, providing a seamless and engaging user experience.

Improved Performance: By offloading the initial rendering to the server, client devices, especially those with limited resources, can handle the application more efficiently.

Hydration improves application performance by avoiding extra work to re-create DOM nodes.

Instead, the corresponding web framework (like React or Angular) tries to match existing DOM elements to the applications structure at runtime and reuses DOM nodes when possible.

This results in a performance improvement that can be measured using Core Web Vitals (CWV) statistics, such as reducing the First Input Delay (FID) and Largest Contentful Paint (LCP), as well as Cumulative Layout Shift (CLS).

Improving these numbers also affects things like SEO performance.

Without hydration enabled, server-side rendered Angular applications will destroy and re-render the application's DOM, which may result in a visible UI flicker.

This re-rendering can negatively impact Core Web Vitals like LCP and cause a layout shift. Enabling hydration allows the existing DOM to be re-used and prevents a flicker.

For which scenarios is hydration ideal:

  • E-Commerce Web Apps
    • Product pages: These need to be indexed by search engines to be more visible and should load quickly to attract user attention. SSR can render the product details on the server side, and hydration can enable dynamic features such as adding to cart, product zoom and reviews.
    • Category pages: Categories or listings benefit from SSR for fast loading and SEO, while Hydration allows sorting, filtering and pagination without a full page reload.
  • Social media platforms
    • User Feeds: social media feeds benefit from SSR for fast initial loading and SEO of public content, while hydration enables live updates, interactive elements (like, comment, share) and infinite scrolling.
    • Profile pages: SSR can render the user profile and posts first for SEO and fast load times, while hydration allows dynamic content updates and interactions.
  • Content management systems (CMS)
    • Blog posts and pages: SSR can render blog posts server-side for fast load times and SEO, while hydration supports dynamic features such as comments, likes and content editing.
    • Landing pages: Marketing and informational landing pages can use SSR for fast load times and SEO, while hydration enables interactive elements such as forms, animations and dynamic content updates.
  • User dashboards and portals
    • Personalized dashboards: SSR can render the basic layout and static data on the server side for fast loading, while hydration handles dynamic data retrieval, real-time updates and interactive widgets.
    • Intranets and corporate portals: SSR can ensure fast loading times and SEO for public areas, while hydration enables interactive features such as internal messaging, notifications and data-driven applications.
  • Progressive web applications (PWAs):
    • Offline-first applications: SSR can render server-first content to ensure fast load times, while hydration manages offline features, caching and background refreshes.
    • Real-time data applications: SSR can handle initial application state rendering, while hydration manages real-time data updates, user interactions and dynamic content loading.
  • Complex forms and multi-stage processes
    • Registration and checkout flows: SSR can render the initial form or step on the server side to reduce load times, while hydration allows for validation, dynamic field updates and smooth transitions between steps without the need to reload the entire page.
    • Interactive surveys: SSR can render the initial survey layout server-side, while hydration manages dynamic question loading, validation of user input and progress tracking.

In which scenario is SSR with hydration not useful?

Hydration can lead to these disadvantages:

Increased complexity: SSR with hydration leads to additional complexity in terms of state management, synchronization between server and client, and handling edge cases. This can lead to higher development and maintenance costs.

Additional performance overhead: The process of hydrating the HTML rendered by the server can lead to performance degradation, especially on slower networks or less powerful devices. This can negate some of the initial load time benefits of SSR.

Complex development and debugging: Troubleshooting issues caused by inconsistencies between the server-rendered HTML and client-side JavaScript can be difficult. Developers need to be proficient in both server-side and client-side technologies, which increases the learning curve and the risk of errors.

Resource management: A robust infrastructure is required to ensure that the server can handle the load of rendering HTML for each request.

SSR with hydration may not be useful for the following use cases:

  • Highly interactive single-page applications (SPAs):
    • Real-time collaboration tools: Applications such as collaborative editing tools (e.g. Google Docs) require frequent real-time updates and strong client-side interactivity. Client-side rendering (CSR) is often more efficient when it comes to synchronizing data in real time and performing user interactions without the overhead of SSR.
    • Games and graphical applications: Online games or applications that rely heavily on WebGL or other client-side graphics libraries are better suited for CSR. The initial load benefits of SSR are less impactful compared to the continuous interactivity and performance required during gameplay.
  • Websites with static content:
    • Static blogs and documentation sites: For content that does not change frequently, Static Site Generation (SSG) is more efficient. SSG generates static HTML files during the build process that are provided directly to the user, eliminating server-side rendering and hydration for each request.
    • Marketing landing pages: Pages that consist mainly of static content and do not need to be updated frequently can benefit from SSG. This ensures fast loading times, excellent SEO and less complexity than SSR with hydration.
  • Simple websites without dynamic interactivity:
    • Simple corporate websites: Simple corporate websites that display static information such as company profiles, contact details and service descriptions can use SSG or even simple static HTML/CSS without needing the complexity of SSR and hydration.
    • Portfolio websites: Personal or professional portfolios that display static content, images and project descriptions are better served with SSG as it offers fast load times and simplicity.
  • Resource-constrained environments:
    • Networks with low bandwidth: In environments with slow internet connections, the extra JavaScript needed for hydration can be a bottleneck. SSG with minimal JavaScript might be a better approach.
    • Low-performance devices: Devices with limited CPU and memory capacity may struggle with the overhead of hydration. SSG or CSR with optimized, lightweight frameworks can provide a better user experience.
  • Applications with minimal SEO requirements:
    • Internal tools and dashboards: Applications for internal use where SEO is not an issue can utilize CSR for faster development cycles and simpler architectures. For internal dashboards and tools, client-side performance and interactivity often take precedence over initial load times and SEO.
    • Platforms that are only accessible to authenticated users: Platforms where all or most content is behind authentication (e.g. SaaS applications) benefit more from CSR as SEO is not relevant and initial server-side rendering is unnecessarily complex.
  • Fast development cycles and simplicity:
    • Prototyping and MVPs: For projects in the prototyping phase or Minimum Viable Products (MVPs), the simplicity and speed of CSR can accelerate development. The introduction of SSR with hydration adds complexity that may not be necessary in the early stages.
    • Small development teams: Teams with limited resources and expertise may prefer CSR, SSR or SSG to avoid the additional complexity and maintenance associated with SSR and hydration.

Example App

To show how SSR works with Hydration under the hood, I have created a small React / expressjs sample project 👇

GitHub - bitsmuggler/react-simple-ssr-hydration-example
Contribute to bitsmuggler/react-simple-ssr-hydration-example development by creating an account on GitHub.