繁体   English   中英

如何摆脱 Angular aot 编译中装饰器不支持的函数调用?

[英]How to get rid of Function calls are not supported in decorators in Angular aot compiling?

我正在测试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"
  }

我的问题是:我可以在这里做些什么来避免提到的编译错误? 谁能解释为什么会发生这种情况? (可选)

这通常是 angular 的问题。 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 }], }; }

  1. 在其他地方使用 DI 使用令牌:

 export class ConfigService { constructor(@Inject(USER_OPTIONS) private _config: MyConfig) { } }

这里提到 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 { }

我遇到过同样的问题。 尝试删除getHighchartsModule从出口App.Module.ts并把导出的函数在它自己的文件。 然后将其导入App.Module.ts

我还没有弄清楚为什么会发生这种情况。

如果它可以帮助人们克服错误,我想提出一个额外的答案。 我在Angular 11上有两个几乎相同的应用程序,它们共享相同的库模块,该模块具有用于自定义注入配置的static forRoot方法声明。

@NgModule()
export class TheModule {
  static forRoot(...) {
   ... 
  }
}

App A 按预期工作,App B 抛出了有问题的错误。 当然,我的两个应用程序本质上是不同的,所以这将其缩小到infrastructureconfiguration差异。

调查

查看共享模块的compiled代码,例如the-module.module.d.ts以查看是否存在差异:

从工作应用的范围来看:

// the-module.module.d.ts
import * ...
...

export declare class TheModule {
    static ɵmod: ɵngcc0.ɵɵNgModuleDefWithMeta<TheModule, [typeof ɵngcc4.AComponent, ...]
    static ɵinj: ɵngcc0.ɵɵInjectorDef<TheModule>;
}

请注意emod (模块)和einj (注入)定义。

从损坏的应用程序的范围

它缺少这些定义:

// the-module.module.d.ts
export declare class TheModule {
}

好的,那么为什么损坏的应用程序的模块是空的!? 它必须是编译的东西! 查看根tsconfig.json

对于损坏的应用程序:

启用了以下angularCompilerOptions设置:

// woops, remove this to use the newer compiler for angular versions > 9.0
"angularCompilerOptions": {
    "enableIvy": false
 }

这是前几天留下的疤痕。 删除它后,错误消失了,它使编译器能够与共享库模块交互并填充其类型。

编译 AOT 时,请查看编译器选项文档: https : //angular.io/guide/angular-compiler-options以查看详细信息。 @AngularJs 打印的错误消息,将其视为decorator是一种“副作用”,并且不相关。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM