Стратегии загрузки маршрутов

В Angular маршруты играют ключевую роль в построении одностраничных приложений. Управление маршрутами позволяет создавать динамические и гибкие веб-приложения. Одним из важных аспектов работы с маршрутами является стратегия их загрузки, которая определяет, когда и как загружать модули приложения. Angular предлагает несколько стратегий загрузки маршрутов, каждая из которых оптимизирует производительность по-разному.

Стратегии загрузки маршрутов

  1. Eager Loading (немедленная загрузка)

По умолчанию в Angular используется стратегия Eager Loading. В этом случае все модули, связанные с маршрутом, загружаются сразу при старте приложения. Это может привести к избыточной загрузке, если приложение содержит множество неиспользуемых маршрутов. Однако, в некоторых случаях такая стратегия подходит, когда приложение относительно небольшое, и все его части должны быть доступны с самого начала.

Пример использования Eager Loading:

const routes: Routes = [
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent }
];

Здесь оба компонента, HomeComponent и AboutComponent, будут загружены сразу при старте приложения, независимо от того, какой путь был выбран пользователем.

  1. Lazy Loading (ленивая загрузка)

Lazy Loading позволяет загружать модули только тогда, когда они действительно необходимы. Это значительно улучшает время начальной загрузки приложения, так как только критически важные части приложения подгружаются при старте. Остальные модули загружаются по мере перехода к соответствующим маршрутам.

Для настройки ленивой загрузки нужно использовать свойство loadChildren в маршрутах. Вместо того чтобы непосредственно указывать компонент, указывается путь к модулю, который будет загружен только тогда, когда пользователь перейдет на соответствующий маршрут.

Пример ленивой загрузки:

const routes: Routes = [
  { path: 'home', component: HomeComponent },
  { path: 'dashboard', loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule) }
];

В этом примере модуль DashboardModule загружается только при переходе на маршрут /dashboard. Это позволяет уменьшить размер начальной загрузки приложения.

Для правильной работы ленивой загрузки необходимо, чтобы модуль, который загружается лениво, был настроен как самостоятельный модуль с маршрутизацией. Это достигается с помощью функции forChild в модуле маршрутизации.

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class DashboardRoutingModule { }
  1. Preloading (предварительная загрузка)

В некоторых случаях может быть полезно заранее загрузить некоторые модули, чтобы ускорить переход к ним, но без немедленной загрузки при старте приложения. Preloading — это стратегия, при которой модули загружаются после загрузки начальных данных приложения, но до того, как пользователь перейдет на соответствующий маршрут.

Для реализации предварительной загрузки используется встроенный сервис PreloadAllModules. Этот сервис инициирует загрузку всех лениво загружаемых модулей после загрузки начальной части приложения.

Пример использования Preloading:

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

С помощью этой настройки Angular начнет загружать все модули, которые были настроены для ленивой загрузки, после того как приложение загрузится, улучшая производительность при дальнейшей навигации.

Кроме того, можно использовать более тонкие настройки для предзагрузки, создавая собственную стратегию.

@Injectable({
  providedIn: 'root'
})
export class CustomPreloadingStrategy implements PreloadingStrategy {
  preload(route: Route, load: Function): Observable<any> {
    return route.data && route.data['preload'] ? load() : of(null);
  }
}

И затем использовать её в маршрутах:

const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),
    data: { preload: true }
  }
];
  1. No Preloading (отсутствие предварительной загрузки)

По умолчанию Angular использует стратегию отсутствия предварительной загрузки, то есть только те модули, которые непосредственно требуются для работы с текущим маршрутом, загружаются. Это позволяет минимизировать начальную загрузку и избежать излишних запросов. Однако, при большом количестве маршрутов и модулей, пользователь может столкнуться с задержками при переходе на менее часто используемые разделы.

Пример настройки стратегии без предварительной загрузки:

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: NoPreloading })
  ]
})
export class AppRoutingModule { }
  1. Custom Preloading Strategy (пользовательская стратегия предзагрузки)

Angular предоставляет возможность создания собственных стратегий предзагрузки. Это позволяет настроить, какие модули нужно загружать в зависимости от различных условий, например, на основе предпочтений пользователя или сетевых условий.

Для создания пользовательской стратегии предзагрузки нужно реализовать интерфейс PreloadingStrategy и переопределить метод preload.

Пример кастомной стратегии:

@Injectable({
  providedIn: 'root'
})
export class SelectivePreloadingStrategy implements PreloadingStrategy {
  preload(route: Route, load: Function): Observable<any> {
    return route.data && route.data['preload'] ? load() : of(null);
  }
}

Затем, в маршрутах можно указать данные для ленивой загрузки, чтобы контролировать, когда они должны загружаться:

const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),
    data: { preload: true }
  },
  {
    path: 'profile',
    loadChildren: () => import('./profile/profile.module').then(m => m.ProfileModule),
    data: { preload: false }
  }
];

Заключение

Правильная стратегия загрузки маршрутов позволяет значительно повысить производительность Angular-приложений. Выбор между Eager Loading, Lazy Loading, Preloading и созданием собственных стратегий зависит от архитектуры приложения, частоты использования различных разделов и требований к скорости загрузки.