Angular lazyload module без route
Ленивая загрузка (по мере необходимоси) помогает уменьшить начальные размеры js файлов, что, в свою очередь, помогает сократить время загрузки. В Angular основной способ загружать модули лениво - настроить их загрузку в зависимости от выбранного маршрута.
Используется Angular 8
const routes: Routes = [
{
path: 'customers',
loadChildren: () => import('./customers/customers.module').then(mod => mod.CustomersModule)
},
{
path: 'orders',
loadChildren: () => import('./orders/orders.module').then(mod => mod.OrdersModule)
},
];
Но что, если хочется управлять этим механизмом более гибко?
CLI-based lazy modules
Такая возможность есть в angular CLI. Предствим, что имеется модуль src\app\lazy\lazy.module.ts
с 3 компонентами.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OneComponent } from './one/one.component';
import { TwoComponent } from './two/two.component';
import { EntryComponent } from './entry/entry.component';
@NgModule({
declarations: [OneComponent, TwoComponent, EntryComponent],
entryComponents: [EntryComponent],
imports: [CommonModule],
})
export class LazyModule {
static rootEntry = EntryComponent;
}
Нужные компоненты для динамической отрисовки должны находится в массиве entryComponents
В файле настроек проекта angular.json
следуется поместить созданные модуль в массив lazyModules
(projects["<name-of-project>"].architect.build.options.lazyModules
)
...
"options": {
"outputPath": "dist/lazy-module-no-route",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"lazyModules": ["src/app/lazy/lazy.module"], <<=== вот сюда
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
},
...
Ну и немного магии: src\app\app.component.ts
@Component({
selector: 'app-root',
template: `<h1>Welcome!</h1><div #here></div>`,
})
export class AppComponent implements AfterViewInit, OnDestroy {
/** Экземпляр Модуля созданного через фабрику */
moduleRef: NgModuleRef<LazyModule>;
/** Контейнер для размещения динамического компонента */
@ViewChild('here', { read: ViewContainerRef, static: true })
here: ViewContainerRef;
constructor(private compiler: Compiler, private injector: Injector) {}
ngAfterViewInit(): void {
import('src/app/lazy/lazy.module')
.then(m => m.LazyModule)
.then(lazyModule => {
this.compiler.compileModuleAsync(lazyModule).then(ngModuleFactory => {
this.moduleRef = ngModuleFactory.create(this.injector);
const compFactory = this.moduleRef.componentFactoryResolver.resolveComponentFactory(
lazyModule.rootEntry
);
this.here.createComponent(compFactory);
});
});
}
ngOnDestroy(): void {
if (this.moduleRef) {
this.moduleRef.destroy();
}
}
}
- Загрузить модуль LazyModule
- Скомпилировать загруженный модуль
- Создать фабрику LazyModule модулей
- Из фабрики создать экземпляр модуля
- Из экземпляра модуля создать фабрику нужного компонента
- Из фабрики компонента создать компонент
- Прицепить компонент к какому-нибудь
ViewContainerRef
- Изи?
Пример на github
- https://www.dzurico.com/angular-lazy-load-modules-with-cli/
- https://medium.com/@matt.denobrega/for-those-of-you-who-implemented-this-and-are-getting-warnings-about-ngmodulefactoryloader-being-ae20ce1bca20
- https://netbasal.com/the-need-for-speed-lazy-load-non-routable-modules-in-angular-30c8f1c33093
- https://blog.angularindepth.com/asynchronous-modules-and-components-in-angular-ivy-1c1d79d45bd3