Fractionnement du code au niveau de la route dans Angular

Améliorez les performances de votre application en utilisant la division du code au niveau du routage.

Cet article explique comment configurer la division du code au niveau des routes dans une application Angular. Cela peut réduire la taille du groupe JavaScript et considérablement améliorer le temps de réponse.

Vous trouverez les exemples de code de cet article sur GitHub. L'exemple de routage eager est disponible dans la branche eager. L'exemple de fractionnement du code au niveau de la route se trouve dans la branche lazy.

Pourquoi le fractionnement du code est-il important ?

La complexité croissante des applications Web a entraîné une augmentation significative de la quantité de code JavaScript envoyée aux utilisateurs. Les fichiers JavaScript volumineux peuvent retarder considérablement l'interactivité. Ils peuvent donc représenter une ressource coûteuse, en particulier sur mobile.

Le moyen le plus efficace de réduire la taille des bundles JavaScript sans sacrifier les fonctionnalités de vos applications consiste à introduire une division du code agressive.

Le scission du code vous permet de diviser le code JavaScript de votre application en plusieurs fragments associés à différentes routes ou fonctionnalités. Cette approche n'envoie aux utilisateurs que le code JavaScript dont ils ont besoin lors du chargement initial de l'application, ce qui réduit les temps de chargement.

Techniques de fractionnement du code

Le fractionnement du code peut être effectué à deux niveaux : au niveau du composant et au niveau de la route.

  • Avec la division du code au niveau des composants, vous déplacez les composants vers leurs propres blocs JavaScript et les chargez de manière paresseuse lorsqu'ils sont nécessaires.
  • Dans la division du code au niveau du parcours, vous encapsulez la fonctionnalité de chaque parcours dans un bloc distinct. Lorsque les utilisateurs parcourent votre application, ils récupèrent les fragments associés aux routes individuelles et obtiennent la fonctionnalité associée lorsqu'ils en ont besoin.

Cet article explique comment configurer la division au niveau des routes dans Angular.

Exemple d'application

Avant de voir comment utiliser la division du code au niveau des routes dans Angular, examinons un exemple d'application :

Vérifiez l'implémentation des modules de l'application. Dans AppModule, deux routes sont définies : la route par défaut associée à HomeComponent et une route nyan associée à NyanComponent :

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

Répartition du code au niveau de la route

Pour configurer le fractionnement du code, le routage anticipé nyan doit être refactorisé.

La version 8.1.0 de la CLI Angular peut tout faire pour vous avec cette commande :

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

Cela génère les éléments suivants : - Un nouveau module de routage appelé NyanModule - Un parcours dans AppModule appelé nyan qui chargera dynamiquement NyanModule - Un parcours par défaut dans NyanModule - Un composant appelé NyanComponent qui sera affiché lorsque l'utilisateur cliquera sur le parcours par défaut

Passons manuellement par ces étapes pour mieux comprendre l'implémentation du fractionnement du code avec Angular.

Lorsque l'utilisateur accède à l'itinéraire nyan, le routeur affiche le NyanComponent dans la sortie du routeur.

Pour utiliser le fractionnement du code au niveau de la route dans Angular, définissez la propriété loadChildren de la déclaration de route et combinez-la à une importation dynamique :

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

Il existe deux différences principales par rapport à la méthode eager :

  1. Vous avez défini loadChildren au lieu de component. Lorsque vous utilisez le fractionnement du code au niveau de la route, vous devez faire pointer vers des modules chargés dynamiquement, et non vers des composants.
  2. Dans loadChildren, une fois la promesse résolue, vous renvoyez NyanModule au lieu de pointer vers NyanComponent.

L'extrait de code ci-dessus indique que lorsque l'utilisateur accède à nyan, Angular doit charger dynamiquement nyan.module à partir du répertoire nyan et afficher le composant associé à la route par défaut déclarée dans le module.

Vous pouvez associer la route par défaut à un composant à l'aide de la déclaration suivante:

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

Ce code affiche NyanComponent lorsque l'utilisateur accède à https://example.com/nyan.

Pour vérifier que le routeur Angular télécharge nyan.module de manière paresseuse dans votre environnement local :

  1. Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
  2. Cliquez sur l'onglet Réseau.

  3. Cliquez sur NYAN dans l'exemple d'application.

  4. Notez que le fichier nyan-nyan-module.js apparaît dans l'onglet "Réseau".

Chargement différé des groupes JavaScript avec fractionnement du code au niveau de la route

Consultez cet exemple sur GitHub.

Afficher une roue de sélection

Pour le moment, lorsque l'utilisateur clique sur le bouton NYAN, l'application n'indique pas qu'elle charge JavaScript en arrière-plan. Pour fournir des commentaires à l'utilisateur pendant le chargement du script, vous devrez probablement ajouter un spinner.

Pour ce faire, commencez par ajouter un balisage pour l'indicateur dans l'élément router-outlet de app.component.html :

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

Ajoutez ensuite une classe AppComponent pour gérer les événements de routage. Cette classe définira l'indicateur loading sur true lorsqu'elle entendra l'événement RouteConfigLoadStart et sur false lorsqu'elle entendra l'événement 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;
        }
      }
    );
  }
}

Dans l'exemple ci-dessous, nous avons introduit une latence artificielle de 500 ms afin que vous puissiez voir l'icône de chargement en action.

Conclusion

Vous pouvez réduire la taille du bundle de vos applications Angular en appliquant un fractionnement du code au niveau de la route:

  1. Utilisez le générateur de modules à chargement différé de la CLI Angular pour créer automatiquement une route chargée dynamiquement.
  2. Ajoutez un indicateur de chargement lorsque l'utilisateur accède à une route différée pour indiquer qu'une action est en cours.