Skip to main content

Technology

Améliorez la vitesse de votre application React grâce à des techniques d'optimisation des performances qui ont fait leurs preuves

July 14, 2026 • 6 Minutes Read

Améliorez la vitesse de votre application React grâce à des techniques d'optimisation des performances qui ont fait leurs preuves
Harsh Joshi

Harsh Joshi

Co-founder & Technical Director

Votre application React était rapide lorsque vous l'avez créée. Aujourd'hui, elle est lente, les temps de chargement ont augmenté et les utilisateurs commencent à s'en rendre compte. La bonne nouvelle, c'est que la plupart des problèmes de performances liés à React proviennent d'une poignée de causes profondes qui peuvent être corrigées.

Ce guide vous présente sept techniques éprouvées pour accélérer votre application React avec des données concrètes, des modèles de code pratiques et des conseils clairs sur les situations dans lesquelles les appliquer. Que votre application soit lente au démarrage, qu'elle mette du temps à réagir aux actions de l'utilisateur ou qu'elle ait du mal à gérer des ensembles de données volumineux, vous trouverez ici une solution adaptée à votre problème.

Avant même d'écrire la moindre ligne de code, ouvrez le profileur de React DevTools et enregistrez une interaction qui vous semble lente. La vue « flamegraph » vous montre précisément quels composants sont affichés, combien de temps dure chaque rendu et ce qui l'a déclenché. Optimiser sans ces données revient à avancer à l'aveuglette. Grâce à elles, vous pouvez concentrer vos efforts là où cela fait réellement la différence.

1. Fractionnement du code pour un chargement plus rapide

Par défaut, votre outil de compilation regroupe l'intégralité de votre application React dans un seul fichier JavaScript. Chaque utilisateur télécharge l'intégralité de ce fichier, y compris les parties qu'il ne consulte jamais.

Le « code splitting » divise ce bloc en segments plus petits qui ne se chargent qu’en cas de besoin. React.lazy() associé à Suspense simplifie le fractionnement au niveau des itinéraires :

import { lazy, Suspense } from 'react';

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

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Dashboard />
    </Suspense>
  );
}

Le Tableau de bord Le composant ne se charge désormais que lorsqu'il est affiché, et non plus dès la première visite de la page. Pour la plupart des applications, le fractionnement du code au niveau des routes réduit la taille initiale du bundle de 30 à 50 %, ce qui améliore directement le Largest Contentful Paint (LCP). Selon HTTP Archive (données de 2024), la taille médiane des fichiers JavaScript pour les utilisateurs d'ordinateurs de bureau dépasse déjà les 500 Ko. Un fractionnement rigoureux permet d'empêcher ce chiffre de continuer à augmenter.

Au-delà des itinéraires, pensez à fractionner les bibliothèques tierces volumineuses (bibliothèques de graphiques, éditeurs de texte enrichi, visionneuses de PDF) qui n'apparaissent que sur certaines pages spécifiques. Utilisez Analyseur de paquets Webpack pour visualiser votre ensemble et identifier les éléments qui y contribuent le plus avant de décider où effectuer la scission.

2. La mémorisation pour éviter les rendu inutiles

React réaffiche un composant chaque fois que son parent est réaffiché, même lorsque les props de ce composant n’ont pas changé. Dans un tableau de bord comportant 50 composants, une modification de l’état au niveau supérieur peut entraîner le réaffichage inutile de l’ensemble des 50 composants. Selon une étude menée par Bit.dev, de mauvaises performances d’affichage peuvent augmenter le temps d’exécution des scripts de 30 à 60 %, un impact tangible sur les deux expérience utilisateur et référencement naturel (SEO).

React.memo C'est votre première ligne de défense. Elle encapsule un composant et effectue une comparaison superficielle des propriétés avant de déclencher un réaffichage :

const ExpensiveList = React.memo(function ExpensiveList({ items }) {
  return (
    <ul>
      {items.map(item => <li key={item.id}>{item.name}</li>)}
    </ul>
  );
});

React.memo ne fonctionne que lorsque les props qu'il reçoit ont des références stables. À associer avec useMemo pour les valeurs calculées et useCallback pour les gestionnaires d'événements :

function ProductPage({ products }) {
  const sortedProducts = useMemo(() => {
    return [...products].sort((a, b) => b.price - a.price);
  }, [products]);

  const handleDelete = useCallback((id) => {
    // delete logic
  }, []);

  return <ExpensiveList items={sortedProducts} onDelete={handleDelete} />;
}

Quand ne pas recourir à la mémorisation : Chaque React.memo Le wrapper effectue une comparaison superficielle à chaque rendu. Pour les composants petits et rapides à afficher, cette surcharge peut s'avérer plus coûteuse qu'un simple réaffichage. Commencez par analyser les performances avec React DevTools, puis appliquez la mémorisation de manière sélective aux composants dont le temps de rendu est supérieur à 5–10 ms et qui sont fréquemment déclenchés. Enveloppez tout dans React.memo L'absence de mesure est un anti-modèle courant.

Lorsqu'elle est correctement mise en œuvre, la mémorisation permet de réduire les ré-affichages de 30 à 50 % sur de longues listes. Un audit interne a mis en évidence un 40 % réduction du nombre de rafraîchissements sur la page de fiche produit après une mémorisation ciblée.

3. Virtualiser les listes volumineuses

L'affichage d'une liste de 500 éléments implique que le navigateur crée 500 nœuds DOM, gère 500 écouteurs d'événements et effectue des opérations de mise en page et de dessin pour chacun d'entre eux, même ceux qui se trouvent bien en dehors de la zone visible. Il en résulte un affichage initial lent, un défilement saccadé et une consommation de mémoire élevée.

La virtualisation résout ce problème en ne rendant que les éléments actuellement visibles dans la fenêtre d'affichage, auxquels s'ajoute une petite marge de sécurité. react-window C'est la bibliothèque la plus couramment utilisée à cet effet :

import { FixedSizeList } from 'react-window';

function VirtualizedList({ items }) {
  return (
    <FixedSizeList
      height={400}
      itemCount={items.length}
      itemSize={50}
      width={300}
    >
      {({ index, style }) => (
        <div style={style}>{items[index].name}</div>
      )}
    </FixedSizeList>
  );
}

Pour une liste de 10 000 éléments, cela permet d’afficher environ 20 nœuds DOM à tout moment, au lieu de 10 000. Il a été démontré que cette seule modification permettait de réduire le temps d’affichage de la liste de plus de 3 secondes à un temps quasi instantané.

Recourez à la virtualisation lorsque votre liste dépasse 100 éléments. En dessous de ce seuil, le DOM gère la charge sans dégradation notable. Au-delà, les gains s’accumulent à mesure que la liste s’allonge. Veillez également à utiliser des propriétés-clés stables et uniques : l’utilisation de l’index du tableau comme clé provoque des bugs subtils lors du réordonnancement et du filtrage, et oblige React à réafficher inutilement la liste entière.

4. Optimiser les images et autres ressources

Les images constituent généralement les fichiers les plus volumineux d'une page React. Les images volumineuses et non compressées ralentissent le chargement de la page, allongent les temps de LCP et gaspillent de la bande passante, en particulier sur les réseaux mobiles.

Passez à des formats modernes. Les images WebP sont 25 à 35 % plus petit que les fichiers JPEG à qualité équivalente. Le format AVIF offre un taux de compression encore plus élevé lorsque les navigateurs le prennent en charge. La mise à jour de votre pipeline d'images pour servir des fichiers WebP par défaut est l'une des solutions les plus rapides à mettre en œuvre :

<img src="photo.webp" alt="Product image" />

Chargement différé des images hors écran. L'autochtone loading="lazy" L'attribut indique au navigateur de ne charger les images que lorsqu'elles apparaissent à l'écran. Cela réduit le poids initial de la page et évite que les images hors écran n'entrent en concurrence avec les ressources essentielles :

<img src="photo.webp" loading="lazy" alt="Product image" />

Proposez des images adaptatives. Envoyer une image de 2 000 px sur un écran de mobile de 400 px gaspille de la bande passante et ralentit le chargement. Utilisez srcSet et tailles pour afficher des images dont la taille est adaptée à la fenêtre d'affichage :

<img
  srcSet="photo-400.webp 400w, photo-800.webp 800w"
  sizes="(max-width: 600px) 400px, 800px"
  src="photo-800.webp"
  alt="Product image"
/>

Si vous êtes développement avec Next.js, le suivant/image Le composant gère automatiquement la conversion de format, l'ajustement dynamique de la taille et le chargement différé.

5. Utiliser une version de production et réduire la taille du bundle

Les versions de développement de React contiennent des avertissements supplémentaires, des outils de débogage et du code non minifié, qui n'ont pas leur place en production. Déployez toujours à l'aide d'une version de production. Dans Créer une application React, cela signifie courir npm run build. Dans Next.js, cela signifie prochaine version. La différence de taille entre les lots est considérable.

Au-delà du mode de compilation, maîtrisez la taille de votre bundle grâce au « tree shaking ». Les outils de bundling modernes (Webpack, Vite, Rollup) éliminent automatiquement le code inutilisé, mais uniquement si vous importez exactement ce dont vous avez besoin :

// Imports the entire lodash library (~70KB)
import _ from 'lodash';

// Imports only the function you need (~2KB)
import debounce from 'lodash/debounce';

Cette simple modification au niveau de l'importation réduit la taille d'une dépendance de 70 Ko à 2 Ko. Si l'on applique ce principe à 10 à 15 dépendances, la réduction cumulée est considérable.

Utilisation Analyseur de paquets Webpack pour identifier les éléments les plus volumineux. Vous constaterez souvent qu’un ou deux paquets représentent une part disproportionnée de votre ensemble et qu’il existe des alternatives plus légères.

6. Mettre en place le chargement différé pour les composants

Le chargement différé est étroitement lié au fractionnement de code, mais son champ d'application va au-delà des routes. Tout composant dont le rendu est coûteux et qui n'est pas nécessaire lors du chargement initial peut faire l'objet d'un chargement différé.

Vous avez déjà vu React.lazy() Dans la section consacrée au fractionnement du code. Appliquez le même principe à :

  • Boîtes de dialogue modales qui n'apparaissent qu'à la suite d'une action de l'utilisateur
  • Panneaux d'administration ou les écrans de paramètres consultés rarement
  • Graphiques et visualisations de données qui ne s’affichent que sur certaines pages
  • Intégrations tierces — lecteurs vidéo, visionneuses de PDF, cartes

Évitez d'appliquer le chargement différé aux composants situés juste au-dessus de la ligne de flottaison. Si l'utilisateur les voit dès le premier affichage, ils doivent se charger immédiatement ; sinon, vous créez un délai perceptible qui donne l'impression d'un bug.

Pour les saisies dans les champs de recherche et autres interactions qui déclenchent des calculs gourmands en ressources, pensez à mettre en place un délai de rebond afin de limiter la fréquence à laquelle ces calculs sont effectués :

useEffect(() => {
  const timer = setTimeout(() => {
    setDebouncedQuery(query);
  }, 300);
  return () => clearTimeout(timer);
}, [query]);

Une fenêtre anti-rebond de 300 ms permet de détecter la plupart des pauses lors de la saisie sans ajouter de délai perceptible. Pour les applications React utilisant React 18 ou une version ultérieure, useTransition Propose une alternative à React Native qui préserve la réactivité de l'interface utilisateur tout en différant les mises à jour d'état non urgentes, ce qui s'avère particulièrement efficace pour les fonctionnalités de recherche en temps réel.

7. Suivre et analyser les performances en continu

La gestion des performances n'est pas une tâche ponctuelle. Les fonctionnalités sont déployées, les dépendances s'accumulent, et ce qui est rapide aujourd'hui peut devenir un goulot d'étranglement dans trois mois. C'est la surveillance continue qui distingue les équipes qui maintiennent les performances de celles qui ne redécouvrent les problèmes qu'après les plaintes des utilisateurs.

Voici les outils à intégrer à votre flux de travail habituel :

Profilateur React DevTools Il permet d'identifier les composants qui ont été affichés, la durée de chaque affichage et ce qui l'a déclenché. Utilisez-le pendant le développement et après la publication de nouvelles fonctionnalités majeures afin de détecter les régressions avant qu'elles n'atteignent l'environnement de production.

Phare (disponible dans Chrome DevTools) analyse votre application par rapport aux seuils définis par les Core Web Vitals : LCP inférieur à 2,5 secondes, INP inférieur à 200 millisecondes et CLS inférieur à 0,1. Exécutez-le dans votre pipeline d'intégration continue (CI) pour éviter que des baisses de performances ne se glissent dans l'environnement de production sans être détectées.

Web Vitals JS collecte des données provenant d'utilisateurs réels en environnement de production. Les mesures effectuées en laboratoire ne reflètent pas toujours l'expérience réelle des utilisateurs sur différents appareils et dans diverses conditions réseau. Les données de terrain, elles, le font.

Onglet « Performances » de Chrome DevTools offre une vue image par image du temps d'exécution du JavaScript, des tâches longues, des événements de dessin et de mise en page, ainsi que des pertes d'images. Utilisez-le lorsque le Profiler signale un composant lent, mais que vous avez besoin de comprendre ce qui se passe au niveau du navigateur.

Intégrez l'analyse de profilage à votre processus de révision du code, en particulier pour les composants partagés et les kits d'interface utilisateur. Examinez les graphiques de flammes après chaque refactorisation majeure. Configurez des alertes en cas de régression des Core Web Vitals. Les équipes qui détectent les problèmes de performances le plus tôt sont celles qui passent le moins de temps à les résoudre.

Pour accélérer le démarrage d’une application React, il faut commencer par adopter la bonne approche

La vitesse n'est pas seulement un indicateur technique. Chaque tranche de 100 millisecondes de latence a un impact mesurable sur les taux de conversion, et les sites qui respectent systématiquement les trois seuils des Core Web Vitals obtiennent systématiquement de meilleurs résultats que leurs concurrents dans les résultats de recherche naturelle.

Les techniques présentées dans ce guide — fractionnement du code, mémorisation, virtualisation, optimisation des images, versions de production, chargement différé et surveillance continue — s’attaquent aux causes profondes de la plupart des problèmes de performances liés à React. Appliquez-les de manière systématique, effectuez des mesures avant et après chaque modification, et concentrez vos efforts sur les goulots d’étranglement que le Profiler met réellement en évidence.

Prêt à optimiser encore davantage les performances de votre application React ?

Monarch Innovation collabore avec des équipes de développement pour identifier les goulots d'étranglement en matière de performances, mettre en œuvre des stratégies d'optimisation et créer des applications React plus rapides et plus évolutives. Découvrez ce que Monarch Innovation peut apporter à votre projet.

Foire aux questions

Qu'est-ce que le « code splitting » et en quoi permet-il d'accélérer une application React ?

Le fractionnement de code est une technique qui consiste à diviser votre application React en plusieurs paquets JavaScript plus petits, au lieu de charger l'application dans son intégralité en une seule fois. Cela permet aux utilisateurs de ne télécharger que le code nécessaire à la page en cours, ce qui réduit le temps de chargement initial et améliore les performances. React prend en charge le fractionnement de code à l'aide de React.lazy() et dynamique import().

Quand faut-il utiliser React.memo, useMemo et useCallback ?

Ces outils d'optimisation React permettent d'éviter les réaffichages inutiles :

  • React.memo: Regroupez les composants fonctionnels qui reçoivent fréquemment les mêmes props afin d'éviter un rafraîchissement inutile.
  • useMemo: Mémoriser les calculs coûteux afin qu'ils ne soient exécutés que lorsque les dépendances changent.
  • useCallback: Mémorisez les fonctions de rappel afin d'éviter toute recréation inutile de fonctions, en particulier lorsque vous transmettez des fonctions à des composants enfants.

Ne les utilisez que lorsque l'analyse de performance met en évidence des goulots d'étranglement, car une mémorisation excessive peut ajouter une complexité inutile.

Comment virtualiser des listes volumineuses dans React ?

La virtualisation ne rend que les éléments visibles d'une longue liste, au lieu de tous les éléments du DOM. Cela améliore considérablement les performances de rendu et réduit l'utilisation de la mémoire. Des bibliothèques telles que react-window et react-virtualized sont couramment utilisées pour afficher efficacement des milliers de lignes tout en garantissant un défilement fluide.

Comment optimiser les images dans une application React ?

L'optimisation des images améliore la vitesse de chargement des pages et l'expérience utilisateur grâce à :

  • Compression des images avant leur mise en ligne.
  • En utilisant des formats modernes tels que WebP ou AVIF.
  • Fournir des images adaptatives aux dimensions appropriées.
  • Mise en place du chargement différé pour les images situées sous la ligne de flottaison.
  • Utilisation d'un CDN pour accélérer la diffusion des images.

Ces pratiques permettent de réduire la consommation de bande passante et d'améliorer les indicateurs Core Web Vitals.

Qu'est-ce que le chargement différé et quels composants dois-je charger de manière différée dans React ?

Le chargement différé retarde le chargement des composants jusqu’à ce qu’ils soient réellement nécessaires. Il réduit la taille initiale du paquet et accélère le chargement de la première page.

Parmi les éléments qui se prêtent bien au chargement différé, on peut citer :

  • Pages basées sur les itinéraires
  • Tableaux de bord d'administration
  • Pages de paramètres
  • Modules de graphiques et d'analyse
  • Grands formulaires
  • Fenêtres modales et boîtes de dialogue
  • Composants tiers qui ne sont pas immédiatement visibles

React propose React.lazy() et Suspense pour mettre en œuvre efficacement le chargement différé.

Comment puis-je surveiller en continu les performances d'une application React ?

La surveillance des performances doit être un processus continu. Suivez régulièrement des indicateurs tels que le temps de chargement des pages, la réactivité des interactions, la taille des paquets et les Core Web Vitals. Utilisez des outils tels que Lighthouse, le profileur de React DevTools, le panneau « Performance » de Chrome DevTools et des solutions de surveillance des utilisateurs réels (RUM) pour identifier les goulots d'étranglement. Une surveillance continue permet de détecter rapidement les régressions et garantit que votre application React reste rapide à mesure qu’elle évolue.


Partager sur :