Everything you need to know about Webpack's Bundle-Analyzer

mbarzeev

Matti Bar-Zeev

Posted on April 28, 2023

Everything you need to know about Webpack's Bundle-Analyzer

I have recently had the opportunity to get my hands dirty with Webpack bundle analyzer and have observed a shortage of comprehensive resources available on the web. It appears that this tool is often encountered sporadically, leading us to relearn its features each time we engage with it.
In this post I would like to extend an invitation to share the insights I have gained from my experience and provide a more thorough understanding of its functionality.


Hey! for more content like the one you're about to read check out @mattibarzeev on Twitter 🍻


Launching the analyzer

I assume you can find your way in installing the bundle-anayzer webpack plugin, as described here, but if you’re using the Create React App it might not be that trivial.
The way I found to do that is to build the application with --stats param and then use the result json file to generate the bundle-analyzer treemap.

You can sum it up all in a single npm script that goes like this:

"scripts": {
       . . .
       "profile": "npm run build -- --stats && npx webpack-bundle-analyzer ./build/bundle-stats.json"
   },
Enter fullscreen mode Exit fullscreen mode

Let’s see how it looks on a sample React application:

Image description

We can clearly see 2 main JS bundles and another small “runtime” one. The “runtime” bundle is for supporting code splitting, so we will focus on the 2 main ones:

  • build/static/js/2.ba16a06d.chunk.js
  • build/static/js/main.7a341cc4.chunk.js

TIP: It is important to mention that when you launch the analyzer it is better to make sure that Webpack runs in “production” mode, and generates optimized bundles (this should be the default case, but you know… ). This in order to get the closest simulation to what happens in production.

Analyzing you bundles

In order to start analyzing your bundles you should get a better understanding of the tool you’re about to use. Let’s explore it together -

We can clearly see the 2 bundles which make our application. Webpack, as part of its optimization, divides the code into 2 chunks - one is the chunk for 3rd party vendors such as React, Mobx etc., and the other chunk is the actual application code.

  • 2.ba16a06d.chunk.js - 3rd party vendors
  • Main.7a341cc4.chunk.js - Application code

If you click on an area in the Treemap it will attempt to focus on that area and enlarge it. Using the mouse wheel will also zoom in and out.

TIP: The Treemap is a Canvas based UI, and as such trying to find modules in it using the native browser’s “find” will not help much, but there are other solutions for that. Keep reading… ;)

Inspection Sidebar

On the top-left corner there is a small button that when clicked, opens up the inspection sidebar. Let’s open it up and pin it so it won’t get closed each time (which is super annoying… just saying):

Image description

The Treemap sizes

We start at the top and see that there are 3 modes of Treemap size - Stat, Parsed and Gzipped. What does each mean?

Stat - Stat sizes are fetched from the webpack stats object directly, and use the actual source code of your modules as-is and report the size before minification or gzip.

Parsed - Parsed sizes are calculated by reading the actual compiled bundle files and making a link back to the modules from the webpack stats file. So if you use a minifier, such as UglifyJS, the parsed size shows you the size after minification.

Gzipped - gzip sizes are calculated by reading the actual compiled bundle files and running gzip for each one of the module sources separately. Thus the gzip size shows you the size after minification and gzip, but it isn't a 1-to-1 mapping with the actual file sizes as gzipping each module separately yields less "wins" in terms of compression as the separate sources have less opportunities for gzip to compress together.

(These explanations are taken from a response in this enlightening GitHub thread)

If you change the size mode you’re in you will see an immediate effect in 2 places - in the chunks size at the bottom of the sidebar and in the Treemap itself.
The sizes will usually go like this:

Stat > Parsed > Gzipped
(> acts as greater-than here)

Sometimes the “Stat” size mode will give more information on the content of each package, or in other words, will better indicate what modules are bundled from a certain package.
To improve the analysis even further we can check the “Show content of concatenated modules” checkbox (right below the sizes mode) so that we can see what modules are getting concatenated.

For example, let’s take the application bundle and see the difference side-by-side:

Image description

Once you have a more detailed overview of what your bundle includes you can start making better decisions on how to optimize it.

Filter to initial chunks

Though not relevant to our current application example, since we have a single entry file for Webpack, sometimes Webpack has more than a single entry point. In that case you will be able to filter on the entry point which interests you and drill down to its chucks. Moving on.

Search modules

Remember when I told you that you cannot use the browser native “find” to locate modules you’re interested in? Well, this is where the “search modules” come in handy. You just place your regex and the Treemap will filter the module or package you’re looking for.

It does more than that - it will show you where this module is used in the different chucks, and the sizes in each place. Let’s try it with “mobx”:

Image description

What happens in the Treemap is even cooler. See how all the places where Mobx is found are painted in red:

Image description

This can help in cases where you would like to take a 3rd party like, say, Lodash which may be scattered in different chunks and extract it so it won’t be bundled in each chunk - you will see that before extracting it there are many “Red” patches in Treemap and afterwards it will reside in a single place.
Show chunks
At the bottom of the sidebar we have the chucks size, where we see all the chunks in total and then each by itself:

Image description

We can select just certain chunks to focus on them.

Optimization demo

Let’s take a simple case to show how the bundle-analyzer can help us with optimizing one of our chunks.
I’m looking at the chuck which holds the mobx-react package, and inspect its size:

Image description

As you can see in the tooltip, upon hovering the package, its parsed size is 9.27KB. Let’s see if we can reduce that.
I’m going to use mobx-react-lite for that. I’m installing it and changing every place in the code which uses mobx-react into the lite version. Here is the result after the change was made:

Image description

As you can see the change reduces mobx-react parsed footprint on the bundle to 4.14KB (more than 50%), and the bundle-analyzer helps us see that right away.

Wrapping up

The bundle-analyzer is a great tool to gain better understanding on what goes on in your application bundles, and also a tool to check the implications of your bundle optimizations.
A variation of it can also be found in Google’s Lighthouse devtool, and you can inspect your production bundles and also see the amount of unused code, etc.


Hey! for more content like the one you've just read check out @mattibarzeev on Twitter 🍻

đź’– đź’Ş đź™… đźš©
mbarzeev
Matti Bar-Zeev

Posted on April 28, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related