Libraries sometimes depend on tsickle decorator downleveling
See original GitHub issueπ bug report
Affected Package
The issue is caused by package @angular/....@angular/compiler-cli
/ @angular/bazel
Is this a regression?
No
Description
Angular applications which are built with NGC but arenβt setting up tsickle
for decorator downleveling (e.g. donβt set the annotationsAs: "static fields"
), canβt be rendered on the server if DOM-specific types are referenced on class members which are decorated.
e.g.
@Directive(...)
export class MyDirective {
@Input() triggerElement: HTMLElement;
}
This results in the following ES5 JavaScript output if tsickle
is not enabled
__decorate([
core_1.Input(),
__metadata("design:type", HTMLElement)
], MyDirective.prototype, "triggerElement");
Notice how the __decorate
call tries to access HTMLELement
from a global context. This causes an exception when the following file is executed in NodeJS since DOM APIs are not available. We mock most of the DOM APIs with domino
but providing these mocks globally so that such failures can be avoided is not common right now.
Building the project with tsickle fixes the problem automatically as decorators are downleveled into a static field while tsickle
also discards the type reference to HTMLElement
(as it is not relevant for Angular).
MyDirective.propDecorators = {
triggerElement: [{ type: core_1.Input }]
};
TL;DR:
- Everything currently works as expected within the CLI since it provides optimizations that removes the decorators anyway when using AOT mode or build-optimizer.
- It becomes an issue if a project is not built with the CLI / and does not use build-optimizer. Previously tsickle was part of the NGC workflow by default⦠so it now causes unexpected failures. Needs documentation? See: https://github.com/angular/angular/commit/29761ea5f8e4bae68442236f4a0abc1666487a35
How is Angular Bazel affected?
With Bazel it is not possible to opt-in for tsickleβs decorator downleveling. Tsickle can be enabled by passing the bazelOptions: {tsickle: true}
, but that comes with more tsickle transformations which arenβt desired. e.g. type imports are rewritten to goog.requireType
.
π¬ Minimal Reproduction
https://github.com/devversion/ngc-without-tsickle
π₯ Exception or Error
__metadata("design:type", HTMLElement)
^
ReferenceError: HTMLElement is not defined
π Your Environment
Angular Version:
Latest: 8.0.0-rc.4
Anything else relevant?
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:11 (10 by maintainers)
History: when we first needed decorator downleveling around Angular 2 timeframe, TS didnβt have CustomTransformers. tsickle was the closest thing available so we added the functionality there.
Now, it doesnβt make sense. tsickle should be βts to closureβ (thatβs where the name derives: ts2cl) and the decorator downleveling should be a transpile step for all Angular code. I wish it was baked right into tsc/ngc using CustomTransformer but I guess putting it in the webpack layer via angular/angular-cli#14473 is our short-term answer to keep forwardRef working in target=es2015
Also of interest is that TypeScript has an alternative format for the metadata that uses arrow functions. However, it is disabled via a hardcoded constant. https://github.com/microsoft/TypeScript/blob/master/src/compiler/transformers/ts.ts#L1659