简体   繁体   English

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

[英]Angular 8 CLI: How to lazy load non-routable feature module with providers

So hey, 嘿,

I tried to follow these guides: https://angular.io/guide/lazy-loading-ngmodules 我试着遵循这些指南: https//angular.io/guide/lazy-loading-ngmodules

But the official documentation only covers this with Router (just wow. Qngular docs are suboptimal) 但是官方文档只用Router来解决这个问题(哇哇.Qngular docs不是最理想的)

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

So this medium article was exactly what I was searching for. 所以这篇中篇文章正是我所寻找的。 My only problem is that it wont work. 我唯一的问题是它不会工作。

ANGULAR.JSON ANGULAR.JSON

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

APP MODULE APP MODULE

 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]

MODULE MODULE

@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]
    };
  }
}

SERVICE 服务

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

LAZY LOAD PROVIDER 懒惰的负载提供商

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

LAZY LOAD DIRECTIVE 懒惰的指令

@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();
  }
}

IN APP COMPONENT HTML 在APP组件HTML

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

so the result is: 结果是:

  1. If I am using th SystemJsNgModuleLoader without wrapper object, Chunking works (webpack reports that it build a path-to-components-my-module.ts ) In dev tools I get NullinjectorError for SystemJsNgModuleLoader 如果我使用没有包装器对象的SystemJsNgModuleLoader,则Chunking工作 (webpack报告它构建了一个路径到组件my-module.ts )在开发工具中我得到SystemJsNgModuleLoader的NullinjectorError

  2. If I am using the SystemJsNgModuleLoader directly in providers I dont get an error in dev console. 如果我直接在提供程序中使用SystemJsNgModuleLoader我在开发控制台中没有出错。 Chunking works also. Chunking也有效。 But in network console, the module never gets loaded , even if i directly set showModule=true in app controller... 但是在网络控制台中, 模块永远不会被加载 ,即使我直接在app控制器中设置showModule = true ...

The above example worked. 上面的例子很有效。 The guide was trivially assuming that everyone remembers to add the loader component the root module. 该指南非常简单地假设每个人都记得将加载程序组件添加到根模块。

Interestingly no error was thrown, (because it is a directive, not an element) and the system just assumed that lazyLoadModule is a permitted HTML attribute? 有趣的是没有抛出错误,(因为它是一个指令,而不是一个元素),系统只是假设lazyLoadModule是一个允许的HTML属性? ANyway fixed by: ANyway修正:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM