Server-side rendering

Server-side rendering of your frontend application can be indispensable for some cases, but... is it worth the effort?

4 min read


By Eirik Wiig


December 19, 2018

Server-side rendering - worth the effort?

In simple terms, server-side rendering (SSR) in React enables you to render your app to static html on a server, which can then be returned to a browser. There are numerous ways of setting up the full SSR experience - and for those, Google is your friend. The basic setup however, is fairly straightforward.

On a Node.js server, simply render your app by:

import ReactDOMServer from "react-dom/server";
// ...
ReactDOMServer.renderToString(<MyApp />);

This renders a React element to an HTML string, which can then be returned as HTML in a response body. However, when loaded by a browser, this will only be static content without any JavaScript included. To enable JavaScript to be executed, the client-side code needs to be combined with the server-side output. Enter .hydrate():

import ReactDOM from "react-dom";
// ...
ReactDOM.hydrate(<MyApp />, document.getElementById(MY_APP_MOUNT_POINT));

This works in the same way as render(), but basically fills in the gaps of the html created by your SSR by adding the event listeners. And there you go, you got your App hooked up with SSR!

Hot or not?

As with all the big questions in life, the answer is that very unsatisfying... "it depends". So let's take a closer look at how it stacks up.

Benefit 1: First Meaningful Paint

SSR gets you to first meaningful paint faster. Or at least, potentially. Instead of having to download and then render the JavaScript in your browser, HTML is downloaded directly. For the user, they get the feeling that the site loads quicker.

That said, it isn't always a clear cut victory: getting the first byte takes more time as server-side rendering is slower to execute. Pre-rendered HTML is also generally bigger than your JavaScript bundle, so also takes longer time to download.

There are also other ways to achieve the same effect without having to go down the SSR road. Using loading animations, optimising your code and build packages for speed, pre-rendering tools (etc.) can also improve the perception among your users of a blazing fast site.

Benefit 2: Search Engine Optimisations

Perhaps the most important use-case for SSR is search engine optimisation (SEO). If the entire app was client-side rendered, traditionally, all the web-crawler could "see" was an empty page. Nowadays, many search engines have the ability to render JavaScript in the crawler. But, and this is important, not all of them can, nor do they do it all the time. Google for example have JavaScript bots, but these are not run as often. So the general rule of thumb is - make it as easy as you can for the bots, and both the bots and your marketing department will love you.

Again, as an alternative to SSR, you could look to pre-render your site using tools like react-snap and react-static in order to support you with your SEO performance.

Benefit 3: Sharing pages on social media

When you share a link on a social media platform (Facebook, Slack, etc), the link is rendered to show a preview of the page. The platforms only preview whatever html is on the page and do not render the javascript, which means that SSR could be useful. That said, the content for the preview is typically retrieved from the meta-tags of the html. So to be able to preview your page, you might not need the full SSR experience - but rather just a selected amount of meta-tags, such as title, description, image etc.

Do or don't?

There is broad agreement in the community that SSR can be hard and a real pain to do well and to maintain, in particular if you have a data rich application with many routes.

Essentially, you will be pushed to duplicate a lot of features to get it working correctly on the server-side. Think things like how to manage your redux store, CSS-in-JS, internationalisation, and so forth. In addition, one of the key challenges about SSR is how to know what data your view needs and how to get that data, before rendering it. Furthermore, there is the challenge on how to best handle cookies, redirects, and non 200 HTTP statuses. You also need to set up the infrastructure to render your app for you.

Of course, these are all challenges that are solvable - it just requires development time and effort. And it then becomes a matter of deciding whether the benefits outweigh the costs.

Up next...