Skip to content

Libraries sometimes depend on tsickle decorator downleveling #30586

@devversion

Description

@devversion

🐞 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:

  1. Everything currently works as expected within the CLI since it provides optimizations that removes the decorators anyway when using AOT mode or build-optimizer.
  2. 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: 29761ea

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?

Metadata

Metadata

Assignees

Labels

area: bazelIssues related to the published `@angular/bazel` build rulesarea: compilerIssues related to `ngc`, Angular's template compilerfreq3: highhotlist: components teamRelated to Angular CDK or Angular Materialtype: bug/fix

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions