Améliorez les performances de votre application en répartissant le code au niveau de la route.
Cet article explique comment configurer la répartition du code au niveau de la route dans une application Angular afin de réduire la taille du bundle JavaScript et d'améliorer considérablement le délai d'interaction.
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 division du code au niveau de la route se trouve dans la branche différée.
Pourquoi le fractionnement du code est-il important ?
La complexité croissante des applications Web a entraîné une augmentation significative de la quantité de JavaScript livrée aux utilisateurs. Les fichiers JavaScript volumineux peuvent nettement 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 groupes JavaScript sans sacrifier les fonctionnalités de vos applications consiste à introduire une division agressive du code.
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 code peut être fractionné à deux niveaux: au niveau du composant et au niveau de la route.
- La division du code au niveau du composant consiste à déplacer les composants vers leurs propres fragments JavaScript et à les charger en différé lorsqu'ils sont nécessaires.
- 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 porte sur la configuration de la division au niveau de la route dans Angular.
Exemple d'application
Avant de voir plus en détail comment diviser le 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 {}
Répartition du code au niveau de la route
Pour configurer la répartition du code, la route eager nyan
doit être refactorisée.
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
Vous obtiendrez les résultats suivants:
- Un nouveau module de routage appelé NyanModule
- Une route dans AppModule
appelée nyan
qui chargera dynamiquement NyanModule
- Une route par défaut dans le NyanModule
- Un composant appelé NyanComponent
qui s'affiche lorsque l'utilisateur trouve la route par défaut
Nous allons suivre ces étapes manuellement pour mieux comprendre comment implémenter le fractionnement du code avec Angular.
Lorsque l'utilisateur accède à la route nyan
, le routeur affiche le NyanComponent
dans la prise du routeur.
Pour diviser le 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 majeures par rapport à l'itinéraire rapide:
- Vous avez défini
loadChildren
au lieu decomponent
. Lorsque vous utilisez la division du code au niveau de la route, vous devez pointer vers des modules chargés dynamiquement, et non vers des composants. - Dans
loadChildren
, une fois la promesse résolue, renvoyezNyanModule
au lieu de pointer versNyanComponent
.
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 le fichier nyan.module
de manière différée dans votre environnement local:
- Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
Cliquez sur l'onglet Réseau.
Cliquez sur NYAN dans l'application exemple.
Notez que le fichier
nyan-nyan-module.js
apparaît dans l'onglet "Network".
Recherchez 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 donner 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 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 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:
- Utilisez le générateur de modules à chargement différé de la CLI Angular pour créer automatiquement une route chargée dynamiquement.
- Ajoutez un indicateur de chargement lorsque l'utilisateur accède à une route différée pour indiquer qu'une action est en cours.