Перейти к содержанию

Маршрутизация. Асинхронная загрузка

С ростом приложения увеличивается количество его модулей и общее время его загрузки. Для оптимизации скорости работы приложения можно применить асинхронную (lazy load) маршрутизацию.

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

Для отложенной загрузки необходимо задать свойство маршрута loadChildren в модуле родителе в следующем формате:

{path: 'order', loadChildren: './modules/order/order.module#OrderModule'}

В качестве модуля родителя обычно выступает корневой модуль приложения, но вложенность может любой.

Загружаемый асинхронно модуль должен иметь свою собственную маршрутизацию, URL которой будут строиться относительно того, что указано в path (здесь order).

Таким образом, когда будет запрошен маршрут в состав которого входит order, тогда и загрузится OrderModule. Но в момент старта приложения он не включается в загрузку.

Ранее упоминалось, что guard CanLoad используется при загрузке lazy load. CanLoad схож с CanActivate, отличие лишь в том, что первый отвечает за доступ к целому модулю.

{
    path: 'order',
    loadChildren: './modules/order/order.module#OrderModule',
    canLoad: [AuthGuard]
}

CanLoad может использоваться только совместно с тем маршрутом, у которого определено свойство loadChildren.

Существует еще одна технология, позволяющая загружать необходимые модули в фоне - предзагрузка. После каждого успешного перехода Router сервис ищет не загруженные модули согласно заранее определенной стратегии предзагрузки и, если необходимо, подгружает их незаметно для пользователя.

По умолчанию в Angular доступны две стратегии:

  • предзагрузка отключена (используется по умолчанию);
  • предзагрузка включена для модулей lazy load.

Стратегия предзагрузки указывается в объекте конфигурации, который передается вторым параметром методу маршрутизации forRoot(), в свойстве preloadStrategy.

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

import { PreloadAllModules } from '@angular/router'

RouterModule.forRoot({}, { preloadingStrategy: PreloadAllModules })

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

Пользовательская стратегия предзагрузки создается с помощью интерфейса PreloadingStrategy, который реализует единственный метод preload().

custom-preloading-strategy.service.ts

@Injectable({ providedIn: 'root' })
export class CustomPreloadingStrategyService implements PreloadingStrategy {
  preload(route: Route, load: () => Observable<any>): Observable<any> {
    let modules: any = ['contacts', 'orders']

    if (modules.includes(route.path)) {
      return load()
    } else {
      return of(null)
    }
  }
}

Здесь предварительно загружаются модули, URL которых начинается с одного из значений, описанных в массиве переменной modules. Метод preload() всегда должен возвращать Observable и вызывается для каждого маршрута с двумя аргументами - маршрут и функция загрузки модуля.

Если модуль не удовлетворяет критерию предварительной загрузки, необходимо вернуть Observable значения null.

Далее стратегия указывается в качестве значения свойства preloadStrategy.

import { CustomPreloadingStrategyService } from './custom-preloading-strategy.service'

RouterModule.forRoot(
  {},
  { preloadingStrategy: CustomPreloadingStrategyService }
)

Ссылки