Fractionnement du code au niveau de la route dans Angular

Améliorez les performances de votre application en divisant le code au niveau du routage.

Cet article explique comment configurer la répartition du code au niveau du routage dans une application Angular, afin de réduire la taille du bundle JavaScript et d'améliorer considérablement le délai avant interactivité.

Vous trouverez des exemples de code dans 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 différée.

Pourquoi la division du code est-elle importante ?

La complexité croissante des applications Web a conduit à une augmentation significative de la quantité de JavaScript envoyée aux utilisateurs. Les fichiers JavaScript volumineux peuvent considérablement retarder l'interactivité. Ils peuvent donc s'avérer coûteux, en particulier sur les appareils mobiles.

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

La division du code vous permet de diviser le code JavaScript de votre application en plusieurs fragments associés à différents itinéraires ou fonctionnalités. Cette approche n'envoie aux utilisateurs que le code JavaScript dont ils ont besoin pendant le chargement initial de l'application, ce qui permet de réduire les temps de chargement.

Techniques de division du code

Le fractionnement du code peut s'effectuer à deux niveaux: au niveau du composant et au niveau de la route.

  • Lors du fractionnement du code au niveau du composant, vous déplacez les composants vers leurs propres blocs JavaScript et les chargez en différé lorsque cela est nécessaire.
  • Dans la division du code au niveau de la route, vous encapsulez la fonctionnalité de chaque route dans un fragment 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 de la route dans Angular.

Exemple d'application

Avant d'expliquer comment utiliser la division du code au niveau de la route 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 {}

Fractionnement du code au niveau de la route

Pour configurer la division du code, vous devez refactoriser la route rapide nyan.

La version 8.1.0 de la CLI Angular peut tout faire pour vous à l'aide de cette commande:

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

Cela génère : - Un nouveau module de routage appelé NyanModule - Un itinéraire dans AppModule appelé nyan, qui charge de manière dynamique le NyanModule - Un itinéraire par défaut dans NyanModule - Un composant appelé NyanComponent qui s'affiche lorsque l'utilisateur atteint la route par défaut

Nous allons effectuer ces étapes manuellement afin de mieux comprendre comment implémenter la division du code avec Angular.

Lorsque l'utilisateur accède à la route nyan, le routeur affiche le NyanComponent dans la prise du routeur.

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

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

Il existe deux différences clés par rapport à la voie rapide:

  1. Vous avez défini loadChildren au lieu de component. Lorsque vous divisez le code au niveau du routage, vous devez 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 en différé nyan.module 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'application exemple.

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

Chargement différé des bundles JavaScript avec division du code au niveau de l'itinéraire

Retrouvez cet exemple sur GitHub.

Afficher une icône de chargement

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 une icône de chargement.

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éfinit l'indicateur loading sur true lorsqu'elle entend l'événement RouteConfigLoadStart et définit l'indicateur sur false lorsqu'elle entend 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 ajouté une latence artificielle de 500 ms afin que vous puissiez voir la roue de sélection des couleurs en action.

Conclusion

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

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