Podział kodu na poziomie trasy w Angular

Popraw wydajność swojej aplikacji, używając podziału kodu na poziomie trasy.

W tym poście wyjaśniamy, jak skonfigurować w aplikacji Angular dzielenie kodu na poziomie trasy, co może zmniejszyć rozmiar pakietu JavaScript i znacznie skrócić czas do pełnej interaktywności.

Przykładowy kod z tego artykułu znajdziesz na GitHub. Przykład routingu z żądaniem jest dostępny w gałęzi zainteresowań. Przykład podziału kodu na poziomie trasy znajduje się w leniwej gałęzi.

Dlaczego dzielenie kodu jest takie ważne

Rosnąca złożoność aplikacji internetowych powoduje znaczny wzrost ilości kodu JavaScript wysyłanego do użytkowników. Duże pliki JavaScript mogą zauważalnie opóźniać interaktywność, przez co mogą być kosztowne, zwłaszcza na urządzeniach mobilnych.

Najskuteczniejszym sposobem zmniejszenia pakietów JavaScript bez rezygnacji z funkcji aplikacji jest agresywny podział kodu.

Dzielenie kodu umożliwia podzielenie kodu JavaScript aplikacji na kilka fragmentów związanych z różnymi trasami lub funkcjami. Ta metoda wysyła użytkownikom kod JavaScript tylko podczas początkowego wczytywania aplikacji, co skraca czas wczytywania.

Techniki podziału kodu

Podział kodu może odbywać się na 2 poziomach: na poziomie komponentu i poziomu trasy.

  • W przypadku podziału kodu na poziomie komponentu przenosisz komponenty do ich własnych fragmentów JavaScriptu, a w razie potrzeby wczytujesz je leniwie.
  • W przypadku podziału kodu na poziomie trasy zamykasz funkcjonalność każdej trasy w osobnym fragmencie. Gdy użytkownicy poruszają się po Twojej aplikacji, pobierają fragmenty powiązane z poszczególnymi trasami i w razie potrzeby otrzymują powiązane funkcje.

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

Przykładowa aplikacja

Zanim dowiemy się, jak używać podziału kodu na poziomie trasy w Angular, przyjrzyjmy się przykładowej aplikacji:

Sprawdź implementację modułów aplikacji. W elemencie 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 można było skonfigurować podział kodu, trzeba refaktoryzować trasę żądania nyan.

Interfejs wiersza poleceń Angular w wersji 8.1.0 może wykonać wszystko 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ć trasę NyanModule; – trasy domyślnej w NyanModule; – komponentu o nazwie NyanComponent, który zostanie wyrenderowany, gdy użytkownik wybierze trasę domyślną.

Wykonajmy te czynności ręcznie, aby lepiej zrozumieć, jak działa podział kodu w Angular.

Gdy użytkownik przejdzie na trasę nyan, router wyrenderuje NyanComponent w gniazdku routera.

Aby w Angular użyć podziału kodu na poziomie trasy, ustaw w deklaracji trasy właściwość loadChildren 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 stosunku do tej drogi:

  1. Ustawienie loadChildren zamiast component. Gdy używasz podziału kodu na poziomie trasy, musisz wskazywać moduły ładowane dynamicznie, a nie komponenty.
  2. W usłudze loadChildren, gdy obietnica zostanie zrealizowana, zwracasz wartość NyanModule, zamiast wskazać NyanComponent.

Powyższy fragment kodu określa, że gdy użytkownik przechodzi do nyan, Angular powinno dynamicznie wczytywać nyan.module z katalogu nyan i renderować 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 kod NyanComponent, gdy użytkownik przechodzi do aplikacji https://example.com/nyan.

Aby sprawdzić, czy router Angular pobiera nyan.module leniwie 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. Kliknij NYAN w przykładowej aplikacji.

  4. Pamiętaj, że plik nyan-nyan-module.js jest widoczny na karcie Sieć.

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

Ten przykład znajdziesz na GitHubie.

Pokaż wskaźnik postępu

W tej chwili, gdy użytkownik kliknie przycisk NYAN, aplikacja nie wskazuje, że wczytuje kod JavaScript w tle. Aby przekazać użytkownikowi opinię podczas ładowania skryptu, warto dodać wskaźnik postępu.

Aby to zrobić, zacznij od dodania znacznika wskaźnika wewnątrz elementu router-outlet w języku app.component.html:

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

Następnie dodaj klasę AppComponent do obsługi zdarzeń routingu. Ta klasa ustawi flagę loading na true, gdy usłyszy zdarzenie RouteConfigLoadStart, i ustawi flagę 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 poniższym przykładzie wprowadziliśmy sztuczne opóźnienie wynoszące 500 ms, aby można było zobaczyć działanie wskaźnika postępu.

Podsumowanie

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

  1. Użyj generatora modułów leniwego ładowania w interfejsie wiersza poleceń Angular, aby automatycznie tworzyć rusztowanie dynamicznej trasy.
  2. Dodaj wskaźnik wczytywania, gdy użytkownik przechodzi na leniwą trasę, aby pokazać, że trwa działanie.