Here’s how I reduced my bundle size by 90%

While working on a side project, I realized that I was shipping the way more code to client than I should be. Bundle size was huge. So I looked for some optimizations.

On the front of performance also, it was taking 3.25 secs for first meaningful paint even on Wifi connection. So my big bundle was hitting harder to my web performance also.

And when it finished with easy to do optimizations, I was looking at bundle size 90% less as compared to size when I started.

Here is the initial webpack config

Change mode to production

By changing mode to production, it tells webpack to use its built-in optimizations. Such using uglifyjs for uglification and minification. So passing mode as production , reduced my bundle size by almost 50%.

Production mode sets process.env.NODE_ENV to production for build process. So that any dependency which relies on mode detection for optimization, can do it during build.

webpack --mode production --config ./webpack.client.js

main bundle size reduced, thanks to Production mode !!!

Additional Readings:

Production Mode explained

Split chunks

A lot of my code contained node_modules, so creating a vendor chunk with all the node_modules in it, would help further reduce the main bundle size.

cacheGroups in SplitChunks lets you define various caching groups. For creating a group of vendor chunks, we set test to contain all modules whose path contains node_modules in it. When a chunk name is matched, all modules in that chunk are selected. chunks option tells from where the chunks can be shared, it can be initial if it has to be shared in sync chunks, or async for async chunks, or all for both sync and async chunks.
Separating vendors chunk

Further Reading:

Split Chunks Plugin

RIP CommonsChunkPlugin

Remove dev tools mapping

We write ES6, and transpile it to browser compatible code(ES 5) using Babel. Then webpack concatenates all my files into a single chunk. Now to debug my original JS files in browser, I had enabled mapping of modules. Now this is very helpful during development, but for production these mappings create a lot of overhead for bundles. So in order to further optimize the bundle size, I removed dev tools mappings altogether from production mode.

After removing dev-tools mappings

Further Reading:

Devtool Mappings


Now, I wanted to compress it to further reduce the bundle size. Although, gzip compression is more popular, I tried brottli , a compression algorithm developed by Google. It is more efficient as compared to gzip. I used brotli-webpack-plugin to achieve it.

.br extension indicates file compressed by brotli

Further Reading:

Introduction to Brottli

Brotli Compression

End Note

I started with bundle size 2.97 MiB , and reduced it to 64 KiB (vendor and main bundle combined). Reduced bundle size helps a lot in performance tuning. It results in faster page load. Initially it was taking 3.25 secs for First Meaningful paint, which now reduced to 1.02 secs . That’s a huge win in performance.

No CPU throttling, Wifi connection
No CPU throttling; Fast 3G
4X CPU slowdown; Fast 3G (First Meaningful Paint — 1.2 seconds)

Further optimizations can be done by extracting runtime chunk, and inlining it in html response generated on server. See complete webpack configuration here.

If you liked this story, please give it a clap, and follow me on medium or twitter for more such articles.