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
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.
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
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.
- Rich site interactions
- Fast rendering after the initial load
- Partial real-time updates
- Cheaper to host & scale
- 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)
Server rendering generates the full HTML for a page on the server in response to navigation.
- Consistent SEO
- Performance, initial page load
- Works well with Social Media crawlers and platforms (SMO)
- Frequent requests
- Slow page rendering (TTFB — Time to first byte)
- Complex architecture (For universal approach)
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.
- Initial render on the server
- Show fully formed HTML
- JS executions
- React takes over / re-render
- JSX on Node.js
- Redux on server
Rehydration Image Source
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.
Classic single page application.
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.
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.
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
Single Page Application — Lighthouse result
Server-Side Rendering Application — Lighthouse result
Keep in mind, all these tests happened without a heavy load. So in the real world circumstances, results may change.
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.
- Rich site interactions
- The network is fast
- Minimal server recourses
- Main scripts are small or lazy loaded/split
- Real-time / partial updates
- SEO is important
- The network is slow
- Enough server recourses
- Main scripts are large and loads slowly
- Social sharing is important