Imports Dynamiques JavaScript : Maîtriser le Code Splitting et le Lazy Loading | MLOG | MLOG

Le composant Modal n'est chargé que lorsque l'utilisateur clique sur le bouton "Ouvrir la modale".

3. Code Splitting basé sur les fonctionnalités

Cette approche se concentre sur le fractionnement du code en fonction de fonctionnalités distinctes au sein de votre application. C'est particulièrement utile pour les grandes applications avec des fonctionnalités complexes qui ne sont pas toujours nécessaires pour tous les utilisateurs. Par exemple, un site de e-commerce pourrait charger en différé le code lié aux avis sur les produits ou aux listes de souhaits uniquement lorsque l'utilisateur interagit avec ces fonctionnalités.

Exemple (chargement différé d'une fonctionnalité de reporting) :

            import React, { useState, lazy, Suspense } from 'react';

const ReportingDashboard = lazy(() => import('./features/ReportingDashboard'));

function AdminPanel() {
  const [showReporting, setShowReporting] = useState(false);

  const handleShowReporting = () => {
    setShowReporting(true);
  };

  return (
    
{showReporting && ( Chargement du reporting...
}> )}
); } export default AdminPanel;

Le composant ReportingDashboard, contenant probablement des visualisations de données complexes et une logique d'analyse, n'est chargé que lorsque l'administrateur clique sur le bouton "Afficher le tableau de bord de reporting".

4. Code Splitting conditionnel

Cette technique consiste à importer dynamiquement des modules en fonction de certaines conditions, telles que l'appareil de l'utilisateur, son navigateur ou sa localisation. Cela vous permet d'adapter le code de votre application aux besoins spécifiques de chaque utilisateur, optimisant ainsi davantage les performances et l'utilisation des ressources. Pensez à servir différents formats d'image (par exemple, WebP pour les navigateurs compatibles) ou à ne charger les polyfills que pour les navigateurs plus anciens.

Exemple (chargement de polyfills pour les navigateurs anciens) :

            async function loadPolyfills() {
  if (!('fetch' in window)) {
    await import('whatwg-fetch');
    console.log('Polyfill Fetch chargé.');
  }

  if (!('Promise' in window)) {
    await import('promise-polyfill/src/polyfill');
    console.log('Polyfill Promise chargé.');
  }
}

loadPolyfills();

            

Ce code vérifie si l'API fetch et Promise sont prises en charge par le navigateur. Si ce n'est pas le cas, il importe dynamiquement les polyfills correspondants.

Stratégies de Lazy Loading

Le lazy loading (chargement différé) est une technique qui reporte le chargement des ressources jusqu'à ce qu'elles soient réellement nécessaires. Cela peut considérablement améliorer les temps de chargement initiaux de la page et réduire la consommation de bande passante. Les imports dynamiques sont un outil puissant pour mettre en œuvre le lazy loading dans les applications JavaScript.

1. Lazy Loading des images

Les images sont souvent un contributeur majeur à la taille d'une page. Le lazy loading des images garantit que les images situées sous la ligne de flottaison (c'est-à-dire celles qui ne sont pas immédiatement visibles dans la fenêtre d'affichage) ne sont chargées que lorsque l'utilisateur fait défiler la page vers le bas.

Exemple (avec l'API Intersection Observer) :

            const images = document.querySelectorAll('img[data-src]');

function preloadImage(img) {
  img.src = img.dataset.src;
  img.onload = () => {
    img.removeAttribute('data-src');
  };
}

const imgObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      preloadImage(entry.target);
      observer.unobserve(entry.target);
    }
  });
});

images.forEach(img => {
  imgObserver.observe(img);
});

            

Dans cet exemple, l'attribut data-src contient l'URL de l'image. L'API Intersection Observer est utilisée pour détecter quand l'image entre dans la fenêtre d'affichage, moment auquel l'image est chargée.

2. Lazy Loading des vidéos

Semblables aux images, les vidéos peuvent également avoir un impact significatif sur les temps de chargement des pages. Le lazy loading des vidéos empêche leur chargement jusqu'à ce que l'utilisateur interagisse avec elles (par exemple, en cliquant sur un bouton de lecture).

Exemple (lazy loading d'une vidéo avec une image de remplacement) :

            
Espace réservé pour la vidéo

La vidéo est initialement représentée par une image de remplacement. Lorsque l'utilisateur clique sur le bouton de lecture, la source de la vidéo est chargée et la lecture commence.

3. Lazy Loading des Iframes

Les iframes, souvent utilisées pour intégrer du contenu provenant de sources tierces, peuvent également affecter les performances de la page. Le lazy loading des iframes garantit qu'elles ne sont chargées que lorsque l'utilisateur fait défiler la page à proximité.

Exemple (lazy loading d'une iframe avec l'API Intersection Observer) :

            const iframes = document.querySelectorAll('iframe[data-src]');

function loadIframe(iframe) {
  iframe.src = iframe.dataset.src;
  iframe.onload = () => {
    iframe.removeAttribute('data-src');
  };
}

const iframeObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      loadIframe(entry.target);
      observer.unobserve(entry.target);
    }
  });
});

iframes.forEach(iframe => {
  iframeObserver.observe(iframe);
});

            

Similaire à l'exemple de lazy loading d'image, ce code utilise l'API Intersection Observer pour détecter quand l'iframe entre dans la fenêtre d'affichage, puis charge le contenu de l'iframe.

Webpack et les imports dynamiques

Webpack est un bundler de modules populaire qui offre un excellent support pour les imports dynamiques. Il détecte automatiquement les instructions d'import dynamique et divise votre code en "chunks" (morceaux) séparés, qui peuvent ensuite être chargés à la demande.

Configuration :

Aucune configuration spéciale n'est généralement requise pour activer les imports dynamiques dans Webpack. Cependant, vous pourriez vouloir configurer plus en détail le code splitting en utilisant des fonctionnalités comme :

Exemple (configuration Webpack pour le code splitting) :

            module.exports = {
  // ...
  output: {
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].js',
    path: path.resolve(__dirname, 'dist'),
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
  // ...
};

            

Cette configuration crée un chunk séparé pour les bibliothèques tierces (code provenant de node_modules) et utilise un hash unique pour chaque chunk afin de permettre la mise en cache par le navigateur.

React et les imports dynamiques

React offre un support intégré pour le chargement différé des composants en utilisant la fonction React.lazy() et le composant Suspense. Cela facilite la mise en œuvre du code splitting dans les applications React.

Exemple (chargement différé d'un composant React) :

            import React, { lazy, Suspense } from 'react';

const MyComponent = lazy(() => import('./MyComponent'));

function App() {
  return (
    Chargement...
}> ); } export default App;

La fonction React.lazy() prend une fonction qui retourne un import dynamique. Le composant Suspense fournit une interface utilisateur de secours pendant le chargement du composant.

Angular et les imports dynamiques

Angular prend en charge le lazy loading des modules via sa configuration de routage. Vous pouvez définir des routes qui chargent des modules à la demande, ce qui peut améliorer considérablement le temps de chargement initial de votre application Angular.

Exemple (lazy loading d'un module dans Angular) :

            import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'feature',
    loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule)
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

            

Dans cet exemple, le FeatureModule est chargé uniquement lorsque l'utilisateur navigue vers la route /feature.

Vue.js et les imports dynamiques

Vue.js fournit également un support pour le chargement différé des composants en utilisant les imports dynamiques. Vous pouvez utiliser la syntaxe import() dans vos définitions de composants pour charger des composants à la demande.

Exemple (chargement différé d'un composant Vue.js) :

            Vue.component('async-component', () => ({
  // Le composant Ă  charger. Doit ĂŞtre une Promise
  component: import('./AsyncComponent.vue'),
  // Un composant Ă  utiliser pendant le chargement du composant asynchrone
  loading: LoadingComponent,
  // Un composant à utiliser si le chargement échoue
  error: ErrorComponent,
  // Délai avant d'afficher le composant de chargement. Défaut : 200ms.
  delay: 200,
  // Le composant d'erreur sera affiché si un timeout est
  // fourni et dépassé.
  timeout: 3000
}))

            

Cet exemple définit un composant asynchrone nommé async-component qui charge le fichier AsyncComponent.vue à la demande. Il fournit également des options pour les composants de chargement, d'erreur, de délai et de timeout.

Meilleures pratiques pour les imports dynamiques et le Lazy Loading

Pour tirer parti efficacement des imports dynamiques et du lazy loading, considérez les meilleures pratiques suivantes :

Considérations mondiales

Lors de la mise en œuvre d'imports dynamiques et de lazy loading pour un public mondial, il est crucial de prendre en compte les éléments suivants :

Conclusion

Les imports dynamiques JavaScript fournissent un mécanisme puissant pour mettre en œuvre le code splitting et le lazy loading, vous permettant d'optimiser les performances de votre application web et d'offrir une expérience utilisateur supérieure à un public mondial. En fractionnant stratégiquement votre code en fonction des routes, des composants ou des fonctionnalités, et en chargeant les ressources à la demande, vous pouvez réduire considérablement les temps de chargement initiaux, améliorer la réactivité et augmenter l'efficacité globale de l'application. N'oubliez pas de suivre les meilleures pratiques, de tenir compte des considérations mondiales et de surveiller en permanence les performances de votre application pour vous assurer que vous offrez la meilleure expérience possible aux utilisateurs du monde entier. Adoptez ces techniques et regardez votre application prospérer dans le paysage numérique mondial.