Как избавиться от вызовов функций не поддерживается в декораторах в компиляции Angular aot?

Я тестирую Highcharts Angular2x Wrapper. Сначала у меня не было проблем с использованием функции Angular CLI (1.6.1) "ng serve" и профилирования с Chrome. Затем я попытался использовать компиляцию вовремя, чтобы увидеть, как это влияет на производительность.

Итак, используя:

ng serve --aot

Я получаю следующую ошибку:

ERROR in Error during template compile of 'AppModule'
  Function calls are not supported in decorators but 'ChartModule' was called.

Теперь я знаю, что aot генерирует заводский код для модулей и каким-то образом "превращает" шаблоны в VanillaJS, здесь все немного сложно, и я не мог понять, как ngc собирается генерировать заводский код для модуля, для которого требуется внешняя библиотека.

Я получил этот App.Module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ChartModule } from 'angular2-highcharts';

import { AppComponent } from './app.component';

declare var require: any;
export function getHighchartsModule() {
  return  require('highcharts');
}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ChartModule.forRoot(getHighchartsModule) // This causes the error
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Мои зависимости Package.json:

"dependencies": {
    "@angular/animations": "^5.0.0",
    "@angular/common": "^5.0.0",
    "@angular/compiler": "^5.0.0",
    "@angular/core": "^5.0.0",
    "@angular/forms": "^5.0.0",
    "@angular/http": "^5.0.0",
    "@angular/platform-browser": "^5.0.0",
    "@angular/platform-browser-dynamic": "^5.0.0",
    "@angular/router": "^5.0.0",
    "angular2-highcharts": "^0.5.5",
    "core-js": "^2.4.1",
    "rxjs": "^5.5.2",
    "zone.js": "^0.8.14"
  }

Мои вопросы: есть ли что-нибудь, что я могу сделать здесь, чтобы избежать упомянутой ошибки компиляции? Может ли кто-нибудь объяснить, почему это происходит? (необязательный)

Ответ 1

Упоминание о проблеме Github здесь. Следующее решение помогло мне.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

// Angular Highcharts Imports
import {HighchartsStatic} from 'angular2-highcharts/dist/HighchartsService'; 
import { ChartModule } from 'angular2-highcharts';

// Factory Function
export function highchartsFactory() {
  var hc = require('highcharts');
  return hc;
}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ChartModule // Import Module Here
  ],
  providers: [ // Provide Service Here
    {
      provide: HighchartsStatic,
      useFactory: highchartsFactory 
    },
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Ответ 2

Это проблема с угловым вообще. Angular компилятор хочет, чтобы код forRoot был полностью статичным.

Например, в следующем коде даже присвоение статической переменной с причиной этой ошибки:

static forRoot(config: MyConfig): ModuleWithProviders {
    MyConfigService.config = config;// This line with cause an error
    return {
      ngModule: HttpTrackerLibModule,
    };
  }

Если вы не являетесь создателем библиотеки, вы ничего не можете сделать, кроме как попробовать решения для конкретной библиотеки, подобные приведенному выше. Но если вы являетесь создателем библиотеки, вы можете попробовать статический подход следующим образом:

  1. Создать токен для инъекций:

    export const USER_OPTIONS = new InjectionToken<MyConfig>('USER_OPTIONS');

  2. Предоставьте токен в модуле вашей библиотеки

static forRoot(config: MyConfig): ModuleWithProviders {
            return {
                ngModule: HttpTrackerLibModule,
                providers: [{
                    provide: USER_OPTIONS,
                    useValue: config
                }],
            };
        }

Ответ 3

Я столкнулся с этой проблемой. Попробуйте удалить экспорт getHighchartsModule из App.Module.ts и поместите экспортированную функцию в свой собственный файл. Затем импортируйте его в App.Module.ts.

Я не понял, почему это происходит.