Originally posted by Jakub Klimek on Altalogy blog
History of the rendering solution
Since the dawn of the web history, the only way to get your website on the screen was by using SSR. You had to upload your HTML & styles to the server, it compiled everything, and then you were ready to browse with fully populated HTML.
However, these were times where the pages mainly contained pictures and text, like the first website in history βΒ http://info.cern.ch/, which looks like this:
Quickly jumping to nowadays, there's no longer the case. Current sites are closer to web applications like facebook, twitter, or eBay. The world of the web has grown and become more demanding. The needs of users have increased, people want to send messages, get it in real-time, watch videos, have more interaction with the website. Developers have started to render websites on the client-side using frameworks like angular, backbone, ember, react.js e.t.c.
If you are asking yourself which method is better, CSR or SSR - first of all, you have to ask yourself - what do you want to build or achieve?
- Learn React?
- Create a Single Page App?
- Want to build the frontend for a new web application?
- Build a website is mostly static?
On this choice, it depends on what you should decide on.
Background
Whenever you open a website, your browser makes a request to the server to get the content of the web - HTML, assets, styles, and the rest of the data.
Request and response speed depends on a few things:
- your internet connection speed
- distance between you and the server
- CDN optimization
- how many users are trying to open your site in one moment
- how the website is optimized to be loaded
When the webpage is loaded, it can either be rendered in the browser (client-side rendering) or on the server (server-side rendering). Each is slightly different and has its pros and cons.
Client-Side Rendering
What is client-side rendering?
With a client-side rendering solution, when the user opens your website, his browser makes a request to the server, and the user gets a response with a single HTML file without any content, loading screen, e.t.c. It's a blank page until the browser fetches all linked JavaScripts and lets the browser compile everything before rendering the content.
Client-side rendering pros:
- Fast render after initial load
- Faster navigation
- Lower server load
- Remarkable for web apps
Client-side rendering cons:
- slower initial load
- unpredictable performance - you never know if your user will open and 'compile' your website on a mobile device with a very slow internet connection or not updated browser
- Client-side routing solutions can delay web crawling.
- SEO - if you not implemented correctly
- Initial req loads the page, CSS, layout, js,
- some or all content is not included
Server-side rendering
What is server-side rendering?
As I mentioned above, - SSR is not a new concept. It has been used since the first backend solution, like PHP or JAVA. Server-side rendering is a method to render your website. When the user opens your page, his browser makes a request to the server, and the server generates ready to provide HTML.
Server-side rendering pros:
- SEO friendly - SSR guarantees your pages are easily indexable by search engines
- Better performance for the user - User will see the content faster
- Social Media Optimization: When people try to post your link on Facebook, Twitter, etc. then a nice preview will show up with the page title, description, and image.
- Shared code with backend node
- User-machine is less busy
- Best for static sites
Server-side rendering cons:
- TTFB (Time to first byte) is slower; your server has to spend some time to prepare HTML for your page instead of sending almost empty HTML doc with link to javascript
- The server will be busier, can execute fewer request per second
- HTML doc will be bigger
- The page is viewable sooner, but it's not interactive and the beginning, a user has to wait until react will be done executing
- Full page reload after routes change
Example page
To make a comparison of these two methods, let's use a very simple website with one image.
Client-side rendering - code example
Bellow you can check example HTML served to the user in the react application (create-react-app). As you can see there is no image yet, only simple HTML with linked js files.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<title>React App</title>
<link href="/static/css/main.64d7c8c6.chunk.css" rel="stylesheet">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/static/js/2.1cca17c9.chunk.js"></script>
<script src="/static/js/main.234a2bc6.chunk.js"></script>
</body>
</html>
Server-side rendering - code example
Bellow you can check our example website on next.js. As you can see, the main difference is that we already have HTML with image, ready to render.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
<meta charSet="utf-8" />
<title class="jsx-3505738252">Home</title>
<link rel="icon" href="/favicon.ico" class="jsx-3505738252" />
<meta name="next-head-count" content="4" />
<link rel="preload" href="/_next/static/6AZVKi7KqSIP8pz3uCg0R/pages/index.js" as="script" />
<link rel="preload" href="/_next/static/6AZVKi7KqSIP8pz3uCg0R/pages/_app.js" as="script" />
<link rel="preload" href="/_next/static/runtime/webpack-035ac2b14bde147cb4a8.js" as="script" />
<link rel="preload" href="/_next/static/chunks/commons.4a179d4644f468f50fbf.js" as="script" />
<link rel="preload" href="/_next/static/runtime/main-6bef3842d6b2422a0213.js" as="script" />
</head>
<body>
<div id="__next">
<div class="jsx-3505738252">
<div class="jsx-3505738252"><img cassName="img" src="/header.png" class="jsx-3505738252" /></div>
</div>
</div>
<script id="__NEXT_DATA__" type="application/json">{"dataManager":"[]","props":{"pageProps":{}},"page":"/","query":{},"buildId":"6AZVKi7KqSIP8pz3uCg0R","nextExport":true,"autoExport":true}</script>
<script async="" data-next-page="/" src="/_next/static/6AZVKi7KqSIP8pz3uCg0R/pages/index.js"></script>
<script async="" data-next-page="/_app" src="/_next/static/6AZVKi7KqSIP8pz3uCg0R/pages/_app.js"></script>
<script src="/_next/static/runtime/webpack-035ac2b14bde147cb4a8.js" async=""></script>
<script src="/_next/static/chunks/commons.4a179d4644f468f50fbf.js" async=""></script>
<script src="/_next/static/runtime/main-6bef3842d6b2422a0213.js" async=""></script>
</body>
</html>
Performance
To understand a nomenclature of the all graphs bellow I will use this image as an explanation, thanks to Google: https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#user-centric_performance_metrics
CSR performance
- Simulated Slow 4G, 4x CPU slowdown
- No throttling
SSR performance
- Simulated Slow 4G, 4x CPU slowdown
- No throttling
Conclusions
- both apps become viewable and interactable after 1-1,5 seconds, in this simple example SSR is a little bit faster
- in server-side-rendering user will get HTML rendered much faster than in client-side-rendering
- in client-side-rendering, non-content can be displayed until browser will download all the js files
- DOM Content is loaded much faster in SSR than in CSR; in client-side-rendering, you have to wait to download js
- first Contentful Paint is also faster at SSR
- a blank page is much longer on client-side-rendering, as a developer you have to avoid it using some loader, or loading screen
- image is faster available with SSR compared to CSR, because when using CSR the images cannot be downloaded before linked js files, HTML is not ready,
What should I use?
If you want to build site which is mostly static (blog, portfolio, landing page), use Gatsby, it's not SSR, but it pre-renders the website into HTML at the build time
If you want to build a web app with react, and you care about SEO, easier social media optimization and faster render for user you should think about SSR and framework like next.js
If you building a SPA (single page application), and you don't want to configure everything on the server side like: i18n, router e.t.c. you should use create-react-app
Originally posted by Jakub Klimek on Altalogy blog
Top comments (1)
Nice article!
I think it bears mentioning as well that client-side rendering requires some extra effort to maintain accessibility when the route changes - otherwise focus can be left on items no longer on the page, new content goes unannounced, and the page title never changes.