Code minifiers have been a black box for me up to now. I have seen them in two languages: CSS and JavaScript. A minifier is a program which transforms source code into other code that is smaller but behaves the same way. Since browsers download JavaScript and CSS as source code, smaller code means better performance. Altough the immediate effect of a minifier is on size, the target effect is on performance. Today I will try to get a high-level overview of what Babel’s JavaScript minifier1 does.

It’s all Babel plugins

The Babel minifier is just a Babel preset that you put inside your .babelrc configuration file. And since a preset is just a collection of Babel plugins, all transformations performed by the minifier are already neatly split across multiple packages inside packages. If you are unfamiliar with Babel’s architecture I suggest you take a look at the Basics section of the handbook2. This setup makes the actual minification steps very accessible, so we can jump right into those by examining the different plugins.

A simple minfication: Boolean literals

While minification as a whole might seem complex, some steps are really simple just like babel-plugin-transform-minify-booleans3. This plugin performs minification of boolean literals, namely true and false. These are excessively long and can be replaced by the shorter expressions !0 and !1. Why use negation and not 0 and 1 directly?

The reason is that 0 and false are not values of the same type. More concrete, if you transform typeof false into typeof 0 the code no longer behaves the same way. Using the negation always works, because it results in a boolean value. I think technically it must also be guaranteed that the ! operator always takes precedence over whatever operator might use the value !0. Looking at the operator precedence table on MDN4, I think that is given.

Advanced transformations

Most transformations are not a simple as the one above. If you want to see a full list of transformations I suggest you browse through all the plugin readmes in the packages folder. Instead of duplicating this content I will highlight some points I found interesting:

  • Not all transformations reduce code size. Some plugins produce code of the exact same size but try to make it better suited for compression algorithms like gzip5.

  • Constant folding is a general optimization concept: Perform pure computation on constants at compile time and use the result instead. The plugin implementing this optimization does more than I expected though. It not only evaluates arithmetic expressions, but also function calls and member access to built in things like [].length or [].reverse().

  • Mangling variable names is the process of shortening all variable names down as much as possible. By looking through the source code I realized that this is not as trivial as it sounds. If you walk through all variables in one scope and simply start renaming at a, you might end up with a less than optimal result. It matters how many times a variable name occurs in the current scope. For a scope with many variables, some of them will have to take names longer than one character. In order to minimize the output length, most frequently referenced variables need to get the shortest names.

Further reading: OSS deep dive: How does Babel’s minifier fold constant values?