Comprendre le lazy loading
Le lazy loading ou chargement différé est une technique visant à charger une ressource uniquement quand on en a besoin. L’intérêt principal du lazy loading est de réduire le temps de chargement des pages web. Avec le lazy loading, les ressources non critiques n’impactent pas le chemin critique de rendu.
Lorsqu’un utilisateur accède à votre site internet ou votre application web, le navigateur va demander à votre serveur toutes les ressources qu’il a besoin pour générer votre affichage. Les ressources non-critiques sont aussi récupéré et font l’objet d’une requête pour être chargés. L’accumulation de nombreuses ressources non-critiques peuvent donner lieu à des temps de chargement allongé. Le lazy loading a pour but de retirer des ressources non-prioritaires du chargement initial et de les récupérer uniquement qu’on en a besoin. Le chargement différé peut s’appliquer sur différentes ressources, ainsi que le moment de les chargés peut varier. Dans la suite de cet article, je vais vous présentez des cas d’utilisation du lazy loading et des manières de le mettre en place.
Mettre en place un chargement différé de vos images ?
Le lazy loading est souvent associé au chargement différé des images. Cette technique très répandue de nos jours, consiste à charger les images en fonction de la position de notre utilisateur dans la page.
Les avantages de différer le chargement de vos images
- Réduire le temps de chargement des pages web, les utilisateurs et les robots Google aime les faibles temps de chargement
- Optimiser les ressources utilisées par un utilisateur suivant son comportement sur le site
Les inconvénients du lazy load de vos images
- Peut entraîner une mauvaise indexation du contenu chargé en différé
- Il faut le coder, mais ne vous inquiété pas, je vais vous aidez pour ça
Comment coder un système de lazy loading ?
Créer un système de lazy loading est relativement simple, vous aurez besoin de faire un peu de JavaScript et de HTML.
Étape 1 : Ne plus passer l’url de votre image dans l’attribut src de la balise img
Afin que le navigateur ne charge pas directement votre image, vous devez retirer l’attribut src de votre balise img. Pour ne pas perdre l’information de l’url de l’image qu’on veu afficher, nous allons la mettre dans un attribut data-src (ou un autre nom).
<div class="container">
<img data-src="/mon-image.png" alt="mon image utilisant le lazy loading" />
</div>
Étape 2 : Détecter quand l’image doit être chargé
L’objectif du lazy loading est de charger l’image au dernier moment, lorsque l’utilisateur en a besoin. Pour cela, nous allons utiliser une API native de JavaScript qui permet d’observer lorsqu’un élément est sur le point d’apparaître à l’écran. L’IntersectionObserver nous permet de savoir quand une intersection entre un élément cible et un élément racine s’effectue.
const options = {
root: null, // null == viewport
rootMargin: "20px", // edit taille de root pour anticiper les intersections
threshold: 0 // seuil pour trigger
};
const intersectionObserver = new IntersectionObserver((elements) => {
elements.forEach((element) => {
console.log('intersection', element)
});
}, options);
intersectionObserver.observe(document.querySelector('img'));
Ici, on créé une instance de IntersectionObserver qui fera appel à la fonction callback passé en paramètre à chaque fois qu’un élément observé sera dans le viewport. Ensuite, on demande à notre instance d’observer notre image. La fonction callback sera appelé quand notre image sera affiché à l’écran de l’utilisateur.
Étape 3 : Charger l’image pour qu’elle s’affiche
Pour que notre navigateur charge notre image et l’affiche à notre utilisateur, il suffit de transformer l’attribut data-src en attribut src. Pour cela, nous allons modifier la fonction callback de notre IntersectionObserver pour faire des traitements sur la balise img pour qu’elle affiche notre image.
const intersectionObserver = new IntersectionObserver((elements) => {
elements.forEach((element) => {
if (false === element.isIntersecting) {
return;
}
const img = element.target;
if (img.hasAttribute("src")) {
return;
}
img.setAttribute("src", img.getAttribute("data-src"));
});
}, options);
Fin : Vous avez créé un système de lazy loading pour vos images
Grâce à l’onglet réseaux de Google Chrome, on peut voir que le trait bleu correspond à la fin de chargement du DOM et qu’ensuite, on a notre image (trait rouge) qui vient se charger suite à mon scroll vers la balise img. On peut s’assurer que c’est bien notre système de lazy loading qui est à l’origine de ce comportement, car l’initiateur est mon fichier JavaScript.
Le lazy loading natif des images
Maintenant que vous savez créer un système de lazy loading, je pense que c’est le bon moment pour vous dire qu’une grande partie des navigateurs comprennent le lazy loading natif du HTML. En effet, il vous suffit d’ajouter loading=’lazy’ à vos iframes et à vos images pour que le navigateur gère le lazy loading sans avoir à dev. WordPress utilise nativement le lazy loading, à moins que vous utilisiez des plugins pour optimiser votre site qui empêche de le faire fonctionner.
C’est quoi le lazy loading de contenu ?
Vous avez certainement déjà rencontré le lazy loading de contenu dans vos applications de tous les jours. TikTok, Instagram ou encore Facebook utilisent le lazy loading de contenu pour vous garder le plus longtemps possible sur leurs applications. Chargé du contenu en différé ou encore le scroll infinie sont des implémentations du lazy loading qui consiste à récupérer du contenu et l’afficher à l’utilisateur après que la page initiale soit chargée.
Les avantages du lazy loading de contenu
- Réduire le temps de chargement des pages web, les utilisateurs et les robots Google aime les faibles temps de chargement
- Optimiser les ressources utilisées par un utilisateur suivant son comportement sur le site
- Captiver un utilisateur plus longtemps grâce au scroll infini par exemple
Les inconvénients de différer le chargement de votre contenu
- Peut entraîner une mauvaise indexation du contenu chargé en différé
- Il faut le coder
Comment faire du chargement différé de contenu ?
Le système est très proche de celui pour les images, je ne vais donc pas vous refaire un tuto. La différence majeure entre le lazy loading de contenu et d’image est qu’ici, vous n’allez pas vous contenter de changer un attribut, mais vous allez devoir récupérer du contenu via une API par exemple et l’ajouter au DOM.
Qu’est ce que le lazy loading pour les SPA ?
Les SPA(Single Page Application) sont à la mode et ça se comprend. Les SPA permettant de charger une application une fois et de ne plus avoir à recharger la page lors de la navigation. Mais charger l’entièreté d’une application dès son arrivée peu donner lieu à un long temps de chargement pour les grosses applications. Pour contrer ce problème de temps de chargement long, il est possible de charger des petites parties de l’application au fur et à mesure qu’on navigue dedans grâce au lazy loading de module. La plupart des frameworks et librairies majeures pour le front-end permettent le lazy loading.
Les avantages du chargement différé des modules
- Diminuer la taille du bundle Javascript initial
- Accélérer le temps de chargement initiale de l’application
- Meilleur expérience de développement car quand on modifie un fichier, seul le NgModules correspondant va être rebuild
- Réduit le couplage dans l’application car on garantie la séparation du code des différentes features
Implémenter le lazy loading avec Angular
Pour comprendre le lazy loading d’Angular, il faut comprendre un des building block d’Angular : NgModules. NgModule est un fichier qui permet de décrire comment doit être compilé une partie de votre application et comment l’injection de dépendance doit fonctionner au runtime. Par défaut, au chargement de votre application, l’utilisateur va charger tous les NgModules, mais ce qui est intéressant, c’est qu’on peut les lazy loader. Mettre en place du lazy loading pour nos NgModules permettra de réduire le temps de chargements lors de l’arrivé de notre utilisateur, il complétera les autres NgModules qu’il a besoin suivant sa navigation.
Il ne s’agit pas d’un tuto step-by-step
Je vais vous présenter seulement les points clé pour réussir à implémenter du lazy loading pour vos NgModules. Un tutoriel plus détaillé pourrait voir le jour si on me le demande.
Étape 1 : Spécifier le NgModule à charger en fonction de la routes
Dans la gestion des routes de votre applications (routing module) vous pouvez demander à charger un NgModule spécifique pour une route, celui ci sera chargé par l’utilisateur au moment d’accéder à la route en question. Ici, on charge le NgModule RegisterModule lorsque l’utilisateur utilise la route ‘register’.
const routes: Routes = [
{
path: 'home',
component: HomeComponent
},
{
path: 'register',
loadChildren: () => import('./register/register.module')
.then(m => m.RegisterModule)
}
]
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Étape 2 : Créer une route dans le NgModule qui sera lazy loader
Maintenant que votre route renvoi vers un NgModule, il faut lui ajouter une route avec le component à utiliser. Pour cela, vous allez créer un routing module semblable à celui de l’app et l’importer dans votre NgModule.
const routes: Routes = [
{
path: '',
component: RegisterComponent
}
]
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class RegisterRoutingModule { }
Fin : Votre NgModule est bien chargé en différé
On peut voir au niveau de la cascade que j’ai un module qui a été chargé en décalé après tous les autres. Lorsque j’ai navigué vers la route qui correspond à mon NgModule ‘register’, le module a été récupéré et a permis d’afficher le component liée a cette route.
Proposition de lectures
Immediately Invoked Function Expression (IIFE) sont des fonctions utilisées automatiquement et directement après leur déclaration.
Les SPA pour Single Page Application est une implémentation d’une application web, elle consiste à mettre à jour le contenu de la page lors de la navigation au lieu de recharger la page entièrement.