Разделение кода на уровне маршрута в Angular

Повысьте производительность своего приложения, используя разделение кода на уровне маршрутов!

В этой статье объясняется, как настроить разделение кода на уровне маршрута в приложении Angular, что может уменьшить размер пакета JavaScript и значительно сократить время до взаимодействия .

Примеры кода из этой статьи можно найти на GitHub . Пример маршрутизации Angry доступен в ветке Angry . Пример разбиения кода на уровне маршрута находится в ветке Lazy .

Почему разделение кода имеет значение

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

Самый эффективный способ уменьшить размер пакетов JavaScript без ущерба для функциональности ваших приложений — это внедрить агрессивное разделение кода.

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

Методы разделения кода

Разделение кода может выполняться на двух уровнях: уровне компонентов и уровне маршрутов .

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

В этой статье мы рассмотрим настройку разделения на уровне маршрутов в Angular.

Образец заявления

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

Проверьте реализацию модулей приложения. Внутри AppModule определены два маршрута: маршрут по умолчанию, связанный с HomeComponent , и маршрут nyan , связанный с NyanComponent :

@NgModule({
  ...
  imports: [
    BrowserModule,
    RouterModule.forRoot([
      {
        path: '',
        component: HomeComponent,
        pathMatch: 'full'
      },
      {
        path: 'nyan',
        component: NyanComponent
      }
    ])
  ],
  ...
})
export class AppModule {}

Разделение кода на уровне маршрута

Чтобы настроить разделение кода, необходимо реорганизовать маршрут nyan .

Версия 8.1.0 Angular CLI может сделать все за вас с помощью этой команды:

ng g module nyan --module app --route nyan

Это сгенерирует: - Новый модуль маршрутизации с именем NyanModule - Маршрут в AppModule с именем nyan , который будет динамически загружать NyanModule - Маршрут по умолчанию в NyanModule - Компонент с именем NyanComponent , который будет отображаться, когда пользователь переходит по маршруту по умолчанию

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

Когда пользователь переходит по маршруту nyan , маршрутизатор отображает NyanComponent в выходном разъеме маршрутизатора.

Чтобы использовать разделение кода на уровне маршрута в Angular, задайте свойство loadChildren объявления маршрута и объедините его с динамическим импортом:

{
  path: 'nyan',
  loadChildren: () => import('./nyan/nyan.module').then(m => m.NyanModule)
}

Есть два ключевых отличия от активного пути:

  1. Вы устанавливаете loadChildren вместо component . При использовании разделения кода на уровне маршрута вам нужно указать на динамически загружаемые модули, а не на компоненты.
  2. В loadChildren после разрешения обещания вы возвращаете NyanModule вместо указания на NyanComponent .

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

Вы можете связать маршрут по умолчанию с компонентом, используя следующее объявление:

import { NgModule } from '@angular/core';
import { NyanComponent } from './nyan.component';
import { RouterModule } from '@angular/router';

@NgModule({
  declarations: [NyanComponent],
  imports: [
    RouterModule.forChild([{
      path: '',
      pathMatch: 'full',
      component: NyanComponent
    }])
  ]
})
export class NyanModule {}

Этот код отображает NyanComponent , когда пользователь переходит на https://example.com/nyan .

Чтобы проверить, что маршрутизатор Angular лениво загружает nyan.module в вашей локальной среде:

  1. Нажмите `Control+Shift+J` (или `Command+Option+J` на Mac), чтобы открыть DevTools.
  2. Перейдите на вкладку «Сеть» .

  3. Нажмите NYAN в образце приложения.

  4. Обратите внимание, что файл nyan-nyan-module.js отображается на вкладке «Сеть».

Ленивая загрузка пакетов JavaScript с разделением кода на уровне маршрута

Найдите этот пример на GitHub .

Показать спиннер

Прямо сейчас, когда пользователь нажимает кнопку NYAN , приложение не показывает, что оно загружает JavaScript в фоновом режиме. Чтобы дать пользователю обратную связь во время загрузки скрипта, вы, вероятно, захотите добавить спиннер.

Для этого начните с добавления разметки для индикатора внутри элемента router-outlet в app.component.html :

<router-outlet>
  <span class="loader" *ngIf="loading"></span>
</router-outlet>

Затем добавьте класс AppComponent для обработки событий маршрутизации. Этот класс установит флаг loading на true , когда он услышит событие RouteConfigLoadStart , и установит флаг на false , когда он услышит событие RouteConfigLoadEnd .

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  loading: boolean;
  constructor(router: Router) {
    this.loading = false;
    router.events.subscribe(
      (event: RouterEvent): void => {
        if (event instanceof NavigationStart) {
          this.loading = true;
        } else if (event instanceof NavigationEnd) {
          this.loading = false;
        }
      }
    );
  }
}

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

Заключение

Вы можете уменьшить размер пакета ваших приложений Angular, применив разделение кода на уровне маршрутов:

  1. Используйте генератор модулей с отложенной загрузкой Angular CLI для автоматического создания динамически загружаемого маршрута.
  2. Добавьте индикатор загрузки, когда пользователь переходит по ленивому маршруту, чтобы показать, что выполняется какое-то действие.