2019, il n’y a rien de pire que de ne pas avoir de la 4G sur son mobile ou un petit frère qui occupe toute la bande passante de la maison, ce qui a pour conséquence de ralentir le chargement de la page de l’application que tu viens 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 tu ne vois pas encore l’intégralité. La frustration.

Une frustration moderne

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 ton application Web, il faut bien comprendre ce qu’est le Lazy Loading.

C’est quoi 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 tu l’auras remarqué, c’est une méthode que tu croises 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 tu défiles vers le bas. Un lazy loading est toujours la conséquence d’une action de l’utilisateur.

 

Aujourd’hui, je vais abordé spécifiquement le lazy loading de ton application Angular et non de son contenu (HTML, médias, animation, …).

Par défaut, lorsque tu vas accéder à ton application, ton 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 signifie que le navigateur de l’utilisateur, dès son premier accès à l’application, va télécharger toute ton app. Dans le cas d’une webapp Angular, il y a un quelques de 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, tu peux 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 tu es amené à travailler sur des projets plus importants, le poids de ton 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 configuration de ta navigation, le point clé !

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é !

Tu as surement mis en place une navigation dans ton 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 l’on peut trouver dans le tutoriel officiel d’Angular fonctionne très bien. Cependant elle est la raison principale de la compilation totale de ton application dans un seul et unique fichier JS.

Tu le devines, 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 enfant 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 ton application en plusieurs fichiers JS, plus tu délégueras la configuration des routes enfants à leur module respectif, plus tu auras un découpage fin de tes fonctionnalités.

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

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

Les résultats

Pour comparer, tu trouveras ci-dessous le chargement des fichiers JS à la même page que l’exemple présenté plus haut. Tu noteras 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 t’aurai convaincu de mettre en place le lazy load sur tes projets Angular. En résumé, cette technique te 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, tu auras une meilleure lisibilité de ton code.

React et Vue

Après t’avoir décrit cette solution pour une webapp basé sur Angular, il est évident que les deux acolytes, que sont React et Vue, ne sont pas en restes quant à cette fonctionnalité.

Le principe technique du lazy loading repose sur une technologie commune tierce: Webpack. Sa capacité à importer dynamiquement des modules rends la configuration du lazy loading assez similaire entre les différents outils.

Pour React, depuis sa version 16.6, tu as deux fonctionnalités qui ont été ajouté à la librairie: React.lazy() et React.Suspense. Les deux sont nécessaires à l’utilisation du lazy loading dans ton application. La première te permet de définir quel composant tu vas lazy loadé tandis que la seconde est un wrapper du dit-composant.

Exemple de composant intégrant React.lazy() et React.Suspense

Quant à Vue, le lazy loading se configure dans la définition des routes de navigation de l’application. Méthode assez similaire à celle d’Angular, tu retrouveras facilement dans la documentation officielle tout ce qu’il te faut.

Lazy loading vuejsExemple de configuration du lazy loading dans Vue

Pour ce qui est du chargement à la demande de tes fonctionnalités, c’est chose faite. Tu peux désormais te concentrer sur d’autres points de ton application afin de l’optimiser toujours plus et d’en faire profiter des utilisateurs !

Ta webapp optimisée avec le Lazy Loading
4 (80%) 4 vote[s]

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Je veux Contribuer

C'est parti

Je suis un Professionnel

Voyons voir