Создание своей стратегии загрузки в Angular
Недавно наткнулся на собеседовании наткнулся на вопрос, как создать свою стратегию загрузки. В интернете много примеров о том, как это делается для NgModule приложений, но для standalone примеров совсем немного. Что-ж, разберем этот вопрос детальнее.
В Angular есть несколько стратегий загрузки модулей и компонентов, которые позволяют оптимизировать работу приложения, особенно в больших проектах. Всего разработчику доступно 3 стратегии:
- NoPreloading. Отключает предзагрузку. Ленивая загрузка будет происходить только в момент перехода на соответствующий маршрут.
- PreloadingAllModules. Предзагружает все ленивые модули и компоненты, как только основное приложение будет загружено. Загрузка происходит в фоновом режиме, не блокируя основную инициализацию.
- RouterPreloader. Это механизм для создания кастомной стратегии предзагрузки, позволяющий вам определять, какие модули или компоненты должны быть предзагружены
Именно третья стратегия позволяет создать новую, для этого нужно класс реализующий интерфейс PreloadingStrategy:
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, of } from 'rxjs';
export class CustomPreloadingStrategy implements PreloadingStrategy {
preload(route: Route, load: () => Observable<any>): Observable<any> {
// Предзагружаем только те модули, где указан параметр data.preload === true
return route.data?.['preload'] ? load() : of(null);
}
}и сообщить приложению об имеющейся стратегии на момент загрузки приложения (main.ts) и зарегистрировать DI токен (можно так же через providedIn: 'root'):
import { provideRouter, withPreloading, RouterPreloader } from '@angular/router';
bootstrapApplication(AppComponent, {
providers: [
{ provide: RouterPreloader, useClass: CustomPreloadingStrategy }, // регистрируем токен
provideRouter(routes, withPreloading(CustomPreloadingStrategy)) // передаём в роутер стратегию
],
});Остаётся прописать флаг в роутингах, чтобы Angular знал что стоит предзагружать - а что нет.
const routes: Routes = [
{
path: 'important',
loadChildren: () => import('./important/important.module').then(m => m.ImportantModule),
data: { preload: true }, // Будет предзагружен
},
{
path: 'optional',
loadChildren: () => import('./optional/optional.module').then(m => m.OptionalModule),
data: { preload: false }, // Не будет предзагружен
},
];