Analyzing and Reducing React Bundle Size

Bundle size matters.

Vahit Saglam
A Young Developer
6 min readDec 24, 2018

--

Hi everyone!

So, last day I read a story about how Netflix reduced their landing page’s bundle size and it’s inspired me, they removed React and used vanillaJS instead, but I can’t do that. I have limited time for this particular job so I am going to aim biggest reduce in shortest period of time.

Of course we use compression on server side to make sure our users always get smallest javascript file but even after compression, the size is considerably big for a landing page.(and of course a great power like compression comes with great responsibility - decompression-)

Before we get started let me to note that; I ejected my create-react-app and if you haven’t you should do it.

Note: Once you eject you can undo it. Be careful!

this will start the process of ejecting from Create React Native App's build scripts. You'll be asked a couple of questions about how you'd like to build your project. Once this command has successfully run, you should also follow any steps below that are applicable to your environment.

First Step: Analyze the bundle

we should install a npm package called “source-map-explorer”.

you may use yarn as well.

Then in package.json, add the following line to scripts:

let’s roll.

this will open a new tab in your default browser, let’s take a look at it

so this’s how a bundle analyze look like ? pretty complicated right? Not really.

It turned out the problem was our laziness. Our landing page had been a part of our main application before, but months ago we separated them. We forgot to remove a bunch of unnecessary packages and they made the project way more bigger than it should be.

Let ‘s take a closer look, and you can easily see our biggest players are moment, react-bootstrap, sugar, react-dom(react)and redux-form, jquery(somehow).

Moment problem

Moment is really awesome package, easy to use and pretty powerful. It’s been my favorite for handing date easily since the very begging of my web development carrier, but it’s really big.

It’s core only 52KB but for some reason it imports all locale files at once. It’s not modularized so you carry around all the world languages’ locale files in your app.

I don’t want that, I only have used tr, so let’s get rid off useless locales, unfortunately for us, neither its documentation nor its core includes any solution fits for us, but we can always use Webpack for that job. We gonna use webpack.ContextReplacementPlugin.

You might be using some big packages like Moment, always try to use modularized packages so you don’t have to import all library at once.

add the line below to your config/webpack.config.prod.js (you can add this to webpack.config.dev.js as well, but it might or might not slow down dev build progress and may cause latency in live review.)

you can change /en/ part with whatever locale you want. let’s rebuild our app and analyze it.

as you can see, moment’s size reduced to 59kb with just one line.

Sugar is harmfull!!

Just kidding(Unless you are on some kind of diet, or have diabet disease), We used Sugar for some reason(don’t remember why, could not figure out neither).

When I looked up it’s documentation, I realized we’ve been doing it wrong. Our import statements like this;

but it’s super wrong. Sugar is modularized and you should import the part you want to use.

now this should reduce your bundle size, but it wasn’t enough for me and like I said before I don’t even remember even why this package used for, I guess it is one of the remainders of our main project . so I changed Sugar with Vanilla JS and get rid of it all.

Redux-form? Wait, Where did I use that?

Okay, so I use Redux-form in most of my project but I don’t remember using it in landing page so I searched it in project and find the leak. Damn! How did I forget that?

I just combined it with other reducers and forget.

I removed it and our bundle size reduced to 877kb, good but not enough.

By the way, redux’s itself is also is a remainder. I’ll remove it completely

Next step replacing React with Preact

Preact is a lightweight alternative of React. It’s core only 4kb and it mostly compatible with React.

Disclaimer: Even though Preact claims it’s compatible with React and its ecosystem, there are still some packages(such as react-router) do not work as expected and may cause your application crash.

Preact package includes core and dom management and preact-compat is required for React compatibility.

Now we have successfully downloaded preact packages we can proceed to replacing react with preact.

In order to do that you must have ejected your app.

go to config/webpack.config.dev.js and config/webpack.config.prod.js and search for alias and add the following lines into it.

After this restart your app and check does preact work compatible with your packages.

Unfortunately it did not for me and react-router caused errors.

Next step: replacing react-router with preact-router

It’s easy to do but if you already have defined too many routes don’t try to do that and remove Preact.

you can find documentation over here.

react-router
preact-router

After all this steps my bundle size reduced to 577KB, good enough for now.

these steps worked out for me well, I didn’t lost any functionality but I can not give you any guarantee that it will work out in your project as well.

Alternative : Code Splitting

what if your application does not include any unused libraries ? or your application too big to even trying to replace Preact with React ? what can you do then? Well you’d rather use code splitting, fortunately for us, create-react-app comes with the support of code splitting.

Route based splitting might be the best choice to code splitting. Check out React documentation;

How to add route-base code splitting to your app?

first import Suspense, lazy from React.

now replace your import lines with React lazy loading

and now add Suspense and you are ready to go.

Thank you for reading :)!

--

--