DEV Community

Cover image for How we reduced our initial JS/CSS size by 67%

How we reduced our initial JS/CSS size by 67%

Guilherme Oenning on November 26, 2018

We have been working on reducing the amount of bytes that we send to all Fider users. Being a web application built with React, we have focused on ...
Collapse
 
daniel15 profile image
Daniel Lo Nigro

One small suggestion I have is to load React from a CDN, and put it in a separate bundle otherwise (as a fallback). React is very popular, and loading it from a CDN means that it's more likely to be cached - if your users have already hit another site that used the same version of React, from the same CDN.

You're likely not upgrading your React version as often as you're upgrading your other vendor packages, which is why React should be separate. Otherwise, whenever you change any of the other vendor packages, users will need to download the whole of React again.

Collapse
 
goenning profile image
Guilherme Oenning

Great suggestion, thank you! The advantages are clear, but what about the disadvantages? Do you know any? I wonder why this is not more popular on apps using React.

Collapse
 
pavanmehta profile image
Pavan Maheshwari

Won't the other vendor packages expect react as a peer dependency? For example react routerdom

Thread Thread
 
goenning profile image
Guilherme Oenning

You mean the common bundle? It does depend on vendor bundle (which contains React and reactdom), which is why on the html we import the vendor bundle before the common

Thread Thread
 
ajayposhak profile image
Ajay Poshak • Edited

And what about Server Side rendering then? While doing SSR, I need react's renderToString function on server so I have to install react anyways. I am curious to know how did you do it?

Thread Thread
 
goenning profile image
Guilherme Oenning

I don’t have Node.js on the server side, so SSR is very hard to me. So I’m planning to use puppeteer to do prerender for crawlers.

Thread Thread
 
daniel15 profile image
Daniel Lo Nigro

You don't necessarily need Node.js for server side rendering. It's likely your preferred server side language has some JavaScript engine you could use.

Collapse
 
addyosmani profile image
Addy Osmani

Great write-up, Guilherme! Love that the diffs for each improvement are publicly available for folks to learn from. Did you use any other tools while auditing your app? (e.g Lighthouse) 😀

Collapse
 
goenning profile image
Guilherme Oenning

I did run it sometimes, but haven't stored it. I'll boot up both versions, compare the lighthouse result and post here later today! :)

Collapse
 
goenning profile image
Guilherme Oenning

Before: googlechrome.github.io/lighthouse/...

After: googlechrome.github.io/lighthouse/...

This is client-side rendered, so there's still room to improve.

Collapse
 
thedrow profile image
Omer Katz

I wonder why you haven't mentioned using brotli in addition to gzip.
It produces far better compression ratio and decompression speed is off the hook.
It's supported by all major browsers (See caniuse.com/#feat=brotli) and has a webpack plugin (See github.com/mynameiswhm/brotli-webp...).

Collapse
 
goenning profile image
Guilherme Oenning

Hi Omer, I haven't mentioned that because we didn't implement it yet. But we're definitely interested on that too! 😀 Are you using Brotli already? Have you seen much difference?

Collapse
 
thedrow profile image
Omer Katz

I have used brotli in the past.
It's such a huge boost and it's super easy to implement.

Collapse
 
lecstor profile image
Jason Galea

I believe tree shaking is actually disabled in webpack if it finds you are using dynamic imports as it doesn't know (or doesn't go to the trouble to know) all the parts of a module different parts of your code will need.

With your react-icons usage you are imply importing just what you need. However, it appears that with v3 you will still have to import the complete icon set as the icons can no longer be imported individually (they come in a single file).

Collapse
 
goenning profile image
Guilherme Oenning

We're not using dynamic imports on react-icons, so Webpack can still tree shake it. Our react-icons is already on v3 and our bundles only have the SVG for the icons we use. Have you had a different outcome with this setup?

Collapse
 
lecstor profile image
Jason Galea

interesting, maybe there are situations where it will work and I read too much into this.. github.com/webpack/webpack/issues/...
I was definitely having issues and I guess I assumed this applied across the board (especially as we're doing code splitting on routes in the main component).

Collapse
 
thekashey profile image
Anton Korzunov

There is only one mistake in this article - react-loadable.
It's unmaintained for a long time already, and should not be used at all (github.com/jamiebuilds/react-loada...). It's better to say - it always was unmaintained.

Lazy and Suspense are also not quite "done" yet, so please consider "loadable" - github.com/smooth-code/loadable-co...

Collapse
 
goenning profile image
Guilherme Oenning

I wasn't aware of that package, thanks for sharing. I've add a note on the post so others can have a look a that too.

Collapse
 
shanamaid profile image
Jingyi Zeng

You can use archer-svgs to load svg async and cache it in localStorage, when you reuse svg without http request!Remove svgs from your js-bunilde and Thin your js-bundle forever!(eg: Dont reload 100kb svg bundle only for 1kb svg update!)

Collapse
 
sadarshannaiynar profile image
Adarsh

Amazing article on reducing bundle size from a broad range of perspectives.

Collapse
 
glebirovich profile image
Gleb Irovich

Thanks!

Collapse
 
ajayposhak profile image
Ajay Poshak • Edited

I think that the other way to stop changing your main bundle whenever some other bundle changes is to create a runtime chunk separately. This chunk will contain all runtime info that was inside main bundle till yet. I have also written about some techniques to fine-tune your bundle size using webpack medium.com/@poshakajay/heres-how-i...

Collapse
 
agrim profile image
Agrim Prasad

Awesome practical tips,thanks!

Collapse
 
pavanmehta profile image
Pavan Maheshwari

I've seen a wepback plugin that lazily loads css. I'm not sure how that works or whether that's possible. But one of my colleagues showed it to me. Do youveyany experience with that?

Collapse
 
goenning profile image
Guilherme Oenning

We only lazy load the css from the page splitting. But our main css bundle is always loaded synchronously. My understanding is that when lazy loading the whole css, if there’s a delay to download it, the user will first see an ugly and broken layout

Collapse
 
thobyv profile image
Thoby V ijishakin

This is a great article, thanks for sharing too. I particularly like the bundle analysis idea I've been doing that lately, really helps prevent shipping large builds.

Collapse
 
dukemai profile image
dukemai

thanks for your thorough summary :). Now I learn a new tool bundlephobia.