Angular-cli: Tree-shaking not working properly

Created on 26 Oct 2016  路  14Comments  路  Source: angular/angular-cli

I've been testing a bit with the production bundling, and the tree-shaking is not working as I would expect it to. I'm new at the tool, so perhaps I am misunderstanding what it is supposed to do, but the behaviour seems odd to me.

The problem:
Classes that are neither imported nor used are still included in the bundle.

I started a completely clean angular-cli project and created a new file. In this file I created two classes, Foo and Bar. I then, inside app.component.ts import the first of these classes.
import { Foo } from './some.service';

When then creating a production build I assumed that the class Bar would be removed, since it is never imported or used. But it isn't, it's included in the minified bundle. The same happens if I split the classes into one file each and then use a barrel (e.g. index.ts) and import Foo from there.

Am I misunderstanding tree shaking or is this behaviour incorrect? Or do I have to change some setting somewhere to activate it?

This is on Mac OSX - El Capitan and using beta17.

1 (urgent) bufix faq

Most helpful comment

@hansl I believe this issue should be re-opened to track. angular-cli currently promises to deliver low-configuration treeshaking, which is one of our motivations for using it. If webpack doesn't get it together it's reasonable to make a call to either switch to rollup or remove the expectation of treeshaking.

All 14 comments

Hi @HonnKing , AFAIK, the aot compiler does not do tree-shaking.

Tree-shaking is done in a process later in your build pipeline.

Might be, but then the documentation needs to be updated.

"All builds make use of bundling, and using the --prod flag in ng build --prod or ng serve --prod will also make use of uglifying and tree-shaking functionality."

I'm sorry, I was talking about the aot compiler.... But yes, the Angular-CLI makes use of tree shaking. This is automatically done in Webpack (which is what the CLI is using)

I'm sorry for the confusion ;)

Tree shaking definitely should be present. This is something we need to investigate.

My test was similar to yours, I created src/app/tree-shaking-test.ts with the following content:

export class Foo {
  name = 'foo class';
}

export class Bar {
  name = 'bar class';
}

Then added the following to src/app/app.module.ts:

import { Foo } from './tree-shaking-test';

console.log(Foo);

Ran ng build and could find this block inside of dist/main.bundle.js:

"use strict";
/* harmony export (binding) */ __webpack_require__.d(exports, "a", function() { return Foo; });
/* unused harmony export Bar */
var Foo = (function () {
    function Foo() {
        this.name = 'foo class';
    }
    return Foo;
}());
var Bar = (function () {
    function Bar() {
        this.name = 'bar class';
    }
    return Bar;
}());

ng build --prod yielded a similar code block, with both "foo class" and "bar class":

function(t,e,n){"use strict";n.d(e,"a",function(){return r});var r=function(){function t(){this.name="foo class"}return t}();(function(){function t(){this.name="bar class"}return t})()}

Ok there's an issue on Webpack for this: https://github.com/webpack/webpack/issues/2899. I'll keep an eye on it.

@filipesilva Any updates?
Without tree shaking I'm ending up with a prod build for main.bundle.js of 2.5MB, so it is a very large issue.

Similarly to @trevorfrese I'm interested in any progress on this, anything new?

@trevorfrese @lbialy I don't have any updates, just watching the issue.

@TheLarkInn is there any update on your end?

any solution for the problem? Or should I use rollup after building the build thought Angular-cli ?

Closing this as this is a webpack issue and there are fixes being discussed on their side.

@hansl I believe this issue should be re-opened to track. angular-cli currently promises to deliver low-configuration treeshaking, which is one of our motivations for using it. If webpack doesn't get it together it's reasonable to make a call to either switch to rollup or remove the expectation of treeshaking.

The official recommendation from the Angular team is to ship custom libraries as a Flat ES Module generated with rollup. Nevertheless, even exporting libraries as a Flat ES Module, while also avoiding Kitchen Sink modules, importing one module from the FESM would result in the whole library being imported into the final bundle. I know this is particular to Webpack treeshaking not working properly, just wanted to give some input about this, it's still happening.

Edit:
Seems that the Angular team is working on how to properly publish FEMS to allow tree shaking: https://github.com/angular/material2/issues/4137#issuecomment-295012663

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings