ngParty / ng-metadata

Angular 2 decorators and utils for Angular 1.x

Home Page:https://hotell.gitbooks.io/ng-metadata/content/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Angular build optimizer throws error on decorators

aciccarello opened this issue · comments

The Angular CLI actually works pretty well with bundling hybrid ng-metadata applications. However the production build does not like 3rd party decorators (angular/angular#14323).

ERROR in legacy\my.module.ts(17,2): Error during template compile of 'MyModule'
  Only initialized variables and constants can be referenced in decorators because the value of this variable is needed by the template compiler in 'NgModule'
    'NgModule' references 'NgModule'
      'NgModule' references 'NgModule'
        'NgModule' is not initialized at ..\ng-metadata\src\core\directives\decorators.ts(233,22).

If possible ng-metadata should find a way to make the compiler happy and enable AOT on Angular components while keeping the Angular.js/ng-metadata components JIT.

I was able to get an AOT build working on my hybrid application by reimplementing the class decorators as simple functions with a helper function in the actual decorator function. The Angular compiler didn't complain about the parameter decorators.

export function annotateClass(target, annotationInstance) {
  if (annotationInstance instanceof InjectableMetadata) {
    annotationInstance.id = annotationInstance.id || globalKeyRegistry.get(target);
  }

  const annotations = reflector.ownAnnotations(target) || [];
  annotations.push(annotationInstance);
  reflector.registerAnnotations(annotations, target);

  return target;
}

export function Directive(params) {
  return function decorator(target) {
    return annotateClass(target, new DirectiveMetadata(params));
  }
}

The only problem is that the key registry was throwing a type error because one of the internal types was not exported.

ERROR in node_modules/ng-metadata/src/core/di/key.d.ts(1,41): error TS2304: Cannot find name 'KeyRegistry'.

It should be possible to write a PR which re-implements the decorators in a way which satisfies the angular compiler.

If anyones plagued by this.. we have a solution. It's NOT nice but we're actively moving from ng-metadata to ngUpgrade so it wasn't a big deal for us.

import * as m from 'ng-metadata/core';

const Injectable = m['Injectable' + ''];
const Inject = m['Inject' + ''];

I would advocate finding a better solution as I personally hate this but it worked for us.