Tree Shaking Decorators in Angular

- JavaScript Developer and Blogger
Published: Wed Mar 01 2017

In this post I will talk about some of the issues with Tree Shaking of decorators.

Angular uses decorators to define component metadata like template(Url), selector, providers and styles. The compiler depends on this metadata to compile your Angular components.

When doing JiT compilation the decorators are needed at runtime since compilation happens at runtime. However, for AoT builds the decorators are only needed at build time since there is no compilation at runtime.

This means there is no need to include the decorators in AoT builds. However, currently there is no easy way to remove decorators from the final application bundle.

Why are the decorators included in AoT builds?

The issue is that decorators transpile down to code that is difficult to Tree Shake for bundlers like Rollup and Webpack.

Let's take a look at a typical Angular component.

@Component({ selector: 'lazy-loaded', templateUrl: './lazy-loaded.html' }) export class LazyLoaded {}

The above component metadata compiles down to the following JavaScript:

LazyTreeView.decorators = [ { type: Component, args: [{ templateUrl: './tree-view.html', // a template would make this worse selector: 'lazy-tree-view' },] }, ];

As you can see the metadata is pretty much the same in the JavaScript version.

In an AoT build there is no need for any of this metadata. It was all resolved during compilation. My example is a pretty small example, but imagine a much larger component with an inlined template. In a large application the extra decorators could potentially add up in bytes.

What can we do to about it?

Luckily the Angular team is looking into this. We might actually have this resolved by the time Angular 4 goes live.

In the meantime you can attempt to write your own Rollup or Webpack plugin to remove the decorators yourself. I would probably not recommend this though, unless you have a huge application where this actually represents an issue. For fun I added a simple plugin to my own demo project. It removed the decorators, but the savings was only 4k after gzip, so probably not worth the effort.

Another option is to use the Closure compiler for bundling since it is already able to shake out the decorators. The closure compiler is still a bit experimental with Angular though.

I invite you to follow me on twitter