This post describes how to implement lazy or dynamic module loading with angular, based on an Angular 10 demo implementation, and is an extension to the former post I created on lazy-loading components and services.
In the daily business of a Software Engineer, the time comes when some modules, components, or services have to be loaded asynchronously at runtime. For instance to implement some sort of dynamic feature switches or something like that.
In order to manually lazy-load modules, I’ve created a service component DynamicModuleLoaderService
that dynamically loads and compiles an Angular module.
import {Compiler, Injectable, Injector, NgModuleFactory, NgModuleRef} from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DynamicModuleLoaderService {
constructor(private compiler: Compiler, private injector: Injector) {
console.log('Dynamic Module Loader is loaded!');
}
loadModule(m: any): Promise<NgModuleRef<any>> {
return m.then(elementModuleOrFactory => {
if (elementModuleOrFactory instanceof NgModuleFactory) {
// if ViewEngine
return elementModuleOrFactory;
} else {
// if Ivy
return this.compiler.compileModuleAsync(elementModuleOrFactory);
}
}).then(moduleFactory => moduleFactory.create(this.injector))
}
}
This service component can be loaded dynamically as described in the former post. To load the module reference using DynamicModuleLoaderService
you have to pass the path of the module.
Using the module reference the module componentes can be created like discussed in the Dynamic Component and Service Loading post.
async lazyLoadModule() {
if (!this._moduleLoader) {
this._moduleLoader = this.injector.get(DynamicModuleLoaderService);
}
this._lazyLoadedModule =
await this._moduleLoader.loadModule(import('./components/dynamic-module/dynamic.module')
.then(m => m.DynamicModule));
// lazy load component of module (can also be done inside the module. e.g exported components using static references)
const dynamicModuleComponentFactory = this._lazyLoadedModule.componentFactoryResolver.resolveComponentFactory(DynamicModuleComponent);
this._dynamicInstanceRefs.push(
this.dynamicModuleContainer.createComponent(dynamicModuleComponentFactory, null));
}