I have several modules that I want to lazy load dynamically, I am upgrading from v8 to v9, with the version 9 of angular the logic concerning modules seems to have changed. What is the best way of doing it ?
define where we want to load our component in the template with the ng-template tag, define its view query through ViewChild decorator, which gives us access to the DOM and defines the container to which the component will be added, finally, dynamic import the component and add it to the container.
To lazy load Angular modules, use loadChildren (instead of component ) in your AppRoutingModule routes configuration as follows. content_copy const routes: Routes = [ { path: 'items', loadChildren: () => import('./items/items. module'). then(m => m.
Why do we need Lazy Loading in Angular 4? Lazy loading is a technique in Angular that allows you to load JavaScript components asynchronously when a specific route is activated. It improves the speed of the application load time by splitting the application into several bundles.
If we want to lazy-load a component dynamically (with no module), then we can use the same pattern as with routes :
// <ng-template #myContainer></ng-template>
@ViewChild('myContainer', { read: ViewContainerRef }) container: ViewContainerRef;
const { MyLazyComponent } = await import('./path/to/lazy/component');
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(MyLazyComponent);
const { instance } = this.container.createComponent(componentFactory);
If the component depends on other services / components then we need to load the full module. Because it will be lazy loaded (not compiled initially) we need to run the compilation "manually". It is still easier than previous tricks used on previous versions of Angular. Here is a solution.
We can create a service that store module references, and load the component into a container (given a module ID and a container reference).
import { Injectable, Compiler, Injector } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LazyComponentService {
private componenttRefs = {
myFirstLazyModuleId: import('../path/to/first/lazy/module/component.module'),
mySecondLazyModuleId: import('../path/to/second/lazy/module/component.module')
};
constructor(
private compiler: Compiler,
private injector: Injector,
) { }
async loadComponent(moduleId, container) {
let ref;
try {
const moduleObj = await this.componenttRefs[moduleId];
const module = moduleObj[Object.keys(moduleObj)[0]];
const moduleFactory = await this.compiler.compileModuleAsync(module);
const moduleRef: any = moduleFactory.create(this.injector);
const componentFactory = moduleRef.instance.resolveComponent();
ref = container.createComponent(componentFactory, null, moduleRef.injector);
} catch (e) {
console.error(e);
}
return ref;
}
}
Modules need to be compiled. We do it by calling resolveComponentFactory inside each module's constructor :
@NgModule({
imports: [
MyModules...
],
declarations: [
MyFirstLazyComponent
]
})
export class MyFirstLazyComponentModule {
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
public resolveComponent(): ComponentFactory<MyFirstLazyComponent> {
return this.componentFactoryResolver.resolveComponentFactory(MyFirstLazyComponent);
}
}
And then the magic is up, you can dynamically lazy load a component to a container :
const myFirstLazyComponent = await this.lazyComponentService.loadComponent(myFirstLazyModuleId, containerRef);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With