Check out myAngular article series with live demos and Facebook group Angular - Advanced Topics

Combining Prepack and Closure Compiler

Torgeir "Tor" Helgevold
- JavaScript Developer and Blogger
Published: Tue May 09 2017

In this post I want to test if there is any benefit to combining Prepack with the Closure compiler (ADVANCED_OPTIMIZATIONS).

Prepack

Prepack is essentially a build time JavaScript evaluator. The idea is to analyze JavaScript at build time and look for runtime optimizations.

Examples of such optimizations include unrolling loops and evaluating if statements.

This seems somewhat related to Closure compiler optimizations, but the difference is more focus on runtime performance than code size.

I wonder though, can I combine the two and get the best of both worlds?

Let's see what happens if we run both of them against the following code sample:

function getCountries() { return ['USA', 'Norway', 'Germany', 'Sweden']; } function carService() { return ['BMW', 'Ferrari', 'Lamborghini', 'Porsche']; } var cars = carService(); for(var i = 0; i < cars.length; i++) { if(cars[i][0] === 'B') { console.log(cars[i]); } } var countries = getCountries(); for(var i = 0; i < countries.length; i++) { if(countries[i][0] === 'U') { console.log(countries[i]); } }

Here I have created a trivial program consisting of two loops with conditionals.

Closure Compiler

Let's start by running the Closure compiler on the program.

The result is pretty good as seen below:

for(var a=["BMW","Ferrari","Lamborghini","Porsche"],b=0;b<a.length;b++)"B"===a[b][0]&&console.log(a[b]); for(var c=["USA","Norway","Germany","Sweden"],b=0;b<c.length;b++)"U"===c[b][0]&&console.log(c[b]);

As you can see, the functions have been inlined, and the conditionals have been converted to boolean expressions. Overall this is both compact and fast code.

Prepack

Next I will Prepack the same code sample.

var getCountries, carService, i, countries, cars; (function () { function _0() { return ['USA', 'Norway', 'Germany', 'Sweden']; } function _1() { return ['BMW', 'Ferrari', 'Lamborghini', 'Porsche']; } getCountries = _0; carService = _1; i = undefined; countries = undefined; cars = undefined; cars = ["BMW", "Ferrari", "Lamborghini", "Porsche"]; i = 0; console.log("BMW"); i = 1; i = 2; i = 3; i = 4; countries = ["USA", "Norway", "Germany", "Sweden"]; i = 0; console.log("USA"); i = 1; i = 2; i = 3; i = 4; })();

As you can tell the code is more verbose, but at the same time, simpler.

There is no longer any loops or conditionals in the code.

However, the code executes a lot of unnecessary statements like assignments to “i”. It also initializes cars and country arrays that are irrelevant to the outcome of the program.

One of the strengths of Closure compiler is detecting code without impact on the outcome of a program.

Here I have plenty of examples of unnecessary code.

Crazy idea! Let's run the Closure compiler on the output of Prepack to see what we get...

The result is pretty nice..

console.log("BMW");console.log("USA");

Closure compiler was able to determine that the outcome of this program is always two simple console log statements.

I have put this code on Github if you are interested in checking it out.

If you liked this article, share it with your friends on social media:

We also have a new Facebook group about advanced Angular topics.

I invite you to follow me on twitter