Search code examples
angularmoduleaotangular-lazyloading

How to compile the dynamic modules using AOT Compiler in Angular 8


I am using Angular 8 with AOT compiler. I need to compile the modules dynamically when I click the button.

In that module file, the component is declared.

Testingmodule.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CounterComponent } from './counter/counter.component';
import { FetchDataComponent } from './fetch-data/fetch-data.component';


@NgModule({
  declarations: [CounterComponent, FetchDataComponent],
  imports: [
    CommonModule



  ],
  exports: [
    CounterComponent, FetchDataComponent
  ],
  entryComponents: [CounterComponent, FetchDataComponent

  ]


})
export class TestingModule {
  public static components = {
    dynamicComponent: [CounterComponent, FetchDataComponent
    ]
  };
}

=========================================================================================

In component.ts

const mod = this.compiler.compileModuleAndAllComponentsSync(TestingModule);
console.log(mod);

=======================================================================================

In Appmodule.ts

import { NgModule, COMPILER_OPTIONS, CompilerFactory, Compiler } from '@angular/core';
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';

 providers: [

    { provide: COMPILER_OPTIONS, useValue: {}, multi: true },
    { provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
    { provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] }
  ],


export function createCompiler(compilerFactory: CompilerFactory) {
  return compilerFactory.createCompiler();
}

The above line is working locally, it shows the component factories of those modules.

But, when I run the code in the prod mode using ng serve --prod.

When I load the modules dynamically, it shows the below error.

enter image description here


Solution

  • In Angular 8,by default, the JIT compiler is used. If we enabled the AOT compiler manually,the above code is not working.

    If we disable the AOT and buildoptimizer to false, it will work, but the performance is very slow.

    The solution is we need to upgrade the Angular 9 and use the below code for lazyloading. In Angular 9, the default compiler is AOT.

    Create a service file:

    import { ComponentFactoryResolver, Injectable, ComponentFactory, Component } from '@angular/core';
    import { ContentTextBoxComponent } from '../contentTextBox/contentTextBox.component';
    
    @Injectable({
      providedIn: 'root'
    })
    export class SubLazyloadService {
    
      constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
    
    
      getComponentLoad(selectorname) {
     let dyn_comp_arr = [ContentTextBoxComponent]
    ];
    
        for (var i = 0; i < dyn_comp_arr.length; i++) {
          let loadcomp_arr: any = dyn_comp_arr[i];
          const factory: ComponentFactory<Component> = this.componentFactoryResolver.resolveComponentFactory(loadcomp_arr);
          if (factory.selector == selectorname) {       
            return factory;
          }      
        }
      }
     
    }
    

    In HTML file:

    <ng-template #dynamic></ng-template>
    

    In Component file:

     @ViewChild('dynamic', { static: true, read: ViewContainerRef }) private viewRef: ViewContainerRef;
    

    Inside the dynamic component load function

    import('../lazyloadmodules/lazyloading.module').then(({ LazyloadModule }) => {
            this.compiler.compileModuleAsync(LazyloadModule).then((moduleFactory) => {
              console.log(exerciseRef);
              const load_comp: ComponentFactory<Component> = this.lazyloadservice.getComponentLoad(exerciseRef);
              console.log(load_comp.componentType);
              this.viewRef.clear();
    
              const componentFactory = this.componentFactoryResolver.resolveComponentFactory(load_comp.componentType);
              console.log(componentFactory);
    
              const componentRef = this.viewRef.createComponent(componentFactory);
              this.currentExerciseRef = componentRef;
              this.currentExerciseRef.instance.id = inputRef;
            });
         
          });