I am encountering an AOT build issue using Angular@5.1.0.
The error is:
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)
]
}
}
}
This compiles successfully in non-aot builds. This seems to only be a problem for AOT builds.
Why is this error happening?
Ok, it took me a while to figure this out.
TLDR: the forRoot method must dead simple, otherwise the AOT compiler complains.
To make it simple, I had to:
Remove branching logic and function calls from the
forRootmethod.Implement the logic to map the items to routes into a factory provider, rather than inlining it inside the
forRootmethod.Use
Router.resetConfigto add the routes dynamically within the factory impelmentation.Add an ANALYZE_FOR_ENTRY_COMPONENTS provider so that any components passed in would be added to
entryComponentsautomatically as part of the module.Import
RouterModule.forChild([])intoFeatureModulebecause I use the components from@angular/router.Import
RouterModule.forRoot([])intoAppModulebecause it provides the application-wideRouterservice.
Final Solution
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 {
}
The key to solving this was the realization that RouterModule.forChild() does not register any router services. This is intentional so that any module can import the RouterModule and take advantage of its components, without actually registering any services. At the AppModule level, I still needed to register the Router service as a singleton by importing RouterModule.forRoot() into AppModule.
来源:https://stackoverflow.com/questions/47686638/featuremodule-fails-during-an-aot-build-when-static-forroot-has-arguments