tl;dr
There is a huge discussion about Server-Side Rendering these days. Everyone says It’s hard to implement and maintain. I have created a React News web application with 3 different approaches to be able to understand performance and implementation differences between each other. I wanted to make this application as close as possible to a real-world use case. I used; React, React-Router, Redux, Node.js, and Express. You can check each application from the links below;
- Single Page Application bit.ly/spa-react
- Server-Side Rendering (Universal) bit.ly/ssr-react
- Server-Side Rendering with Redis bit.ly/ssr-cached
WHY?
I saw a lot of discussions online especially on Twitter also at the conferences about Server-side rendering. I know there are a lot of universal rendering frameworks for React but I wanted to build it by myself from scratch without any black-box solution. But first It’s good to understand what is server-side and client-side rendering is.
Javascript Revolution
Browsers are more powerful than 5–10 years ago. We started to create entire websites and web apps with client-side JavaScript. We started to call this method “Single Page Application”. This leads us to create more interactive real-time updated web applications.
But there is a problem with this approach, our initial HTML no longer contains all the data related to that URL.
Google and Social Media crawlers are not happy with this at all
What is Client Side Rendering? (CSR)
Rendering an app in a browser, generally using the DOM
The initial HTML rendered by the server is a placeholder and the entire user interface and data rendered in the browser once all your scripts load.
How Client-Side Rendering works?
A general overview of how Client-Side Rendering works
PROS
- Rich site interactions
- Fast rendering after the initial load
- Partial real-time updates
- Cheaper to host & scale
CONS
- SEO and index issues
- Mostly initial bundle.js load duration
- Performance issues on old mobile devices/slow networks
- Social Media crawlers and sharing problems (SMO)
What is Server Side Rendering? (SSR)
Server rendering generates the full HTML for a page on the server in response to navigation.
For our use case with React or with any other Javascript library/framework; Server-side rendering is a technique for rendering a normally client-side only single page app (SPA) on the server and then sending a fully rendered page to the browser.
How Server-side Rendering works?
A general overview of how Server-Side Rendering works
PROS
- Consistent SEO
- Performance, initial page load
- Works well with Social Media crawlers and platforms (SMO)
CONS
- Frequent requests
- Slow page rendering (TTFB — Time to first byte)
- Complex architecture (For universal approach)
How Google indexes?
We mentioned about SEO problems of Single Page Javascript Applications. It’s important to understand how Google index system works to solve this problem with Server-side Rendering.
At Google I/O 2018 JavaScript session, John Mueller and Tom Greenaway gave some clarity on how the search engine indexes JavaScript. We learned that there are two waves of indexing, and this is how they work:
Google’s 2 wave indexing system
How to SSR?
We have talked about almost all theoretical parts. Let’s focus on the implementation part and how we are going to achieve Server-side Rendering with React.
Methodology
- Initial render on the server
- Show fully formed HTML
- JS executions
- React takes over / re-render
Challenges
- JSX on Node.js
- Redux on server
- Routing
- Rehydration
Rehydration
“Booting up” JavaScript views on the client such that they reuse the server-rendered HTML’s DOM tree and data.
Rehydration Image Source
News Web Application with React
I have created a News application with React based on News API with 3 different approaches. I created my custom implementation to understand how it works under the hood. Custom webpack configurations can be tricky with Create-React-App.
Single Page Application (Yellow)
Classic single page application.
Demo: bit.ly/spa-react
Repo: bit.ly/spa-repo
Server-Side Rendering — Universal (Red)
Initial render happens on the server (Node.js / Express). After first render and bundle.js load, React rehydrates and takes over the application. This means that each click after the first load will be handled by React-Router and it will work like a Single-page application. If you check the source code you will see the complete dom-tree with all data in it. If you refresh the same page or press enter on the URL bar, the current page will be handled by the server.
Demo: bit.ly/ssr-react
Repo: bit.ly/ssr-repo
Server-Side Rendering with Redis (Blue)
Works almost the same with Server-side version. I tried to cache HTML result just before sending to browser to see performance improvements. So the first response from a server will be cached at Redis for a certain URL, the second response will come from memory. To test this actually you can enter a URL, copy that URL and visit again on incognito or another browser.
Demo: bit.ly/ssr-cached
Performance Comparisons
First of all, I wanted to check if Google would be able to index my universal application. As you can see below, it was able to see all the page content without any problem. This also means that Social media crawlers also can crawl my page content without a problem.
Google Search Console index check for Server-Side Rendering
My second test was about performance. I did a couple of performance tests with Lighthouse tool and WepageTest.
Desktop Load Comparison
We can see how SSR shines under slow network conditions in the video below.
Mobile comparison on Moto G4 — Chrome — Slow Network
Lighthouse Tests
Single Page Application — Lighthouse result
Server-Side Rendering Application — Lighthouse result
Results Comparison
Keep in mind, all these tests happened without a heavy load. So in the real world circumstances, results may change.
Conclusion
I really enjoyed and learned a lot while developing these applications. I didn’t mention a lot about the code part but all you can check implementations on the GitHub repos. I should mention that these implementations are just for proof-of-concept so far from production quality.
So far I can say that Server-Side Rendering is not a magic implementation. It’s important to check if your business really needs it or not. You can see my opinionated decide list below.
When to use Single-Page Applications?
- Rich site interactions
- The network is fast
- Minimal server recourses
- Main scripts are small or lazy loaded/split
- Real-time / partial updates
When to use Server-Side Rendering (Universal)?
- SEO is important
- The network is slow
- Enough server recourses
- Main scripts are large and loads slowly
- Social sharing is important
Further Reading
Rendering on the Web | Web | Google Developers