Podział kodu na poziomie trasy w Angular

Popraw wydajność aplikacji, dzieląc kod na poziomie trasy.

Z tego posta dowiesz się, jak skonfigurować dzielenie kodu na poziomie trasy w aplikacji Angular, co może zmniejszyć rozmiar pakietu JavaScriptu i znacznie skrócić czas do pełnej interaktywności.

Przykłady kodu z tego artykułu znajdziesz na GitHub. Przykład routingu zachłannego jest dostępny w gałęzi eager. Przykład podziału kodu na poziomie trasy znajduje się w gałęzi lazy.

Dlaczego dzielenie kodu jest ważne

Rosnąca złożoność aplikacji internetowych doprowadziła do znacznego wzrostu ilości kodu JavaScript dostarczanego użytkownikom. Duże pliki JavaScriptu mogą znacznie opóźniać interaktywność, więc mogą być kosztownym zasobem, zwłaszcza na urządzeniach mobilnych.

Najskuteczniejszym sposobem na zmniejszenie pakietów JavaScriptu bez utraty funkcji w aplikacjach jest wprowadzenie agresywnego dzielenia kodu.

Podział kodu umożliwia podzielenie kodu JavaScript aplikacji na kilka fragmentów powiązanych z różnymi ścieżkami lub funkcjami. Dzięki temu użytkownicy otrzymują tylko ten kod JavaScript, który jest potrzebny podczas początkowego ładowania aplikacji, co skraca czas ładowania.

Techniki dzielenia kodu

Podział kodu można przeprowadzić na 2 poziomach: komponentu i trasy.

  • W przypadku podziału kodu na poziomie komponentu przenosisz komponenty do ich własnych fragmentów kodu JavaScript i ładujesz je leniwie, gdy są potrzebne.
  • W przypadku podziału kodu na poziomie trasy funkcje każdej trasy są umieszczane w osobnym fragmencie. Gdy użytkownicy poruszają się po aplikacji, pobierają fragmenty powiązane z poszczególnymi trasami i uzyskują powiązane funkcje, gdy ich potrzebują.

Ten post dotyczy konfigurowania podziału na poziomie trasy w Angularze.

Przykładowa aplikacja

Zanim przejdziemy do tego, jak używać dzielenia kodu na poziomie trasy w Angularze, przyjrzyjmy się przykładowej aplikacji:

Sprawdź implementację modułów aplikacji. W obiekcie AppModule zdefiniowane są 2 trasy: domyślna trasa powiązana z HomeComponent i trasa nyan powiązana z NyanComponent:

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

Podział kodu na poziomie trasy

Aby skonfigurować dzielenie kodu, musisz refaktoryzować trasę nyan.

Wersja 8.1.0 interfejsu wiersza poleceń Angular może wykonać wszystkie czynności za pomocą tego polecenia:

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

Spowoduje to wygenerowanie: – nowego modułu routingu o nazwie NyanModule, – trasy w AppModule o nazwie nyan, która będzie dynamicznie wczytywać NyanModule, – domyślnej trasy w NyanModule, – komponentu o nazwie NyanComponent, który będzie renderowany, gdy użytkownik trafi na domyślną trasę.

Wykonajmy te czynności ręcznie, aby lepiej zrozumieć, jak zaimplementować dzielenie kodu w Angularze.

Gdy użytkownik przejdzie do ścieżki nyan, router wyrenderuje NyanComponent w punkcie wyjścia routera.

Aby używać dzielenia kodu na poziomie trasy w Angularze, ustaw właściwość loadChildren deklaracji trasy i połącz ją z importem dynamicznym:

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

Istnieją 2 główne różnice w porównaniu z metodą zachłanną:

  1. Ustawiono loadChildren zamiast component. Jeśli używasz podziału kodu na poziomie trasy, musisz wskazać moduły ładowane dynamicznie, a nie komponenty.
  2. W pliku loadChildren po rozwiązaniu obietnicy zwracasz NyanModule, zamiast wskazywać NyanComponent.

Powyższy fragment kodu określa, że gdy użytkownik przechodzi do nyan, Angular powinien dynamicznie wczytać nyan.module z katalogu nyan i wyrenderować komponent powiązany z trasą domyślną zadeklarowaną w module.

Możesz powiązać trasę domyślną z komponentem za pomocą tej deklaracji:

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 {}

Ten kod renderuje NyanComponent, gdy użytkownik przechodzi do https://example.com/nyan.

Aby sprawdzić, czy router Angulara pobiera nyan.module w sposób leniwy w środowisku lokalnym:

  1. Naciśnij `Control+Shift+J` (lub `Command+Option+J` na Macu), aby otworzyć Narzędzia deweloperskie.
  2. Kliknij kartę Sieć.

  3. W przykładowej aplikacji kliknij NYAN.

  4. Zwróć uwagę, że plik nyan-nyan-module.js pojawia się na karcie Sieć.

Leniwe ładowanie pakietów JavaScript z podziałem kodu na poziomie trasy.

Ten przykład znajdziesz na GitHubie.

wyświetlić wskaźnik oczekiwania,

Obecnie, gdy użytkownik kliknie przycisk NYAN, aplikacja nie informuje, że wczytuje JavaScript w tle. Aby poinformować użytkownika o wczytywaniu skryptu, warto dodać ikonę oczekiwania.

Aby to zrobić, zacznij od dodania znaczników wskaźnika wewnątrz elementu router-outlet w pliku app.component.html:

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

Następnie dodaj klasę AppComponent, aby obsługiwać zdarzenia routingu. Ta klasa ustawi flagę loading na true, gdy wykryje zdarzenie RouteConfigLoadStart, i na false, gdy wykryje zdarzenie 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;
        }
      }
    );
  }
}

W przykładzie poniżej wprowadziliśmy sztuczne opóźnienie wynoszące 500 ms, aby można było zobaczyć, jak działa ikona oczekiwania.

Podsumowanie

Możesz zmniejszyć rozmiar pakietu aplikacji Angular, stosując podział kodu na poziomie trasy:

  1. Użyj generatora modułów ładowanych leniwie w interfejsie wiersza poleceń Angular, aby automatycznie utworzyć szkielet dynamicznie ładowanej ścieżki.
  2. Dodaj wskaźnik ładowania, gdy użytkownik przechodzi do trasy z opóźnionym ładowaniem, aby pokazać, że trwa działanie.