Angular 8 CLI:如何使用提供程序延迟加载不可路由的功能模块

时间:2019-06-07 09:14:23

标签: angular

那么嘿,

我试图遵循以下指南: https://angular.io/guide/lazy-loading-ngmodules

但是官方文档仅使用Router对此进行了介绍(哇!Qngular文档不是最佳选择)

https://netbasal.com/the-need-for-speed-lazy-load-non-routable-modules-in-angular-30c8f1c33093

所以这篇中篇文章正是我在寻找的内容。我唯一的问题是它将无法正常工作。

ANGULAR.JSON

"architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "lazyModules": [
              "path/to/components#MyModule"
            ],

APP模块

 providers: [
    SystemJsNgModuleLoader, // without this I get NullInjectorError
    CookieService,
    { provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader }, // this doesnt seem to do anything
    {
      provide: HTTP_INTERCEPTORS, useClass: AuthHeaderInterceptor, multi: true,
    }
  ],
  bootstrap: [AppComponent]

模块

@NgModule({
  imports: [
    CommonModule,
    MatButtonModule,
    MatIconModule,
  ],
  declarations: [
    MyModule.rootComponent
  ],
  providers: [MyService],
  entryComponents: [MyModule.rootComponent]
})
export class MyModule{
  static rootComponent = MyComponent;
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: MyModule,
      providers: [MyService]
    };
  }
}

服务

@Injectable()
export default class MyService {}
...

延迟加载提供者

export interface LAZY_MODULES {
  'MyModule': string;
}

export const lazyMap: LAZY_MODULES = {
  'MyModule': 'path/to/components#MyModule'
};

export const LAZY_MODULES_MAP = new InjectionToken('LAZY_MODULES_MAP', {
  factory: () => lazyMap
})

无效负载指令

@Directive({
  selector: '[lazyLoadModule]'
})
export class LazyLoadModuleDirective implements OnInit, OnDestroy {

  @Input('lazyLoadModule') moduleName: keyof LAZY_MODULES;
  private moduleRef: NgModuleRef<any>;

  constructor(
    private vcr: ViewContainerRef,
    private injector: Injector,
    private loader: NgModuleFactoryLoader,
    @Inject(LAZY_MODULES_MAP) private modulesMap
  ) { }

  ngOnInit() {
    this.loader
      .load(this.modulesMap[this.moduleName])
      .then((moduleFactory: NgModuleFactory<any>) => {
        this.moduleRef = moduleFactory.create(this.injector);
        const rootComponent = (moduleFactory.moduleType as ModuleWithRoot)
          .rootComponent;

        const factory = this.moduleRef.componentFactoryResolver.resolveComponentFactory(
          rootComponent
        );

        this.vcr.createComponent(factory);
      });
  }

  ngOnDestroy() {
    this.moduleRef && this.moduleRef.destroy();
  }
}

在APP组件HTML中

<ng-container *ngIf="showModule"
              lazyLoadModule="MyModule">
</ng-container>

所以结果是:

  1. 如果我在不使用包装对象的情况下使用SystemJsNgModuleLoader,则 Chunking可以(Webpack报告它正在构建 path-to-components-my-module.ts )在开发工具中,我得到SystemJsNgModuleLoader的NullinjectorError

  2. 如果我直接在提供程序中使用SystemJsNgModuleLoader,则在开发控制台中不会出现错误。分块作品也。但是在网络控制台中,即使我直接在应用程序控制器中将showModule = true设置为模块也不会加载

1 个答案:

答案 0 :(得分:0)

以上示例有效。该指南只是假设每个人都记得将加载程序组件添加到根模块中。

有趣的是,没有引发任何错误(因为它是指令,而不是元素),并且系统仅假定lazyLoadModule是允许的HTML属性?固定方式:

@NgModule({
  declarations: [
    ...,
    LazyLoadModuleDirective
  ]
  ...