loading...
Cover image for What is React Server Side Rendering and should I use it?

What is React Server Side Rendering and should I use it?

mladenstojanovic profile image Mladen Stojanovic ・1 min read

As stated in the title, I will try to present some pros and cons regarding this not-so-hot-anymore technology, and also help someone new to React SSR understand it a bit more.

First of all, let's dive into some terminology stuff

SSR? Isomorphic? Universal? WTF?

First of all, for some of you that don't know (as I haven't until recently) server side rendering is nothing special. Any ordinary static website is server side rendered, a server gets your request and spits out HTML to your browser.
We also had templating languages doing some neat tricks for us that are considered as server side rendering.
BUT when we talk about JavaScript, Server Side Rendering usually points out to an ability of a front-end code to render HTML while running on a back-end system.

SPA + SSR = Isomorphic*

* or universal

Isomorphic or Universal apps are interchangeable phrases commonly referring to a way of writing your apps so that you use the same language on both server and client side. More specifically, for JavaScript, best case scenario would be that you also use the same syntax.
For example if you are running your back-end in NodeJS you are probably using CommonJS module syntax.

//...Our awesome app code...
const circle = require('./circle.js');
//...Rest of our awesome app code...

And you write your React in ES6

//...Our awesome app code...
import React, { Component } from 'react';
//...Rest of our awesome app code...

Using Webpack we can start using our ES6 import syntax also on server side of our app, and that is the true goal of an isomporphic app.

Why would I want to use React with server side rendering in the first place?

Well, our traditional React app would have this flow when loading:

  • Browser requests a page
  • PAUSE
  • We get pretty empty html and a script tag pointing to a JS file where all of our code lives
  • Browser requests that script
  • PAUSE
  • Content visible on the screen

We now see that we have 2 round-trips to server, which is kinda acceptable. But let's imagine that our app has a list of blog posts, or a series of images, or whatever that we need to request from some API, now the flow is a bit more realistic and looks something like this:

  • Browser requests a page
  • PAUSE
  • Browser requests our JS
  • PAUSE
  • React app boots, requests data from backend
  • PAUSE
  • Content visible on the screen

As you can see, the number of requests increased, so there is a lot more happening before our user sees anything on the screen.

Now for the Server Side Rendered React App

  • Browser requests a page
  • PAUSE
  • Content visible on the screen!

Whaaat? How? Let's look at it in a bit more detail

  • Browser requests a page
  • Server loads React in memory
  • Server fetches required data
  • Server renders React app
  • Server sends generated HTML down to the browser
  • USER SEES CONTENT
  • Require JS file
  • React App boots, requests data from backend
  • App rerenders (hydrates) on the screen.

As you can see we did only 1 trip to the server before getting some content for our user. Now, the content that we served before we rerendered everything is static, so if our user is super fast and starts clicking before hydrate happens, the app will not be responsive.

What problems are we solving using this approach?

Two of the biggest ones are SEO and perceived performance boost

If your app is a bit larger, search engine crawlers will see your page as a mostly empty html with a single script tag that requests your massive React app, as it won't wait for the moment it fills up the DOM, your page won't get indexed.
Meanwhile, Google improved their crawlers to search for javascript created content also, but Bing or Baidu are still lacking this feature, so if larger percentage of your audience is coming from other search engines, you will have to work that out.

With React SSR your First Meaningful Paint time will be (in most cases) significantly lower. This is an important metric for some companies. You certainly heard stories of numerous companies increasing their profit by cutting down on load times for their web apps. (https://wpostats.com/).

Above I wrote perceived performance boost, and while it is true that you will get content to your user faster than using a traditional React app, the catch is that it probably isn't a performance boost. In the SSR request example a little bit above you see that server is also doing everything that client does: It boots up React, renders the app for you and spits out HTML. This means that you are doing everything 2 times which isn't ideal. Also renderToString() method that react uses to convert your beautiful jsx code to HTML is really slow and also synchronous. This puts server under more load, and your initial response from server will arrive later.

If you decided to go with server side rendering, you will probably have 2 servers: One for the API and business logic, and another one for rendering purposes. Knowing how big of a task your rendering process is, you can scale up your rendering servers to match the increased load.

Since I am not the first one who had issues with these problems, engineers over at Walmart labs created a tool that optimizes those quirks React SSR has, called Electrode. They also wrote couple of cool articles about it, really worth reading if you made it this far :) (https://medium.com/walmartlabs/using-electrode-to-improve-react-server-side-render-performance-by-up-to-70-e43f9494eb8b)
There are also "frameworks" for React SSR like Next.js for example which is gaining nice traction and support from community.

Using React SSR also adds multiple levels of complexity. Remember freely using window or document to do stuff? Forget about it!

I am just kidding of course, but you will have to be extra cautious, since the app will run first in a Node environment, window and document for example are not defined there, so you will have to restrain yourself from using them outside componentDidMount or without if (typeof window !== 'undefined'). I cannot remember how many times my app broke until I got used to it.

Your Node server will catch your routes and pass it down to React to decide what to render, so how does it have access to your router on server? It doesn't. Solution? Double routes. Your Application renders depending on something from your Redux store? Double store.

There are many complexities introduced with SSR, luckily for us, tools like Next.js solve many of them, but if you are stuck with solving all those problems by yourself, it will be really hard.

Should I use React Server Side Rendering?

Maybe.

If you / your company really values SEO, and significant number of your visits come from search engines other than google, yes.

If you / your company really values user perceived performance, think about it, if your client side application performance can't get anything better, then yes.

In any other case, my advice is to stay out of it, it will just increase complexity of your project without really much benefits.

Posted on Aug 10 '18 by:

mladenstojanovic profile

Mladen Stojanovic

@mladenstojanovic

JavaScript developer currently enjoying working in React!

Discussion

markdown guide
 

I'm just making this up in my head, because I'm pulling together random bits and pieces I've been reading all over, but with http2 isn't possible to do something clever with say splitting up the code so your initial paint is done with a smaller JS bundle and then it progressively loads the rest of your JS payload? It just seems this is something doable from all the bits and pieces I've read around the web. I just don't know if it's something that could be tied together and for a React scenario.

 

Yes, of course! :) There are techniques like tree shaking etc. which you can achieve through webpack, to reduce your client side payload, I am by no means an expert and 'know-it-all', that's why I wrote that people should probably first try to optimize their client side application as much as they can before attempting to go in to the dark side of server side rendering :)

 

I actually developed a tool having this complexity in mind. In our case we couldn’t use a framework like next.js because it is very opinionated. I needed something more flexible and that’s why I developed stormkit.io. I would really appreciate your feedback on it.

 

Looks cool, I will check it out!

 

Finally a clear and succint writeup about the topic! Thanks Mladen!

 

How does this work with dynamic routing, fluid (window aware) design and js based styling?

 
  1. Dynamic routes are not a problem since the fetching of the page will happen on the server (instead of on the client as it is normally the case). That info will pass down to the client where it will hydrate.

  2. Again no problems, the only thing to be aware of is that window is not present on the server, so you would have to do some checks like

if (typeof window !== 'undefined') { ... do your magic }

JS-based styling is supported, right now I am using Next.js with Styled Components, and it works like a charm :)

 

Hold on professor. What do you mean by "not-so-hot technology anymore"?

 

Just personal opinion :D It was all the craze at one point and now I think it died down a bit :)

 

Great piece Mladen, after building several apps with Nextjs I thought I would give SSR a go. Took me a while to get my head round it I can see the benefits it brings.