Quicker loading with ReactJS

Gal Abramovitz
4 min readOct 25, 2018

After a couple of days of continuous research and studying about page-loading time optimizations, I wanted to sum it up - so the next Front-End developer won’t have to go through all the fuss of reading like I did (or at least they’ll be quicker).

I’m working on Benchmarketing.io, which is an (amazing) tool for benchmarking, hand-tailored for e-commerce marketers and managers. The app itself is a single-page application (SPA), which means there’s plenty of room for loading-time optimizations, as explained beautifully in this article.

Figuring what’s going on

First of all, Google’s PageSpeed Insights provided me with a basic ground for my research. It has all the terminology and some basic explanations and action items, which are perfect to get you started.

In my case, the issues that held me back the most were the blocking resources of both JavaScript and CSS.

I’m using Create React App (CRA) to compile my app, so I started with 2 relatively big files that were created by react-scripts build: one that merges my whole CSS files and the other one merges all the JS files.
Obviously these are pretty nasty files to work with, as they include not only my app’s design and scripts, but also the whole Bootstrap’s CSS, along with the node modules I’ve used.

Because the browser blocks its rendering process until it finishes downloading all the required files (including the huge CSS file), the merged file posed a real problem.

Identifying the challenge(s)

After some more research, my insights boiled down to 2 main goals:

  1. The first challenge was to split the gigantic files into smaller, manageable chunks (which is actually how they’re called 🙃).
  2. The second challenge was to actually make React load these chunks of JS and CSS files only when they’re relevant; Hence sparing their loading time when the app initially loads.
Breaking into pieces (by Markus Spiske on Unsplash)

Splitting

The mechanism that actually generates the main files is CRA’s build function.
It magically goes through the app’s source code and identifies what JS files are imported into each component - then it merges the files by the components they’re imported into.

In my case, because I’m working on a SPA, the code was written in a way that just loads everything on initialization. It still took only ~3 seconds to load; However, according to many articles (such as this one), users will leave when an app takes over 3 seconds to load. And here we are.

So the first step was to create asynchronous components - just as explained here. This alone made a big impact, as the app no longer had to load at once.

The bigger issue was handling the CSS files: my app looked great, but still took long time to load, because its design was scattered across a few CSS files - which, in turn, made them relevant for all the components and therefore resulted in the huge merged CSS file.
I needed to clean the CSS design mess and re-organize it in separate files, by its relevance: each “page” in a different CSS file.

Finally I wanted to make the initial user experience as best as possible, so I separated the design of the elements that were above-the-fold from the rest of the landing page’s elements.

This was actually most of the work that needed to be done. The CSS and JS chunks were imported only where they’re relevant, resulting in a much more modular app. The only issue that was left was loading the rest of the landing page’s CSS (after the above-the-fold part is loaded).

Loading code only when it’s relevant

I read A LOT about the possibilities of doing this, but eventually I came with a very simple work-around that work really nice.

Let’s say we have a landing page component (that takes a while to load), with the following structure:

After splitting the main CSS file, we’ll have two files: one for the initial load (above-the-fold content) and the other for the rest of the page’s content.

Then all we need to do is lazy-load the bottom part of the landing page. In my opinion the simplest method to do so is by using React’s built-in React’s code splitting (added in v16.6.0).
Then the whole code, including the CSS, won’t block the whole page from rendering, but will load after the above-the-fold section is presented to the satisfied user.

Bonus: How to configure React-scripts to build the CSS file inside the public directory

As we probably will edit and update our CSS files, if we use Sass we’ll need to build at compilation time those that are in the public directory as well.

Luckily, we only need to add to our package.json file’s “build-css” and “watch-css” properties the relevant parts. For example, using node-sass-chokidar:

--

--