DEV Community

Cover image for From PreReact to React and Next.js A Journey Through Web Rendering and Performance Optimization
Anas Mustafa
Anas Mustafa

Posted on

From PreReact to React and Next.js A Journey Through Web Rendering and Performance Optimization

In this article, we'll explore the origin of React, what problems it solves, and

why Next.js was created. While it's widely known that Next.js offers SSR (server-side rendering), we'll dive deeper into what SSR truly is and why it might be better than CSR (client-side rendering) in certain cases.

A Brief History: Before React.js

Before React.js popularized the concept of CSR (client-side rendering), most applications followed the traditional MPA (multi-page application) model. In MPAs, the server handled the rendering of HTML, a process that we will see had both advantages and drawbacks.

before_react

As we can see, rendering the page was simple. You send a request to the server, it takes some time to set up the necessary HTML, sends it back, and yay the page is loaded.

So, what's the problem? At this stage, there isn't one. In fact, this approach can seem more efficient than how React.js handles page loading—at least initially. However, the problem arises when users start interacting with the page. Let's walk through a hypothetical scenario:

  • You enter a page.
  • You log in (client -> server (for authentication) -> DB (check for user)) and back. No problem here.
  • You navigate to, say, the posts page (client -> server -> DB (get posts)) and back with the post data. No problem here.
  • Create a new post (client -> server (with new post) -> DB (add new post)) and back with a completely new HTML. Here’s where the problem arises. When you add a new post—or make any changes to the page—the server needs to re-render the entire HTML from scratch. This results in a full page re-render, which can be inefficient. This full re-render occurs anytime you update or change anything on the page.

that's was what react was trying to fix

react_spa_csr

Now Enter React.js

How did React fix the problem?

React introduced the revolutionary concept of client-side rendering (CSR). Instead of rendering the HTML on the server, CSR renders it on the client’s browser.
But how does this work?, given that when you first load the page, the server still has to serve HTML?

Here’s what happens: the server sends an initial HTML skeleton, but it doesn’t contain the actual content. Instead, it includes a <script> tag that links to the bundled JavaScript code. When the HTML is loaded—which happens quickly since it’s mostly empty—React takes over, rendering the actual content on the client. However, the content isn’t immediately available. React first has to make a separate request to the server to fetch the necessary data. Only after this process is complete will you see the full page.

react_spa_csr

As you can see, it’s a bit more complex than traditional server-side rendering (SSR) in multi-page applications (MPAs). In fact, it might seem slower initially because it requires multiple round trips to the server—first for the HTML skeleton, then for the JavaScript file, and finally for the data. This is one of the trade-offs React accepted for tthe magic that comes next.

Now, let’s return to the step where the browser loads the JavaScript from the <script> tag in the initial HTML. What React actually does is create a virtual copy of the DOM, known as the Virtual DOM (VDOM). React uses this VDOM to efficiently track changes. Instead of re-rendering the entire HTML page from the server every time something changes, React uses a process called reconciliation.

Reconciliation:

React compares the current state of the DOM with its virtual counterpart to pinpoint exactly where the changes occurred. It then updates only the parts of the DOM that have changed, instead of reloading the entire page.

Reconciliation

Now, that's amazing! React has solved the problem by allowing you to track changes in the DOM and only update the parts that have changed—all on the client side—without needing to make multiple trips to the server.

However, this solution comes with some trade-offs:

  1. Client-side resource usage: The client’s computer is now responsible for rendering the HTML, creating the Virtual DOM, and handling the reconciliation process. This can be time-consuming, especially with large tree structures.

  2. Limited visibility for bots and crawlers: Bots and crawlers—such as those from Facebook, X (formerly Twitter), or Instagram—may have difficulty parsing content in pure client-side rendered applications. This occurs because these bots typically don't execute JavaScript, meaning they can only see the initial HTML that the server sends, which is often blank or minimally populated. This can impact SEO or social media sharing if the content relies heavily on client-side rendering.

spa_webtracker scope

The key challenge here is balancing client-side interactivity and server-side efficiency. Suppose we could return to having the server render the initial HTML (complete with the necessary data) while still leveraging React’s reconciliation and virtual DOM features for client-side updates. In that case, we’d have the best of both worlds.

If only there were a framework...

Now Enter Next.js

This is where Server-Side Rendering (SSR) and frameworks like Next.js come into play. Next.js allows developers to render pages on the server first, ensuring the initial HTML includes all the data the user needs, improving performance and SEO. After this initial server-rendered page is sent to the client, you get the full HTML content, but the page is not interactive yet—React hasn’t been loaded. Once the JavaScript loads, React undergoes a hydration process.

Hydration is when React takes over the pre-rendered HTML on the client-side, enabling smooth interactions and updates through React’s Virtual DOM and reconciliation process.

next_ssr

Top comments (0)