Повысьте производительность приложения, используя разделение кода на уровне маршрута.
В этой статье рассказывается, как настроить разделение кода на уровне маршрута в приложении Angular, чтобы уменьшить размер пакета JavaScript и значительно улучшить показатель Time to Interactive.
Примеры кода из этой статьи можно найти на GitHub. Пример нетерпеливой маршрутизации доступен в ветке eager. Пример разделения кода на уровне маршрута находится в ветке 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.
В Angular CLI версии 8.1.0 это можно сделать с помощью следующей команды:
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)
}
Есть два основных отличия от упреждающего маршрута:
- Вы указали
loadChildrenвместоcomponent. При разделении кода на уровне маршрута необходимо указывать динамически загружаемые модули, а не компоненты. - В
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 в локальной среде с задержкой, выполните следующие действия:
- Нажмите Ctrl + Shift + J (или Command + Option + J на Mac), чтобы открыть Инструменты разработчика.
Откройте вкладку Сеть.
В примере приложения нажмите NYAN.
Обратите внимание, что файл
nyan-nyan-module.jsпоявится на вкладке "Сеть".

Этот пример можно найти на 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, применив разделение кода на уровне маршрута:
- Используйте генератор модулей с отложенной загрузкой Angular CLI, чтобы автоматически создать динамически загружаемый маршрут.
- Добавьте индикатор загрузки, который будет показываться, когда пользователь переходит на страницу с отложенной загрузкой.