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.
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._
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.