2019. Il n’y a rien de pire que de ne pas avoir de la 4G sur son mobile ou une connexion Wifi décevante, ce qui a pour conséquence de ralentir le chargement de la page de l’application que vous venez d’ouvrir. Ces petites secondes qui s’écoulent vite, très vite. Ce menu qui commence à s’afficher mais pas le contenu. Cette image qui a commencé à charger mais dont vous ne voyez pas encore l’intégralité. La frustration s’installe.

Nous connaissons tous ces problèmes de vitesse de chargement et ils sont inhérents à notre quotidien. Souvent la connexion Internet est à la base du problème, mais nous, professionnels et passionnés du web, nous savons. Nous savons que nous pouvons agir et contribuer à diminuer cette frustration moderne. Des bonnes pratiques d’optimisation, telles que la diminution du poids des fichiers médias ou la compilation des fichiers de style sont déjà ancrées dans la culture Web, mais malgré cela le problème subsiste.

C’est là que vient jouer le rôle du Lazy Loading. Une technique abordée pour la première fois en 2002 dans le livre “Patterns of Enterprise Application Architecture” de Martin Fowler.

Avant d’attaquer la configuration et l’optimisation de notre application Web, il faut bien comprendre ce qu’est le Lazy Loading.

Qu’est-ce que le Lazy Loading ?

Le Lazy Loading, le “chargement paresseux” en français, est une technique que l’on peut vulgariser par du chargement à la demande. Je pense que vous l’aurez remarqué, c’est une méthode que vous croisez tous les jours sur une majorité de site. Le meilleur exemple étant les galeries photos de portfolio qui, afin de ne pas alourdir le chargement de la page avec les nombreuses photos HD, vont télécharger les images au fur et à mesure que vous défiliez vers le bas. Un lazy loading est toujours la conséquence d’une action de l’utilisateur.

Aujourd’hui, nous allons aborder spécifiquement le lazy loading de notre application Angular et non de son contenu (HTML, médias, animation, …).

Par défaut, lorsque vous accédez à votre application, votre navigateur va récupérer l’intégralité de cette dernière au travers d’un unique fichier JS, sobrement nommé main.js ou main.min.js. Ce qui veut dire que le navigateur de l’utilisateur, dès son premier accès à votre page d’accueil, va télécharger toute votre application. Dans le cas d’une webapp Angular, il y a quelques fichiers de base: main.js, polyfills.js, runtime.js.


Liste de chargement des fichiers JS sur localhost/connexion

Celui qui nous intéresse est bien évidemment le main.js. Dans l’exemple ci-dessus, vous pouvez voir qu’il fait un poids total de 7.7MB.

Pour des petites réalisations, ce n’est pas bloquant car le fichier compilé ne pèsera pas bien lourd, mais si vous êtes amenés à travailler sur des projets plus importants, le poids de votre application va augmenter inévitablement et prolonger le temps chargement.

Nous cherchons à effectuer un chargement des fonctionnalités à la demande et cet unique main.js pose problème car il contient toute l’application.

La solution serait de servir à l’utilisateur un fichier JS par fonctionnalité. C’est dans cette logique qu’est venu l’idée aux développeurs d’Angular de permettre facilement la mise en place d’un lazy loading. Plus précisément, n’importe quel @NgModule peut être lazy loadé !

Vous avez très certainement mis en place une navigation dans votre projet, c’est de là que toute la magie va opérer. Prenons cet exemple classique d’une définition de routes, ci-dessous :


Définition des routes principales dans le app-routing.module

Cette configuration classique que nous pouvons trouver dans le tutoriel officiel d’Angular fonctionne très bien, mais elle est la raison principale de la compilation totale de votre application dans un seul et unique fichier JS.

Vous l’avez deviné, nous allons donc agir sur cette configuration afin de pouvoir expérimenter une piste du Lazy Loading de fonctionnalités. Le principe de la manipulation que l’on va suivre est de déporter la définition des routes enfants du fragment parent :

ici, séparer login / mot-de-passe-oublie / reinitialisation-mot-de-passe de /connexion.


Définition des routes principales dans le app-routing.module en lazyload

À cette étape, nous retirons le tableau children pour le remplacer par une entrée loadChildren qui va prendre en valeur le chemin du module (du NgModule) qui est le parent des composants enfants vu précédemment. Ensuite, nous allons nous rendre dans ce NgModule pour y poursuivre la définition des routes enfant à /connexion.


Import du RouterModule dans le AuthModule.

Dans ce module, nous allons venir importer en dépendance le RouterModule en lui passant des options par la méthode .forChild(). À ce moment-là, nous reprenons le modèle classique de définition de routes. Ce petit changement aura pour effet de découper la compilation de votre application en plusieurs fichiers JS, plus vous déléguerez la configuration des routes enfants à leur module respectif, plus vous aurez un découpage fin de vos fonctionnalités.


Chaque fichier X.hash.js est un NgModule. Dans cette application, on peut donc distinguer 15 NgModules lazy loadés.

Désormais, votre application chargera uniquement les fonctionnalités dont elle a besoin en fonction des routes que votre utilisateur empruntera. Le poids et le temps de chargement global de votre projet s’en verront allégés et vos visiteurs vous diront un grand merci !

Pour comparer, vous trouverez ci-dessous le chargement des fichiers JS à la même page que l’exemple présenté plus haut. Vous noterez un poids total du JavaScript qui est passé de 8.1MB à 4.7MB, soit une réduction de 42 % !


Liste de chargement des fichiers JS sur localhost/connexion en lazyload

J’espère qu’avec ces résultats, je vous aurai convaincu de mettre en place le lazy load sur vos projets Angular. En résumé, cette technique vous permettra de charger les fonctionnalités à la demande de l’utilisateur. Il y gagnera en poids et en temps de chargement si précieux dans sa vie. Pour finir, un aspect non-négligeable pour tout bon développeur, vous aurez une meilleure lisibilité de votre code.