<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Filip Sobol</title>
    <description>The latest articles on DEV Community by Filip Sobol (@filipsobol).</description>
    <link>https://dev.to/filipsobol</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F878039%2Fb08d89ac-fcc4-4ce3-a0aa-873599590841.jpg</url>
      <title>DEV Community: Filip Sobol</title>
      <link>https://dev.to/filipsobol</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/filipsobol"/>
    <language>en</language>
    <item>
      <title>Downsize your JavaScript: Mastering Bundler Optimizations</title>
      <dc:creator>Filip Sobol</dc:creator>
      <pubDate>Tue, 17 Dec 2024 11:00:00 +0000</pubDate>
      <link>https://dev.to/filipsobol/downsize-your-javascript-mastering-bundler-optimizations-2485</link>
      <guid>https://dev.to/filipsobol/downsize-your-javascript-mastering-bundler-optimizations-2485</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Over the past 15 years, the JavaScript ecosystem has expanded rapidly, introducing countless tools to make development easier. But these tools come at a cost: growing bundle sizes. In fact, data from the HTTP Archive shows that the average amount of JavaScript transferred per page has surged from 90 KB in 2010 to 650 KB in 2024 (&lt;a href="https://httparchive.org/reports/state-of-javascript" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Despite growing adoption and advances in compression, this trend shows no signs of slowing. As we keep adding features, the challenge remains: &lt;strong&gt;How can we ship less JavaScript?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oddly enough, the solutions are both easy and hard. The easy part is the project-level tweaks that can yield quick wins. The hard part is making a lasting impact, which requires a community-wide change to improve bundlers, libraries, and tools.&lt;/p&gt;

&lt;p&gt;This article focuses on actionable improvements for your projects, covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bundlers&lt;/strong&gt;: Optimizing build tools to reduce output size.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Libraries&lt;/strong&gt;: Choosing and using external dependencies wisely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your project&lt;/strong&gt;: Practical steps to shrink your bundles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Future articles will address ecosystem-wide improvements we can make, but for now, let’s tackle how these factors contribute to bloated bundles — and how to manage them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why optimizing JavaScript matters
&lt;/h2&gt;

&lt;p&gt;JavaScript is the engine behind the modern web interactivity, but it isn’t free. &lt;strong&gt;JavaScript is the most computationally expensive resource&lt;/strong&gt; your browser has to handle. It’s often the bottleneck that determines whether a page feels fast or sluggish, as a bloated bundle can block rendering and degrade overall performance.&lt;/p&gt;

&lt;p&gt;The bigger the JavaScript bundle, the longer it takes to load, parse, compile, and run. This delays everything else — like showing content or letting users interact with the page. For someone on a high-end laptop with a fiber connection, this might be a minor annoyance. But for someone on a low-powered phone or a spotty network, it can be the difference between staying or leaving your site entirely.&lt;/p&gt;

&lt;p&gt;The first step at reducing the JavaScript bundle size is tree shaking (or “dead code elimination”), which most bundlers do out of the box. But are all bundlers equal?&lt;/p&gt;

&lt;h2&gt;
  
  
  Bundlers
&lt;/h2&gt;

&lt;p&gt;Bundling in JavaScript has come a long way — from manual concatenation and task runners to sophisticated bundlers. Today, bundler performance is a key focus, with developers prioritizing faster builds. However, &lt;strong&gt;build speed isn’t everything&lt;/strong&gt;. Equally important is the size of the bundles they produce, as smaller bundles translate to faster loading times for users.&lt;/p&gt;

&lt;p&gt;In search for better performance, we have moved from writing bundlers in JavaScript to languages like Rust and Go. This switch required writing them from scratch, so every feature and optimization that was present in the old bundlers has to be reimplemented. In the long run, this will likely pay off. However, in the short term, it means that they are missing some features that JavaScript bundlers had years to develop, like good &lt;strong&gt;tree shaking&lt;/strong&gt; or &lt;strong&gt;minification&lt;/strong&gt;. And these are the very features that can help us minimize bundle size.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benchmark
&lt;/h3&gt;

&lt;p&gt;Of course, talk is cheap, so let's look at the numbers, shall we?&lt;/p&gt;

&lt;p&gt;Let's compare eight popular libraries and bundle them with seven popular bundlers. To keep things fair, I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node 22.12.0&lt;/li&gt;
&lt;li&gt;Mean build time from 10 runs (with 2 warm up runs) using &lt;code&gt;node --run&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Configurations that remove all comments, including licenses, since bundlers handle them differently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can check out the &lt;a href="https://github.com/filipsobol/bundle-size-benchmark" rel="noopener noreferrer"&gt;benchmark setup repository&lt;/a&gt; for the exact configurations.&lt;/p&gt;

&lt;p&gt;Bundlers tested:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;esbuild (&lt;code&gt;0.24.0&lt;/code&gt;) with built-in minifier&lt;/li&gt;
&lt;li&gt;Parcel (&lt;code&gt;2.13.2&lt;/code&gt;) with built-in minifier&lt;/li&gt;
&lt;li&gt;Rolldown (&lt;code&gt;0.15.1&lt;/code&gt;) with &lt;code&gt;rollup-plugin-esbuild&lt;/code&gt; minifier&lt;/li&gt;
&lt;li&gt;Rollup (&lt;code&gt;4.28.0&lt;/code&gt;) with &lt;code&gt;rollup-plugin-esbuild&lt;/code&gt; minifier&lt;/li&gt;
&lt;li&gt;Rspack (&lt;code&gt;1.1.5&lt;/code&gt;) with built-in minifier&lt;/li&gt;
&lt;li&gt;Vite (&lt;code&gt;6.0.3&lt;/code&gt;) with built-in minifier&lt;/li&gt;
&lt;li&gt;webpack (&lt;code&gt;5.97.1&lt;/code&gt;) with swc minifier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that at the time of writing, Rolldown is still in alpha, so it's at the disadvantage and its results will likely improve over time.&lt;/p&gt;

&lt;p&gt;Libraries tested:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;chart.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ckeditor5&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;handsontable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;luxon&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mobx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tippy.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zod&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These libraries vary in size and features — some can function almost like standalone applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build speed
&lt;/h3&gt;

&lt;p&gt;Let's start with build speed, as this is something that developers seem to care a lot about. When bundling all of these libraries together, esbuild is the winner, with the build time of 229 ms. Comparing it to the slowest build time of 7.78 seconds, that's over 34 times faster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6dfs107iyi21v915ycm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6dfs107iyi21v915ycm.png" alt="Build speed benchmark results" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on these results, we can group the bundlers into three categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Blazingly fast™&lt;/strong&gt;: esbuild, Rolldown, Parcel with cache enabled (&amp;lt;1 second, with esbuild under 250 ms).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster&lt;/strong&gt;: Rspack (~2.5 seconds).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slow&lt;/strong&gt;: Parcel without cache, Vite, Rollup, webpack (5+ seconds each).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The differences are stark. For instance, Rolldown and Rspack are 7× and 3× faster than their older counterparts, Rollup and webpack, respectively — all while maintaining theoretical backward compatibility. Switching to these newer bundlers could boost productivity significantly on larger projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Output size
&lt;/h3&gt;

&lt;p&gt;When it comes to output size, the differences aren’t as drastic as build times, but they still matter.&lt;/p&gt;

&lt;h4&gt;
  
  
  Aggregated results
&lt;/h4&gt;

&lt;p&gt;When bundling all eight libraries together, Rollup and Vite are the winners, with the output size of 2081 KiB. Comparing it to the largest output size of 2491 KiB, that's over 19.5% smaller output.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;19.5% difference in output size is substantial&lt;/strong&gt;: on a slow 3G connection, the smallest bundle might take around 5.7 s to download, while the largest closer to 7 s. Parsing and execution times also scale with bundle size, so the real-world difference could be even more noticeable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fff9mjslf7injfch072d8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fff9mjslf7injfch072d8.png" alt="Build size benchmark results" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on these results, we can group the bundlers outputs into three categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Smallest&lt;/strong&gt;: Rollup, Vite, esbuild, Rolldown, and Parcel (~2081–2162 KiB).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Okay&lt;/strong&gt;: webpack (~2317 KiB).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Big&lt;/strong&gt;: Rspack (~2491 KiB).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With this particular set of libraries, webpack and Rspack produced the largest bundles. However, there's a reason for this. In the later section, we will look at it in more detail and introduce an optimization that will help reduce the bundle size in both webpack and Rspack, &lt;strong&gt;bringing webpack bundles up to par with Rollup and Vite&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Individual libraries
&lt;/h4&gt;

&lt;p&gt;Aggregated results don't paint the whole picture because it's unlikely that you will use all the libraries listed above in your project. What is more interesting is how these bundlers handle the individual libraries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnw3bmktuc5g2c33uugw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnw3bmktuc5g2c33uugw.png" alt="Build size benchmark results for individual libraries" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a library like &lt;code&gt;chart.js&lt;/code&gt;, the choice of bundler can dramatically affect the output size, with differences reaching 70%. This highlights the importance of testing bundlers with your specific dependencies. In most other cases, the difference is much smaller, reaching up to 22%.&lt;/p&gt;

&lt;p&gt;Moreover, while in aggregate webpack ended up in the middle, it performed the best in 4 out of 8 cases. However, because it performed much worse when bundling &lt;code&gt;handsontable&lt;/code&gt; and &lt;code&gt;chart.js&lt;/code&gt;, it ended up where it did. This means that, depending on the libraries you use, webpack can be a good choice.&lt;/p&gt;

&lt;p&gt;On the other side of the spectrum, we have Rspack. It performed the worst in 5 out of 8 cases, which produced a bundle much larger than the other bundlers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bundle size vs. output speed
&lt;/h3&gt;

&lt;p&gt;As shown, some bundlers may produce larger builds than others, and the results may also depend on the libraries used.&lt;/p&gt;

&lt;p&gt;When choosing a bundler for your project, or migrating from one to another, don't just compare build times — compare the resulting bundle sizes as well. You may find yourself trading faster builds for larger bundles. You should also &lt;strong&gt;test it with the libraries you use&lt;/strong&gt; to make sure it works well in your specific case and setup.&lt;/p&gt;

&lt;p&gt;For example, after Angular switched from webpack to esbuild, some developers reported that &lt;a href="https://bsky.app/profile/ricky.pt/post/3lciv2c3ykk2r" rel="noopener noreferrer"&gt;the size of an empty Angular app increased by around 20 KB&lt;/a&gt;. This highlights perfectly the build-speed vs. bundle-size trade-off.&lt;/p&gt;

&lt;p&gt;It's not to say that you should not look at the build speed because it's important for developer productiveness and happiness. There's also a &lt;a href="https://graphite.dev/blog/how-long-should-ci-take" rel="noopener noreferrer"&gt;correlation between the CI build time and the time needed to merge the code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbos34k48uuc4bo9ttov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbos34k48uuc4bo9ttov.png" alt="Correlation between build speed and merge time" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When choosing a bundler, look at the features it provides first. Then aim for a &lt;strong&gt;balance between build speed and bundle size&lt;/strong&gt;. Select the bundler that can produce possibly the smallest bundle in the time that you are comfortable with.&lt;br&gt;
Test a few representative libraries from your project. If your dependencies make up most of your codebase, the differences you see in these benchmarks can be a good predictor for your situation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;p&gt;Next on our list are external libraries, which often make up the bulk of your JavaScript bundle. In many, if not most, applications I have worked on, they accounted for the majority of the bundle size. That's why it's so important to choose (and use) them wisely.&lt;/p&gt;
&lt;h3&gt;
  
  
  Gold but old
&lt;/h3&gt;

&lt;p&gt;Many of us have installed libraries like &lt;code&gt;lodash&lt;/code&gt;, &lt;code&gt;axios&lt;/code&gt;, or &lt;code&gt;moment&lt;/code&gt; just to use a single function — leading to bloated applications. These libraries are great and historically important, but as they became more popular, lighter alternatives were created, and some of their features were added to the language itself.&lt;/p&gt;

&lt;p&gt;We can take advantage of that. I could list native APIs or newer and smaller alternatives for these libraries, but there are already many articles covering that. And there are so many other libraries that it would be impossible to cover them all.&lt;/p&gt;

&lt;p&gt;That's why I will only give you a general advice to take a look at the libraries you use and see if you can remove or replace them with native APIs or smaller alternatives. The &lt;a href="https://youmightnotneed.com/" rel="noopener noreferrer"&gt;YOU MIGHT NOT NEED *&lt;/a&gt; website is a great resource to get started.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bundler-specific optimizations
&lt;/h3&gt;

&lt;p&gt;Bundlers support different features and this also can have a significant impact on the output size. We already saw this in the initial benchmark, where webpack and Rspack produced the largest bundles. But there's a reason for this.&lt;/p&gt;

&lt;p&gt;Internally, the &lt;code&gt;handsontable&lt;/code&gt; library uses &lt;code&gt;moment&lt;/code&gt; to handle dates, which uses dynamic &lt;code&gt;require()&lt;/code&gt; calls to load the locale files. Since dynamic &lt;code&gt;require()&lt;/code&gt; calls depend on runtime values, webpack and Rspack bundle all locale files just in case they are needed. Depending on your setup, this may be what you want.&lt;/p&gt;

&lt;p&gt;In most cases, you won't need all the locales, just the ones you choose. That's why we can configure webpack and Rspack not to bundle them, which significantly reduces the bundle size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// webpack.config.mjs / rspack.config.mjs&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;noParse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="sr"&gt;/moment.js/&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This small change reduced the size of the &lt;code&gt;handsontable&lt;/code&gt; in both bundles by almost 20% and brings the webpack bundle with all dependencies up to par with Rollup and Vite.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6thlb24im6dnmzfv7m6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6thlb24im6dnmzfv7m6.png" alt="Build size benchmark results without locales" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimized installation paths
&lt;/h3&gt;

&lt;p&gt;Most libraries aren’t optimized for size by default, but some offer special installation paths or partial builds. Even among the libraries in our test, &lt;code&gt;chart.js&lt;/code&gt;, &lt;code&gt;handsontable&lt;/code&gt;, and &lt;code&gt;ckeditor5&lt;/code&gt; offer a way to reduce the size of the library by only including the parts you need. Let's look at &lt;code&gt;ckeditor5&lt;/code&gt; as an example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dcu3urqa84t4643lo10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dcu3urqa84t4643lo10.png" alt="Comparison between the normal and optimized builds" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default installation path results in the bundle size between 666 and 786 KiB. However, if we use the optimized installation path, the bundle size drops to between 603 and 659 KiB. This is a 7% to 23% reduction in size, depending on the bundler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Duplicated dependencies
&lt;/h3&gt;

&lt;p&gt;Another thing to look out for are duplicate dependencies. This is a surprisingly common problem in JavaScript applications. For example, Bluesky embed widget had two versions of &lt;code&gt;zod&lt;/code&gt; validation library. &lt;a href="https://github.com/bluesky-social/social-app/pull/6610" rel="noopener noreferrer"&gt;Removing the duplicate reduced the bundle size by ~9%&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This problem usually doesn't happen because you pulled two different versions of the same library, but because you and one of the external libraries depend on the same library, but in different versions. This can often be solved by updating the libraries you depend on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your project
&lt;/h2&gt;

&lt;p&gt;With all of this in mind, we can finally move to the last piece of the puzzle — your project. Here’s what you can do to shrink your bundles and improve performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspect your bundles
&lt;/h3&gt;

&lt;p&gt;The first step is &lt;strong&gt;visibility&lt;/strong&gt;. Without understanding what’s inside your bundles, reducing their size becomes a guessing game. For this, you can use a bundle analyzer and visualizer I created called &lt;a href="https://sonda.dev/" rel="noopener noreferrer"&gt;Sonda&lt;/a&gt;. It works with most bundlers mentioned above (except Parcel) and accurately shows the size of individual files that contribute to the bundle.&lt;/p&gt;

&lt;p&gt;You can start by &lt;a href="https://sonda.dev/introduction.html" rel="noopener noreferrer"&gt;installing it in your project&lt;/a&gt; and visually inspecting parts of your bundle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdskzsqypzr91y8eavzcg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdskzsqypzr91y8eavzcg.jpg" alt="Tree map chart for Sonda project itself" width="800" height="705"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have a good understanding of what’s inside the bundles and have identified the parts that can be optimized, you can click on the graph tiles to see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://sonda.dev/features/compression-sizes.html" rel="noopener noreferrer"&gt;file sizes before and after compression&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sonda.dev/features/dependency-tree.html" rel="noopener noreferrer"&gt;list of files that import the selected file&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;and even &lt;a href="https://sonda.dev/features/used-code.html" rel="noopener noreferrer"&gt;inspect parts of the source code included in the bundle&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sonda also warns you about duplicate dependencies so you can quickly identify and fix the root of the problem.&lt;/p&gt;

&lt;p&gt;Ideally, you should not only do a one-time inspection, but set up continues monitoring as part of your CI pipeline. Tracking changes over time, especially in large projects, can help you prevent small changes from snowballing into significant bloat over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remove or optimize external libraries
&lt;/h3&gt;

&lt;p&gt;The fastest code is the code you &lt;strong&gt;don’t&lt;/strong&gt; ship. Whenever possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove libraries that can be replaced by native APIs.&lt;/li&gt;
&lt;li&gt;Swap out heavyweight libraries for smaller alternatives.&lt;/li&gt;
&lt;li&gt;Use optimized installation paths if the library support it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use code splitting
&lt;/h3&gt;

&lt;p&gt;If you can’t remove some part of your application, try code splitting. Code splitting allows you to defer loading certain parts of your app until they’re needed, improving initial load times.&lt;/p&gt;

&lt;p&gt;Use dynamic &lt;code&gt;import()&lt;/code&gt; to load modules on demand. For example, if a particular feature isn’t needed until the user clicks a button, defer loading it until that moment.&lt;/p&gt;

&lt;p&gt;Modern frontend frameworks support lazy loading out of the box, making it easier than ever to integrate code splitting into your workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow the best practices
&lt;/h3&gt;

&lt;p&gt;This is a general advice, but it's worth repeating. Follow the best practices, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use the latest &lt;code&gt;target&lt;/code&gt;&lt;/strong&gt; you can so that the code is not unnecessarily transpiled or polyfilled. Some polyfills can add a lot of code that is not needed at all in modern browsers, but many environments still add them by default. You can also set up a reminder to update the &lt;code&gt;target&lt;/code&gt; every year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regularly update dependencies&lt;/strong&gt;, as every so often the newer versions are smaller or faster. This can also prevent you from having to deal with security vulnerabilities or duplicate dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluate each dependency&lt;/strong&gt; you already have or are considering adding. If you can't justify the size, don't add it or search for a smaller alternative.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Join the Ecosystem Performance (e18e) community
&lt;/h3&gt;

&lt;p&gt;If you are interested in making the web faster or simply just learning new things, you should consider joining the &lt;a href="https://e18e.dev/" rel="noopener noreferrer"&gt;Ecosystem Performance&lt;/a&gt; community. We focus on three main areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean up — Improving packages by removing redundant dependencies or replacing them with modern alternatives.&lt;/li&gt;
&lt;li&gt;Speed up — Improving performance of widely used packages.&lt;/li&gt;
&lt;li&gt;Level up — Building modern alternatives to outdated packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope this article illustrates that you can ship the same features with less code. Bundle sizes can grow out of control if unmanaged, but even small changes can significantly improve performance.&lt;/p&gt;

&lt;p&gt;Start today: analyze your bundles, test a new tool, or replace a heavyweight library. The impact will surprise you.&lt;/p&gt;




&lt;p&gt;I hope you enjoyed this article. If you have any questions or comments, or if you like to learn more about a specific topic, please let me know in the comments below. If you want to learn more about the topic of JavaScript performance, bundling and tree-shaking, you can follow me here or on &lt;a href="https://bsky.app/profile/filipsobol.bsky.social" rel="noopener noreferrer"&gt;BlueSky&lt;/a&gt; and &lt;a href="https://e18e.dev/" rel="noopener noreferrer"&gt;join the e18e community&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Visualizing JavaScript and CSS Bundles with Sonda</title>
      <dc:creator>Filip Sobol</dc:creator>
      <pubDate>Sun, 01 Dec 2024 10:35:34 +0000</pubDate>
      <link>https://dev.to/filipsobol/visualizing-javascript-and-css-bundles-with-sonda-5318</link>
      <guid>https://dev.to/filipsobol/visualizing-javascript-and-css-bundles-with-sonda-5318</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In this article, I'll show what Sonda is and what it can do. If you want to give it a try, check out &lt;a href="https://sonda.dev/" rel="noopener noreferrer"&gt;https://sonda.dev/&lt;/a&gt; or the &lt;a href="https://sonda.dev/demo" rel="noopener noreferrer"&gt;demo&lt;/a&gt; page.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you've ever struggled with optimizing your JavaScript and CSS bundles, you're not alone. As web applications grow more complex, fewer developers focus or learn build tools. But understanding how your code is bundled and what’s inside those bundles becomes increasingly important. This knowledge pays dividends in the long run and should be a key part of a web developer's toolkit.&lt;/p&gt;

&lt;p&gt;One open-source tool that can help you understand your bundles better is &lt;strong&gt;Sonda&lt;/strong&gt;. Sonda lets you visualize and analyze JavaScript and CSS bundles. In this article, let's explore how it can help you gain a deeper understanding of your final bundles after optimizations like minification and tree-shaking.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vbaegzzdr31y1fr7nzu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vbaegzzdr31y1fr7nzu.jpg" alt="Tree map graph showing individual files in the bundle" width="800" height="705"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Works With All Major Bundlers
&lt;/h2&gt;

&lt;p&gt;Sonda works seamlessly with all major bundlers, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vite&lt;/li&gt;
&lt;li&gt;Rollup&lt;/li&gt;
&lt;li&gt;esbuild&lt;/li&gt;
&lt;li&gt;webpack&lt;/li&gt;
&lt;li&gt;Rspack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are no second-class citizens. Plugins for all bundlers offer the same features and provide consistent insights, so you don't need to change tools or workflows because of the bundler you're using.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Accurate Insights
&lt;/h2&gt;

&lt;p&gt;Many existing bundle visualizers struggle to provide an accurate picture of the final bundles, often visualizing the output before crucial optimizations like tree-shaking or minification have occurred. This means that what you see in these reports may not match what is actually delivered to users.&lt;/p&gt;

&lt;p&gt;Sonda addresses this by showing information about the &lt;strong&gt;final bundle&lt;/strong&gt;, after all optimizations are complete. This ensures an accurate representation of what is ultimately delivered to users.&lt;/p&gt;

&lt;p&gt;You can learn more in the &lt;a href="https://sonda.dev/blog/what-makes-sonda-accurate.html" rel="noopener noreferrer"&gt;What Makes Sonda Accurate?&lt;/a&gt; article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detailed Reports for Better Understanding
&lt;/h2&gt;

&lt;p&gt;Sonda provides a detailed analysis, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sizes before and after compression&lt;/li&gt;
&lt;li&gt;Download times&lt;/li&gt;
&lt;li&gt;A dependency graph&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkrwzsrytsfp1p4fn89x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkrwzsrytsfp1p4fn89x.jpg" alt="Sizes of a bundle before and after compression and estimated download times" width="538" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This helps you understand the impact that each file and dependency has on the bundles. With this information, you can make informed decisions about which dependencies are worth keeping or where to trim down your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supports Multiple Formats: HTML &amp;amp; JSON
&lt;/h2&gt;

&lt;p&gt;Sonda can generate reports in &lt;strong&gt;HTML&lt;/strong&gt; and &lt;strong&gt;JSON&lt;/strong&gt; formats. The HTML reports are ideal for visual analysis, offering a clear, interactive visualization that can be easily shared with teammates. The JSON output is useful for integrating Sonda into CI/CD pipelines or other automated processes, making it flexible enough to fit into various workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Highlighting the Code That Matters
&lt;/h2&gt;

&lt;p&gt;Sonda can &lt;strong&gt;highlight the code that is actually used&lt;/strong&gt; in the final bundle. In complex projects, it can be challenging to keep track of which parts of a library or module are necessary. Sonda makes it clear by showing exactly what is in use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbohr700lhxy51rpdzj9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbohr700lhxy51rpdzj9.jpg" alt="Application code where parts used in the bundle are highlighted" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This feature can save significant time on debugging and pruning unnecessary code, providing a straightforward path to bundle optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Identifying Common Issues
&lt;/h2&gt;

&lt;p&gt;Sonda also provides &lt;strong&gt;warnings about common issues&lt;/strong&gt;, such as duplicated dependencies. This helps prevent unintentional duplication that can increase bundle size and impact load times.&lt;/p&gt;

&lt;p&gt;These warnings help you maintain best practices and keep your bundles clean and optimized.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Sonda is a powerful tool for understanding and optimizing JavaScript and CSS bundles. Its bundler-agnostic approach, detailed reports, and accurate post-optimization insights make it a solid choice for shipping smaller and faster web applications.&lt;/p&gt;

&lt;p&gt;If you're interested, give Sonda a try at &lt;a href="https://sonda.dev/" rel="noopener noreferrer"&gt;https://sonda.dev/&lt;/a&gt; or check out the &lt;a href="https://sonda.dev/demo" rel="noopener noreferrer"&gt;demo&lt;/a&gt; page&lt;/p&gt;




&lt;p&gt;What are your biggest challenges when analyzing bundlers? Are there any features that Sonda is missing?&lt;/p&gt;

</description>
      <category>visualizer</category>
      <category>analyzer</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
