静态forRoot有参数时,AOT构建期间FeatureModule失败 [英] FeatureModule fails during an AOT build when static forRoot has arguments

查看:93
本文介绍了静态forRoot有参数时,AOT构建期间FeatureModule失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Angular@5.1.0遇到AOT构建问题。

I am encountering an AOT build issue using Angular@5.1.0.

错误是:

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版本中成功编译。

This compiles successfully in non-aot builds. This seems to only be a problem for AOT builds.

为什么会发生此错误?

Why is this error happening?

推荐答案

好的,我花了一些时间才弄清楚。
TLDR: forRoot 方法必须完全简单,否则AOT编译器会抱怨。

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:


  1. 删除 forRoot 方法中的分支逻辑和函数调用。

  1. Remove branching logic and function calls from the forRoot method.

实施将商品映射到路线到工厂提供者的逻辑,而不是将其内联到 forRoot 方法。

Implement the logic to map the items to routes into a factory provider, rather than inlining it inside the forRoot method.

使用 Router.resetConfig 在工厂实现内动态添加路由。

Use Router.resetConfig to add the routes dynamically within the factory impelmentation.

添加一个ANALYZE_FOR_ENTRY_COMPONENTS提供程序,以便将传入的任何组件自动添加到 entryComponents 作为模块的一部分。

Add an ANALYZE_FOR_ENTRY_COMPONENTS provider so that any components passed in would be added to entryComponents automatically as part of the module.

RouterModule.forChild([])导入 FeatureModule 因为我使用的是 @ angular / router 中的组件。

Import RouterModule.forChild([]) into FeatureModule because I use the components from @angular/router.

RouterModule.forRoot([])导入 AppModule ,因为它提供了应用程序范围的 Router 服务。

Import RouterModule.forRoot([]) into AppModule because it provides the application-wide Router service.



最终解决方案



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 {
}

解决此问题的关键是认识到 RouterModule.forChild()不注册任何路由器服务。这是有意的,因此任何模块都可以导入RouterModule并利用其组件,而无需实际注册任何服务。在AppModule级别上,我仍然需要通过将 RouterModule.forRoot()导入到单个服务器中来注册 Router 服务。 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.

这篇关于静态forRoot有参数时,AOT构建期间FeatureModule失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆