Angular 9 Universal改造中ngx-datable SSR配置问题求助
我之前在把Angular应用改成SSR的时候,也碰到过懒加载模块里ngx-datable服务端Helper不生效的问题,核心原因就是懒加载模块有自己独立的注入器,根模块里的提供者没法直接覆盖它。这里给你几个不用改动懒加载架构的解决方案:
这是最优雅的方案,因为你的项目已经在用SharedModule共享提供者,只需要扩展它来区分SSR和客户端环境:
修改SharedModule,添加
forRoot()静态方法
在SharedModule里定义一个接收环境标识的静态方法,根据传入的参数返回对应环境的提供者:import { NgModule, ModuleWithProviders } from '@angular/core'; import { ScrollbarHelper, DimensionsHelper } from '@swimlane/ngx-datable'; import { ServerScrollBarHelper, ServerDimensionsHelper } from './path-to-your-server-helpers'; @NgModule({ // 保留SharedModule原有的声明、导入、导出配置 }) export class SharedModule { static forRoot(isServer: boolean): ModuleWithProviders<SharedModule> { return { ngModule: SharedModule, providers: [ isServer ? { provide: ScrollbarHelper, useClass: ServerScrollBarHelper } : { provide: ScrollbarHelper, useClass: ScrollbarHelper }, isServer ? { provide: DimensionsHelper, useClass: ServerDimensionsHelper } : { provide: DimensionsHelper, useClass: DimensionsHelper } ] }; } }在客户端和服务端根模块分别调用
forRoot()- 客户端
AppModule里传入false:@NgModule({ imports: [ // 其他模块 SharedModule.forRoot(false) ] }) export class AppModule {} - 服务端
AppServerModule里传入true:@NgModule({ imports: [ AppModule, ServerModule, SharedModule.forRoot(true) ], bootstrap: [AppComponent] }) export class AppServerModule {}
- 客户端
这样所有懒加载模块导入SharedModule时,都会继承根注入器里配置的对应环境的Helper服务,完美解决独立注入器的问题。
方案二:在懒加载模块里动态判断平台提供服务
如果不想改动SharedModule,也可以在每个懒加载模块里通过PLATFORM_ID判断环境,动态生成服务实例:
import { NgModule } from '@angular/core'; import { ScrollbarHelper, DimensionsHelper } from '@swimlane/ngx-datable'; import { ServerScrollBarHelper, ServerDimensionsHelper } from './path-to-your-server-helpers'; import { PLATFORM_ID, Inject } from '@angular/core'; import { isPlatformServer } from '@angular/common'; @NgModule({ providers: [ { provide: ScrollbarHelper, useFactory: (platformId: object) => { return isPlatformServer(platformId) ? new ServerScrollBarHelper() : new ScrollbarHelper(); }, deps: [PLATFORM_ID] }, { provide: DimensionsHelper, useFactory: (platformId: object) => { return isPlatformServer(platformId) ? new ServerDimensionsHelper() : new DimensionsHelper(); }, deps: [PLATFORM_ID] } ] }) export class YourLazyLoadedModule {}
这个方案的缺点是如果有多个懒加载模块,需要重复配置,但胜在不需要改动共享模块的结构。
为什么之前AppServerModule配置不生效?
因为懒加载模块的注入器是子注入器,它会优先使用自己模块内注册的提供者,只有当找不到对应提供者时才会向上查找根注入器。而ngx-datable的默认Helper服务是在其自身模块里注册的,所以根注入器里的覆盖不会生效。而forRoot()模式会把提供者注册在根注入器的优先级位置,确保子注入器会优先使用根注入器的配置。
推荐优先使用方案一,一次配置就能覆盖所有模块,避免重复代码。
内容的提问来源于stack exchange,提问作者DejanG
相关产品推荐
相关产品推荐

