【问题标题】:angular 9 - module lazy loading in production mode not workingangular 9 - 生产模式下的模块延迟加载不起作用
【发布时间】:2020-06-30 15:15:23
【问题描述】:

我有一个库项目,其中有一个模块和几个组件。在我的实际应用程序中,我想动态加载库模块并渲染组件。在开发模式下一切正常,但是当我以生产模式运行我的应用程序时,总是从工厂获取空的组件数组(使用 moduleFactory.componentFactories)。下面是我的代码。任何人都可以帮我解决这个问题。我正在使用 Angular 9.1.0。

import { Injectable, Type, Compiler, Injector, ComponentFactory, NgModuleFactory } from '@angular/core';
import { Observable, of } from 'rxjs';
import { delay, tap } from 'rxjs/operators';
import { ApptorCustomCompHostComponent } from '@apptor/corecomps';

@Injectable({
  providedIn: 'root',
})
export class LazyLoaderService {
  private modules: Map<string, any> = new Map();
  private componentRegistry: any[] = [
    { type: "textbox", className: "ApptorCorecompsWrapperComponent", moduleName: "ApptorCorecompsModule" }
    ];
  constructor(private compiler: Compiler, private injector: Injector) {

  }

  public async getComponentFactory(componentType: string): Promise<ComponentFactory<any>> {
    let compInfo = this.componentRegistry.find(c => c.type === componentType);
    if (compInfo) {
      let factories = this.modules.get(compInfo.moduleName);
      if (!factories) {
        await this.loadModule(compInfo.moduleName);
        factories = this.modules.get(compInfo.moduleName);
      }
      let componentFactory = factories.find(f => compInfo.className === f.componentType.name);
      return componentFactory;
    }
    return null;
  }


  async loadModule(moduleName: string) {
    switch (moduleName) {
      case 'ApptorCorecompsModule':
        this.loadModuleInternal(moduleName, await import('@apptor/corecomps').then(m => m[moduleName]));
        break;
      case 'lazy':
        this.loadModuleInternal(moduleName, await import('@apptor/corecomps').then(m => m[moduleName]));
        break;

    }
  }

  private loadModuleInternal(moduleName: string, moduleType: Type<any>) {
    const moduleFactory = this.compiler.compileModuleAndAllComponentsSync(moduleType);
    const componentFactories = moduleFactory.componentFactories;
    this.modules.set(moduleName, componentFactories);
    console.log("module loaded is: ", moduleName);
  }
}

【问题讨论】:

标签: lazy-loading production-environment angular9


【解决方案1】:

我们使它的工作如下。希望这可以帮助其他人。

import { Injectable, Compiler, Injector, ComponentFactory, ComponentFactoryResolver } from '@angular/core';
import { ReplaySubject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class LazyLoaderService {
  private modules: Map<string, ReplaySubject<any>> = new Map();
  private componentRegistry: any[] = [
    { type: "textbox", className: "ApptorCorecompsWrapperComponent", moduleName: "ApptorCorecompsModule" }
  ];
  constructor(private compiler: Compiler, private injector: Injector,
    private factoryResolver: ComponentFactoryResolver) {

  }

  public async getComponentFactory(componentType: string): Promise<ComponentFactory<any>> {
    //this.loadComponent();
    const compInfo = this.componentRegistry.find(c => c.type === componentType);
    if (!compInfo)
      throw new Error("Invalid component type:" + componentType);

    let modSubject = this.modules.get(compInfo.moduleName);
    if (!modSubject) {
      modSubject = this.loadModule(compInfo.moduleName);
    }
    let ret: Promise<ComponentFactory<any>> = new Promise((resolve, reject) => {
      modSubject.subscribe(async (moduleRef) => {
        //await this.compileModule(mod);
        const compType = moduleRef.instance.controls[compInfo.className];
        if (compType) {
          let componentFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(compType);
          // let componentFactory =  this.factoryResolver.resolveComponentFactory(compType);

          resolve(componentFactory);
        } else {
          console.error("Component :" + compInfo.className + " not found");
          reject(null);
        }
      });

    });
    return ret;


  }

  public loadModule(moduleName): ReplaySubject<any> {
    //let mod:any = null;
    let mod: ReplaySubject<any> = new ReplaySubject();

    switch (moduleName) {
      case 'ApptorCorecompsModule':
        import('@apptor/corecomps').then(async m => {
          let mm = m[moduleName]
          mm = await this.compileModule(mm);
          mod.next(mm);
          //return mm; 
        });
        break;
    }
    if (mod) {
      this.modules.set(moduleName, mod);
      return mod;
    }
    else {
      console.error("Failed to load module: " + moduleName);
      throw new Error("Failed to load module: " + moduleName);
    }
  }
  private async compileModule(module: any) {
    let ret: Promise<any> = new Promise((resolve, reject) => {
      this.compiler.compileModuleAsync(module).then(factory => {

        const moduleRef = factory.create(this.injector);
        resolve(moduleRef);
      });
    });
    return ret;
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    相关资源
    最近更新 更多