May 24, 20253 minute(s)

Rendering Patterns for Web Apps

Rendering is the process of transforming the component code (HTML, CSS and JavaScript) you write into user interfaces (UIs) that user sees and interacts with.

article-banner-image

Client-Side Rendering (CSR)


When a client (such as a browser) requests a website, the server responds with a single HTML page along with static assets like CSS and JavaScript. This page is quite barebones -- typically just a simple div tag and a reference to a JavaScript file.


The logic, templating, data fetching, and routing needed to display content on the page are handled by the JavaScript running on the client side. This whole approach, where the browser transforms JavaScript code into the user interface, is known as Client-Side Rendering (CSR).


client-side-rendering-example


Pros and Cons of CSR

  1. Improved User Experience: CSR enables single-page applications that support navigation without page refreshes. Dynamic content updates and interactions happen directly in the browser, resulting in a faster and smoother user experience.

  2. Reduced Server Load: CSR reduces server load by requiring the server to send only minimal HTML and static assets, offloading the rendering process to the client's browser. This reduction in server demand makes it easier to scale applications with high traffic.

Despite the great interactive experience that it provides, there are a few drawbacks to CSR.

  1. SEO Limitations: In Client-Side Rendering (CSR), the content is rendered using JavaScript in the browser, which can cause issues for search engines that struggle to crawl and index JavaScript-heavy pages effectively. As a result, important content may not be indexed properly, leading to poor search engine visibility and lower rankings.

  2. Performance Issues and UX: Users may experience slow initial page load times because the browser must first download, parse, and execute JavaScript before rendering any meaningful content. This delay can negatively impact the user experience, especially on slower networks or less powerful devices.

Server-Side Solutions


To overcome the drawbacks of CSR, modern web frameworks like Gatsby and NextJS have introduced server-side solutions. When a request comes from the client, instead of sending a barebones HTML file, the server renders the complete HTML. This fully formed HTML document is then sent to the browser, along with a reference to a JavaScript file that makes the UI interactive and adds client-side functionality such as button clicks and scroll events (hydration).


Since the HTML is already generated on the server, the browser can quickly parse and display it, resulting in a faster initial page load time.


What is Hydration?

Hydration is when client-side JavaScript takes control in the browser and reconstructs the component tree in memory using the server-rendered HTML as a blueprint. It carefully maps out where the interactive elements should go and then hooks up the JavaScript logic. This involves initializing the application state, adding click and mouse events, and setting up the dynamic features needed for a fully interactive user experience.


Server-side solutions can be categorized into two main techniques:

  1. Static Site Generation (SSG)
  2. Server-Side Rendering (SSR)

Static Site Generation


Static Site Generation (SSG) happens at build time when you deploy your application to the server. This results in pages that are already pre-rendered and ready to be served as static files (HTML, CSS and JavaScript). It's ideal for websites where the content remains relatively stable, such as landing pages, marketing websites and blogs.


Server-Side Rendering


Server-Side Rendering (SSR), on the other hand, renders pages on demand when a user requests them. It's ideal for websites where content needs to be personalized based on the user -- such as social media platforms, where the HTML changes depending on who is logged in.


For example, imagine a user visiting a social media website like Twitter. When the user types the URL and hits enter, the browser sends a request to the server. The server detects the user’s authentication (via cookies or session tokens), fetches their personalized data -- such as their feed, notifications, and profile information -- and then renders a complete HTML page with that data already embedded. This fully-formed HTML is sent back to the browser, so the user sees their timeline almost immediately. Once the HTML is displayed, the JavaScript bundle is loaded in the background to "hydrate" the page, allowing it to become interactive -- enabling likes, comments, retweets, and other dynamic features to work seamlessly.


server-side-rendering-example


Pros and Cons of SSR

  1. Improved SEO: SSR renders fully populated HTML on the server and sends it to the browser. This means search engine crawlers can immediately index meaningful content without relying on JavaScript execution.

  2. Better First Contentful Paint (FCP): SSR enables content to be visible faster, as HTML is rendered and delivered immediately. The browser doesn't need to wait for JavaScript to load and execute before showing meaningful content, resulting in a quicker First Contentful Paint.

SSR can be thought of as an "all-or-nothing" waterfall because the rendering process is tightly coupled and sequential—each step must be completed before the next one begins

  1. You have to fetch everything before you can show anything: In Server-Side Rendering (SSR), all necessary data must be fetched before the server can render and send the page to the client. If a component requires data from a database or API, this fetching must be completed first. As a result, the server response is delayed because it cannot begin rendering or sending any part of the page until all data is available.

  2. You have to load everything before you can hydrate anything: For successful hydration, the component tree rendered in the browser must exactly match the one generated on the server. This requires that all the JavaScript for the components be fully loaded in the browser before hydration can begin.

  3. You have to hydrate everything before you can interact with anything: React performs hydration in a single pass, meaning it must hydrate the entire component tree before any user interaction becomes functional. This can introduce delays in interactivity, especially for large pages with many components.


Suspense SSR


To address the "all-or-nothing" waterfall effect React 18 introduced the suspense SSR architecture. It allows us to use the Suspense component to unlock 2 major SSR features:

  1. HTML streaming on the server
  2. Selective hydration on the client

HTML Streaming on the Server


Instead of generating one large HTML file containing the necessary markup for the current navigation, we can split it up into smaller chunks! Node streams allow us to stream data into the response object, which means that we can continuously send data down to the client. The moment the client receives the chunks of data, it can start rendering the contents.


Selective Hydration on the Client


Even with faster HTML delivery we cannot start hydrating until we have loaded all JavaScript for that page. If that's a big chunk of code we will still keep users waiting from being able to interact with the webpage.


By wrapping parts of our application with Suspense component, you're not just enabling streaming but telling React that -- it's okay to hydrate other parts of the page before everything is ready. This is what we call as selective hydration.


It allows hydration of parts of the page as they become available even before rest of the HTML and JavaScript are fully downloaded.


Resources


Here are few resources that were used as reference for the content and images featured in this article: