When you develop your modern web app, you usually use tools like Parcel or Webpack. These are bundlers. They take all your modular and human-readable code and transform it into a single file or "bundle". They also make sure that all the other resources for your web app like CSS, images, fonts etc are collected into one folder. Few other bundlers that are getting popularity that are focused on performance and developer experience are ESBuild, Vite and Snowpack. Some are 100% written from scratch not borrowing anything from anyone like ESBuild. Another like Vite and Snowpack are wrappers around SWC, Babel, ESBuild and other standalone tools to achieve better DX by giving an instant feedback loop between code changes in the contrary to Rollup/Webpack which usually take few seconds or minutes for rebuild, especially on the first run, surely depending on the size of the codebase they process.

For development, bundling usually done without any optimizations, so it's quickly ready to test, but in production it has to be done in a slow and highly-optimized way. Typical optimizations are:

  • Minification - this means all your code will be on the same line, without any spaces. All variable and function names will be replaced with super-short names, as will many other things that can take less characters without changing the logic of the code.

  • Dead code elimination - this means the removal of code that's never going to run no matter what you do. For example, you may have a useless if statement that is always true, with a return statement. All code below it will never run. This code would be identified as useless and deleted.

  • Code splitting - this is where you send only the small chunk of code needed to render your first page, and for any other page, additional code will be downloaded on demand.

  • Tree-shaking - this is almost the same thing as dead code elimination, but is based on modules and usage of these modules and their exports. In other words tree shaking is the process of removing unused code from your bundle, but a bit more sophisticated than "Dead code elimination".

Imagine you're using a library of helper functions, let say lodash. Everyone loves lodash but the problem is that people mostly use less than ten of its dozens of functions. Without a tree-shaking optimization, if you imported, for example, the merge function like this: import { merge } from 'lodash', all of the functions available in lodash will be taken along and end up in your bundle, even though you only need merge. Tree-shaking will check what functions, classes, or constants are used and then takes only those into the bundle. So instead of the whole of lodash weighing 66.9 kilobytes, you will only import around 4 kilobytes. You can check if the library that you use is shakable by using services like Bundlephobia.com.

You might wonder why bundle size is so important.

First of all, not all connections are equal, so if you're sitting somewhere in Europe, say Poland or Ukraine, you can expect super-stable half gigabit cable connection at home or in the office. But, if we look at the cellular connection in these two countries, only three or four years ago, Ukraine had only 2G or so-called EDGE connection, whilst Poland has already been enjoying 4G for a few years. So your average user in Poland will download lodash within 5ms, but the average user on the streets of Kyiv will wait for whole second for it to download. Now imagine adding on top of it React, a few libraries, helpers, CSS-in-JS library or whatever, and you could quickly end up with a megabyte of gzipped JavaScript.

Start a new discussion. All notification go to the author.