Hi folks, welcome to my new series on NextJS.
In this article, let’s discuss about Client-side Rendering (CSR) and Server-Side Rendering (SSR) and the process of Hydration.
These concepts are the fundamental knowledge you must know to be great NextJS developer.
Without further ado. Let’s get started.
Client Side Rendering 🖥️
👉 HTML is rendered on the CLIENT (the user’s Computer)
👎 Slower initial page loads
Bigger JavaScript bundle needs to be downloaded before the app starts running
Data is fetched AFTER the components mount
👍 Highly Interactive: All the code and content has already been loaded (except data)
👎 SEO can be problematic
👍 Suitable for SPAs: Perfect for building highly interactive web apps.
👉 Apps that don’t need SEO:
Apps that are used “internally” as tools inside companies
Apps that are entirely hidden behind a login.
Server Side Rendering ⚙️
👉 HTML is rendered on the SERVER (the developer’s Computer)
👍 Faster initial page loads:
Less JavaScript needs to be downloaded and executed
Data is fetched before HTML is rendered
👎 LESS Interactive: Pages might be downloaded on demand and require full-page reloads.
👍 SEO-friendly: Content is easier for search engines to index.
👉 Suitable for Content-driven websites or apps where SEO is essential: E-commerce, blogs, news, marketing website, etc.
Two Types of SSR
Static: HTML generated at BUILD time (often called Static Site Generation or SSG)
Dynamic: HTML is generated each time the SERVER receives a new request. Some people only consider this as true SSR.
Typical Timeline of CSR and SSR with Data Fetching
CSR
First, we gonna have some interaction between the client and the server, when a client requests a page, all the server has to offer is an empty page. This empty page can be quite heavy, cause it’ll contain the ENTIRE app logic
After the JS has finally been downloaded and executed, the app notice, that it has to fetch some data.
We render a quick
Spin
, and the user waits for the data to be fetched from the server. For instance, from API endpoints.At some point, the data will arrive, and the Client application will re-render itself with NEW DATA
At this point we can say, we have our intial page load (LCP - Largest Contentful Paint), it’s the time it takes for the page to show all the relevant content to the user.
By the way, you can check out my article on Web Performance here as a reference.
There’s also a First-Contentful Paint (First Paint). No matter what it is. In this case, it’s the time when user see the
Spin
SSR
When the request from the client comes in, the server starts by fetching all relevant data for the page.
The server takes the data, renders the page, and then sends the WHOLE finished product to the client.
When the page reaches the Client, it already HAS ALL THE CONTENT that User is interested in. This is when FCP and LCP happens in this case, way faster and earlier. ⚡️
Key Takeaways from SSR
In SSR, the SERVER will initiate the Data fetching BEFORE the page (app) is even rendered on the client.
The
RENDER app with data
part move from the Client to the ServerWith all of this, the LCP and FCP typically happen much much faster and earlier than CSR. That makes SSR so useful in content-heavy sites, where users don’t want to wait for all content to appear.
What about Interactivity?
Turns out, in SSR, when the server sends back the page (HTML, CSS, JS), it will still have a JS bundle, this bundle is downloaded and executed just like in CSR
Afterward, we have the process of Hydration happen.
Hydration is the process where Static HTML becomes interactive by adding JS to it.
WHAT IS HYDRATION?
Let’s say we have a React app, with a React Component Tree that we want to render on the Server.
This app is typically written in Nextjs.
Using NextJS, we rendered our app as Server-side Rendered HTML markup. (Over-simplification)
Then this HTML will be sent to the Client. And rendered on the browser as a webpage. At this point we have LCP.
But, the website resulting from our initial React app is NOT INTERACTIVE.
It does not work like the normal Client React app. It’s just HTML.
👉 That’s where the process of HYDRATION Comes into the play!
👉 Hydration will add back the interactivity and event handlers that were LOST when HTML was server-side rendered.
👉 Rendering HTML on the SERVER will remove ALL the interactivity from React app, it just generated ONLY the MARKUP itself. That’s why we need Hydration
👉 Like watering the “dry” HTML with the “water of interactivity and event handlers”, the idea is to make the render to webpage work EXACTLY like the React app that we started with.
Let’s dig a bit deeper.
The HTML page we got on the Client will ALSO download the React bundle from our initial React app (on the server)
This bundle (JS bundle) then HYDRATE the rendered static DOM of our web page
In this process, React will build back the component tree on the Client and then COMPARE it to the actual Server-side rendered DOM that’s currently on the page. They MUST be the same, so React can adopt it.
If matches, React will simply adopt the existing DOM, attach all the event handlers, and fire off existing effects.
Instead of creating brand new DOM, which can take a very long time, React attempts to re-use the existing DOM. In other words, Hydration tries to finishes the process of SSR
Ultimately, we have the exact same React app, but now, on the Client. Then the Page becomes Interactive.
Common Hydration Error
Incorrect HTML element nesting.
Different data used for rendering on Client and Server.
Using browser-only APIs on server.
Side effects,…
That’s it for this article. Thanks for reading.
Reference Source: Jonas Schmedtmann