5 Things You Wouldn’t Necessarily Expect

When Using AOT And Tree Shaking In Angular

AOT speeds up the application especially the startup because templates are already compiled during build. In addition to this, tree shaking reduces the needed file size by removing unused code. But there are some things, one wouldn't necessarily expect. This article presents five of them, we discovered and researched when working with it.

This article has been written after some very insightful conversations with Carmen Popoviciu. She pointed out issues regarding AOT and Tree Shaking, helped me to discover them and their origins and reviewed this article. Big thanks for this.

The most obvious: EcmaScript Modules

Let's start here with the most obvious and least surprising fact: You need sources based on EcmaScript 2015 for tree shaking. At least you need to use EcmaScript Modules introduced with EcmaScript 2015. Those modules use the well known import and export statements which allow for a static code analysis which is the foundation for finding unused code.

It is possible to use a combination of EcmaScript 5 and EcmaScript Modules to support a wider range of tools like webpack 2 which - at the time of this writing - does not support EcmaScript 2015 but leverages import and export statements for tree shaking.

Currently, the product team ships the Angular modules using this exact combination (besides additional UMD bundles). As the next section shows, this has a drawback, as there are some limitations when it comes to analyzing EcmaScript 5 code for tree shaking.

Current Limitations for Tree Shaking

Examples for Tree Shaking clearly show that it brings benefits in terms of file size. But at the time of this writing, there is much room for improvement. This mostly has to do with the fact that tools for tree shaking like Rollup and webpack2 cannot guarantee for every situation that removing unused code is safe. This is especially the case in situations where the code could introduce side effects, like changing a global variable. Therefore, these tools don't remove as much code as possible.

As a matter of fact, this holds true for the Object.defineProperty method, which mutates the first passed object. Unfortunately, this very method is used when transpiling class members down to EcmaScript 5 and therefore affects several parts of Angular as well as libraries like Angular Material.

One can find such parts of code by activating output warning within the webpack configuration for instance. This makes UglifyJS list every part of the bundle which it doesn't remove because of the mentioned reason:

new webpack.optimize.UglifyJsPlugin({
    compress: {
        warnings: true
    },
    output: {
        comments: true
    },
    sourceMap: false
}),

Another interesting experiment is to import a library like Angular Material into the AppModule without using it at all. Normally, one would expect that it is tree shaken but for the reason discussed here this leads to a bigger bundle.

Further information about this can be found inside the issues of webpack and rollup.

The myth about smaller bundles

In general, one would expect smaller bundles as the result of AOT and Tree Shaking. While this should be true for tree shaking, AOT compiles templates down to JavaScript code that is bigger. In small projects this isn't necessarily noticed, as the usage of AOT allows for omitting the code for JIT compilation. But with a growing number of templates the increase in file size due to the larger emitted JavaScript code outweighs this.

Update: This got much better with Angular 4. 

SASS and other Stylesheet Languages

As we found out, there is also an issue when using the AOT compiler together with SASS and SCSS. It cannot deal with it and yields errors. The webpack-plugin discussed here automatically deals with this situation when there is a webpack loader for it.

Libraries need to support AOT and Tree Shaking

In order to shake unused code off from libraries and to use them with AOT, they also have to support it. This not only means that they have to provide the code using EcmaScript Modules. They also have to provide some meta data, especially meta data for Angular's AOT compiler.

None other than Minko Gechev wrote a wonderful article about this. At the end, it also provides a check list with all the things one should consider.