Accueil » Culture web » Comprendre le lazy loading

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.

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);

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.

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.

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.

É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 { }

Proposition de lectures

iife
C’est quoi les IIFE en JavaScript ?

Immediately Invoked Function Expression (IIFE) sont des fonctions utilisées automatiquement et directement après leur déclaration.

les spa
C’est quoi les SPA ?

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.