我使用Angular@5.1.0遇到了AOT构建问题。
错误是:
ERROR in Error during template compile of 'AppModule'
Function calls are not supported in decorators but 'FeatureModule' was called.
feature.module.ts
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([])
],
declarations: [
...
],
exports: [
...
]
})
export class FeatureModule{
static forRoot(items:any[]): ModuleWithProviders {
const routes:Routes = items.map(t=> {
return { path: t.name, component: t.component };
});
return {
ngModule: FeatureModule,
providers: [
provideRoutes(routes)
]
}
}
}
这在非aot构建中成功编译。这似乎只是AOT构建的一个问题。
为什么会发生这种错误?
答案 0 :(得分:4)
好的,我花了一段时间才弄明白这一点。
TLDR:forRoot
方法必须简单,否则AOT编译器会抱怨。
为了简单起见,我不得不:
从forRoot
方法中删除分支逻辑和函数调用。
实现逻辑以将项目映射到工厂提供程序的路由,而不是在forRoot
方法内嵌入它。
使用Router.resetConfig
在工厂插件中动态添加路由。
添加ANALYZE_FOR_ENTRY_COMPONENTS提供程序,以便传入的任何组件都会作为模块的一部分自动添加到entryComponents
。
将RouterModule.forChild([])
导入FeatureModule
,因为我使用@angular/router
中的组件。
将RouterModule.forRoot([])
导入AppModule
,因为它提供了应用程序范围的Router
服务。
export const Items = new InjectionToken<any[]>('items');
export function InitMyService(router:Router, items:any[]) {
var routes:Routes = items.map(t=> { return { path: t.name, component: t.component, outlet: 'modal' }});
var r = router.config.concat(routes);
router.resetConfig(r);
return new MyService(router);
}
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([])
],
declarations: [
MyComponent
],
exports: [
MyComponent
],
providers: [
]
})
export class FeatureModule {
static forRoot(items:any[]): ModuleWithProviders {
return {
ngModule: FeatureModule,
providers: [
{ provide: Items, useValue: items},
{ provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: items},
{ provide: MyService, useFactory: InitMyService, deps:[Router, Items] }
]
}
}
}
<强> app.module.ts 强>
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([]),
FeatureModule.forRoot([{name: 'test', component: TestComponent}])
],
declarations: [ AppComponent, TestComponent ],
bootstrap: [ AppComponent ],
providers: [
],
exports: [AppComponent]
})
export class AppModule {
}
解决这个问题的关键是认识到RouterModule.forChild()
没有注册任何路由器服务。这是故意的,因此任何模块都可以导入RouterModule并利用其组件,而无需实际注册任何服务。在AppModule级别,我仍然需要通过将Router
导入AppModule来将RouterModule.forRoot()
服务注册为单身人士。