React/Front End Bloat (and general update) / by Robert Walker

I'm still here!

Wow!  It's been a busy few months as I've started to integrate into my new position!  Thank you everyone that has been reaching out to me with questions or other stuff and for your patience.

When I started my new position I was tasked with being the project manager and principal software engineer for a brand new web application using a React front-end and Django back-end.  After some busy few months we finally pushed a beta app on-time out last week!  It's already impressing and new work rolling in :)  Unfortunately, I can't share specifics or links.

Topic of the Week - bundle.js Bloat

Moving on... The topic for my post this week is about front-end bloat.  Web application (and primarily JavaScript) have come a very long way in the past few years.  With some very helpful modules and some pre-built Frameworks (like React) we can push out a web application relatively quickly.  Developer modules (e.g., eslint, e2e frameworks like puppeteer and cypress, jest, etc.) and production modules really get things going with reusable code.  But even beyond that, npm build which uses webpack makes deploying production code super easy...

Until you realize you've been npm installing all-the-things and not paying attention to your application production build.  Now that we have beta out the door, we've turned our attention to optimization for the next release.  

Our web application, minified and gzipped and bundled was a nice 1.7 mb.  Not huge for a normal file on most internet connections, but huge for a web application.  That's several seconds for the application the "paint" the first component!  An eternity on today's web where most applications (including this blog) load in fractions of a second. 

So we started looking at our code and running analyses.  Nothing stood out immediately.  We were careful to use proper es6 imports on only the classes and functions we needed for a component, we had isolated our components and made them reusable.  We used proper react lifecycle events, async/await where appropriate, etc.

So why the bloat? When we ran our analysis we found that there were a few modules that were relatively large (200-300kb range).  These were essential and would take months to write the code from scratch.  So what could we do?

Turns out we had forgotten to do one thing... asynchronously load our imports. While not officially supported in JavaScript yet (see tc39), React is forward-looking and has already added it with support from WebPack 2+.  Doing this made a huge difference!  Instead of synchronously loading a 1.7MB JavaScript file onload, we could break up our code ("code splitting") into several smaller js files and load them simultaneously!

There are several really good articles on code splitting in React, but using the react-loadable module and reading it's guide is absolutely the best.

Adding react-loadable to our application and only implementing it on our primary view (e.g., the one beyond login) turned our 1.7MB file into seven new js blocks each less than 200KB that all load on-demand and asynchronously!

Our application now "paints" much faster and the "Loading..." place-holders are barely seen even on very slow connections.

So remember to run npm build regularly, especially after installing that new module with 20 dependencies, and use on-demand, asynchronous loading of modules liberally!  I expect once tc39 is approved we will see an explosion of blogs across the internet on how to use import().then() so keep an eye on it.