Class Decorator prevents tree-shaking
See original GitHub issueCommand
build
Is this a regression?
- Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
No response
Description
A library component with a (non-Angular) decorator will not be tree-shaken. The same component, if inside an app, will be properly tree-shaken.
There is a history of issues related to this topic:
- https://github.com/angular/angular-cli/issues/14610 This matches the topic exactly. According to the issue and the linked PR this might be a regression
- https://github.com/angular/angular-cli/issues/20714#issuecomment-842368726 (links to a comment) This seems to say that all decorators are always assumed to be side-effect free, but it looks like this is not the case anymore
- https://github.com/angular/angular-cli/issues/15396#issuecomment-523552252 (links to a comment) There seemed to be a problem with custom libraries, but in my repro everything comes straight from the angular-cli
- https://github.com/angular/angular-cli/issues/16246#issuecomment-557440527 (links to a comment) This also sounds like this was fixed in the past, hinting yet again that this might be a regression
Minimal Reproduction
Reproduction repository: https://github.com/fischeversenker/ng-decorator-tree-shaking/tree/274524fde27002e87f1535ef6bbef2cf8088ec8d
The essence:
This library code:
import { Component } from '@angular/core';
/*@__PURE__*/
function noopDecoratorFactory() {
return /*@__PURE__*/ (target: any) => target;
}
@noopDecoratorFactory()
@Component({
selector: 'lib-my-library',
template: `my-library works!`
})
export class MyLibraryComponent {}
turns into this:
let MyLibraryComponent = class MyLibraryComponent {
};
// ...
MyLibraryComponent = __decorate([
noopDecoratorFactory()
], MyLibraryComponent);
which seems to not be tree-shakeable.
Exception or Error
No response
Your Environment
Angular CLI: 14.2.6
Node: 16.16.0
Package Manager: yarn 1.22.19
OS: linux x64
Angular: 14.2.7
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1402.6
@angular-devkit/build-angular 14.2.6
@angular-devkit/core 14.2.6
@angular-devkit/schematics 14.2.6
@angular/cli 14.2.6
@schematics/angular 14.2.6
ng-packagr 14.2.2
rxjs 7.5.7
typescript 4.7.4
Anything else relevant?
The real-life use case where this adds huge amounts of unused code to our bundles is when using https://github.com/ngneat/until-destroy#use-with-ivy in library components.
Issue Analytics
- State:
- Created a year ago
- Reactions:2
- Comments:5 (2 by maintainers)
Top Results From Across the Web
File / class deleted during tree shake despite the fact it's being ...
Tree-shaking will remove unused side-effect free code. In Angular custom decorators on classes are treated to be side effect free meaning ...
Read more >Tree Shaking - webpack
Tree shaking is a term commonly used in the JavaScript context for dead-code elimination. It relies on the static structure of ES2015 module...
Read more >dart - how can I prevent class and its members from being tree ...
I would like to make sure that a class and all its members are not tree shaken when compiled with Dart2JS.
Read more >Tree-Shaking Problems with Component Libraries - Medium
Tree-shaking isn't magic, and much like the garbage collector, ... will prevent your components from being tree-shaken.
Read more >Tree-Shaking: A Reference Guide - Smashing Magazine
Tree-shaking” is a must-have performance optimization when ... They're main purpose is to prevent repetition and to leverage reusability.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Why is this not added by default? Angular-CLI (I’m assuming ng-packagr) adds this flag to a library’s “built” package.json, so it already automatically assumes that any Angular library is side-effect-free. Why is the same not true when importing from the source directly?
Indeed the flag is added automatically by ng-packagr unless it’s already specified.
When importing the source directly you effective no longer have a library in terms of a compilation unit and boundary rules. Rather an additional directory in the application with a nested package manifest file.
Overall, It is not recommended to build the library as part of the application either through path mapping or depending directly on the source file. This is also highlighted in the docs here: https://angular.io/guide/creating-libraries#building-and-rebuilding-your-library
Other than the above, there might also be cases when consuming the so called “library” as described above could result in a slow build and increase in bundle size due to the fact that the “library” ESM modules are not flattened (FESMs).
Also, the library in my reproduction repository got created with ng generate library … Would you consider adding “sideEffects”: false to the package.json template?
I am okay with that. Although we do expect libraries to be built prior to being consumed in an application.
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.