Temps de traitement de l'INP : causes, optimisation et exemples de code

Apprenez à trouver et à résoudre les problèmes d'INP causés par le temps de traitement

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-03

Problèmes d'Interaction to Next Paint (INP) causés par le temps de traitement

Cette page fait partie de notre série sur l'Interaction to Next Paint (INP). L'INP mesure le temps total écoulé entre une interaction de l'utilisateur et la mise à jour visuelle suivante. Le temps de traitement (processing time) est la deuxième des trois phases qui composent l'INP, précédée par le délai d'entrée (input delay) et suivie par le délai de présentation (presentation delay). Si vous ne connaissez pas bien l'INP, lisez d'abord notre guide sur la façon d'identifier et résoudre les problèmes d'INP.

En bref : L'Interaction to Next Paint (INP) mesure le temps nécessaire pour qu'un utilisateur voie un changement visuel sur une page après avoir interagi avec elle. Cet INP peut être décomposé en 3 composants : le "délai d'entrée", le "temps de traitement" et le "délai de présentation".

Le temps de traitement est un contributeur majeur à l'INP total, représentant environ 40 % du délai en moyenne. L'optimisation de vos gestionnaires d'événements (event handlers) est le moyen le plus direct de réduire le temps de traitement et d'améliorer votre score INP.

CONSEIL INP : le temps de traitement peut être optimisé en exécutant immédiatement le code important qui précède la mise à jour de la mise en page (layout update) et en planifiant l'exécution de tout le reste du code après cela.

Qu'est-ce que le temps de traitement ?

L'Interaction to Next Paint (INP) peut être décomposée en 3 sous-parties : le "Délai d'entrée", le "Temps de traitement" et le "Délai de présentation".

Le temps de traitement fait référence au temps nécessaire au navigateur pour exécuter tous les rappels d'événements (callbacks) associés après qu'un utilisateur a interagi avec une page web (par exemple, en cliquant sur un bouton ou en appuyant sur une touche). Bien qu'il y ait toujours un certain temps de traitement, les problèmes d'INP surviennent lorsque les rappels d'événements prennent trop de temps de traitement.

Pour faire simple : le temps de traitement est la durée du "travail" qui s'effectue en réponse à votre interaction. Lorsque vous cliquez sur un bouton de recherche, le temps de traitement comprend tout, de la validation de votre requête à la préparation de la requête API, la mise à jour de l'état local, le déclenchement d'événements d'analyse (analytics) et tout autre code attaché à cet événement de clic. Chaque ligne de JavaScript dans ces gestionnaires d'événements contribue au temps de traitement.

Temps de traitement et INP

Le temps de traitement pourrait bien être la première chose qui vous vient à l'esprit lorsque vous pensez à optimiser l'Interaction to Next Paint. C'est le "travail qui doit être fait" avant que la mise en page ne puisse être mise à jour par le navigateur.

De nombreux développeurs pensent à améliorer l'INP en termes d'optimisation des fonctions de rappel (optimisation du temps de traitement), et ils ont raison. Mais en termes d'importance, le temps de traitement n'est même pas la partie la plus importante à améliorer. Il représente toujours, en moyenne, environ 40 % du temps total de l'INP.

Chez CoreDash, nous collectons des millions de points de données Core Web Vitals chaque heure. D'après ces données, le temps de traitement représente 40 % de l'Interaction to Next Paint. 40 %, c'est beaucoup, mais optimiser uniquement le temps de traitement ne résoudra pas les problèmes d'INP. Vous devriez également examiner le délai d'entrée (18 %) et le délai de présentation (42 %).

Exemple de temps de traitement : Lorsqu'un utilisateur clique sur un bouton pour soumettre un formulaire, le code qui valide les données du formulaire, les envoie au serveur et gère la réponse contribue au temps de traitement. Plus ces opérations prennent du temps, plus le temps de traitement est long, et potentiellement, plus le score INP est mauvais.

Quelles sont les causes d'un temps de traitement élevé ?

Un temps de traitement élevé a quatre causes courantes : du code inutile, du code non optimisé, des rappels regroupés et le thrashing de la mise en page (layout thrashing).

  1. Code inutile. Le code ancien, inutilisé ou le code sans pertinence immédiate pour l'interaction de l'utilisateur peut prolonger le temps d'exécution des rappels. Cela inclut les appels d'analyse, la journalisation (logging) et la synchronisation de l'état qui n'ont pas besoin d'être terminés avant le prochain rendu (paint).
  2. Code non optimisé. Un code inefficace (généralement des boucles ou des recherches DOM inefficaces) peut rendre l'exécution des rappels d'événements plus lente que nécessaire. Un exemple courant est l'interrogation du DOM à l'intérieur d'une boucle avec document.querySelectorAll() au lieu de mettre le résultat en cache avant la boucle.
  3. Rappels regroupés (Clustered callbacks). Plusieurs rappels d'événements planifiés de manière rapprochée créent une file d'attente. Si un rappel déclenché par l'interaction de l'utilisateur reste bloqué dans cette file d'attente, la réponse semble retardée. Par exemple, un gestionnaire pointerdown, un gestionnaire mousedown et un gestionnaire click peuvent tous se déclencher séquentiellement pour un seul clic.
  4. Layout thrashing. Les manipulations fréquentes du DOM qui déclenchent des recalculs de la mise en page peuvent surcharger le navigateur et entraîner des baisses de performances. Cela se produit lorsque votre code alterne entre la lecture et l'écriture des propriétés de mise en page à l'intérieur d'une boucle, forçant le navigateur à recalculer la mise en page plusieurs fois.

Minimiser le temps de traitement

Pour améliorer l'INP causé par un long temps de traitement, nous devons faire en sorte que le code responsable de la mise à jour ultérieure de la mise en page s'exécute le plus rapidement possible.

La stratégie est double : optimiser le code existant (supprimer le code inutile et optimiser le code actuel) et distinguer le code qui doit s'exécuter avant et après la mise à jour de la mise en page. Le code qui est critique pour la mise à jour de la mise en page doit s'exécuter en premier, et tout le reste du code peut s'exécuter après la mise à jour de la mise en page.

  1. Supprimer le code inutilisé. Bien que la suppression du code inutilisé puisse sembler évidente, sur la plupart des sites, il y a au moins quelques anciens codes inutilisés qui s'exécutent sans rien ajouter de réel à la page ni à l'UX. La première chose à faire est de s'assurer qu'aucun code non nécessaire ne s'exécute. Cela peut être fait par le tree shaking, le fractionnement du code (code splitting), l'inspection de la couverture de votre code dans Chrome, et en utilisant un bon IDE qui signalera le code inutilisé. (Conseil de pro : jetez également un regard critique sur les ressources chargées par votre Tag Manager.) Pour plus de stratégies, consultez notre guide sur les 14 méthodes pour différer le JavaScript.
  2. Minimiser le temps d'exécution des rappels. Utilisez un profileur JavaScript pour identifier les goulots d'étranglement dans votre code et cibler ces zones pour l'optimisation. Envisagez des techniques telles que la mémorisation (memoization), le précalcul et la mise en cache pour éviter les calculs redondants. (Conseil : vous pouvez utiliser le panneau de performances de Chrome pour trouver les scripts dont le temps d'exécution est long.)
  3. Prioriser le code critique et planifier le reste du code. Lorsque le code de rappel a été optimisé, divisez-le en code qui doit s'exécuter immédiatement et en code qui peut être différé. Jetez un œil à cet exemple concret :

    Dans cet exemple, les rappels d'événements de Google Tag Manager et de Facebook sont exécutés avant le code (React) qui précède la mise à jour de la mise en page. La solution consiste à planifier l'exécution des rappels GTM et Facebook lorsque le navigateur est inactif.
  4. Éviter le layout thrashing ou reflow. Le layout thrashing se produit lorsque les mises à jour de style et les lectures de style sont mélangées dans une boucle, ce qui oblige le navigateur à recalculer la mise en page à de nombreuses reprises. Pour éviter le layout thrashing, effectuez toutes les modifications de style (les "sets" ou écritures) avant de demander les valeurs de style (les "gets" ou lectures). Cette approche minimise la fréquence des mises à jour de mise en page, ce qui donne une page plus rapide. Par exemple, dans une boucle qui définit la largeur de chaque paragraphe pour qu'elle corresponde à la largeur d'un élément, lisez la largeur de l'élément une fois avant la boucle et utilisez cette valeur pour mettre à jour la largeur des paragraphes à l'intérieur de la boucle.

Fractionner les gestionnaires d'événements avec setTimeout(0)

Lorsque vous ne pouvez pas supprimer ou différer le code d'un gestionnaire d'événements, la meilleure option suivante consiste à le diviser en plus petits morceaux. Le modèle setTimeout(callback, 0) vous permet de répartir le travail sur plusieurs tâches, donnant au navigateur une chance de gérer la mise à jour de la mise en page entre elles. Voici un exemple pratique :

// Avant : un long gestionnaire d'événements bloque le prochain rendu
button.addEventListener('click', () => {
  updateUI();           // Critique : doit s'exécuter avant le rendu
  validateForm();       // Important mais peut attendre
  sendAnalytics();      // Non critique
  syncLocalStorage();   // Non critique
});

// Après : séparation en travail critique et différé
button.addEventListener('click', () => {
  updateUI();  // Critique : s'exécute immédiatement avant le rendu

  setTimeout(() => {
    validateForm();
  }, 0);

  setTimeout(() => {
    sendAnalytics();
    syncLocalStorage();
  }, 0);
});

L'inconvénient de setTimeout(0) est qu'il place la suite à la fin de la file d'attente des tâches. Si d'autres tâches sont déjà en file d'attente, le code différé peut ne pas s'exécuter immédiatement. Pour un comportement plus prévisible, utilisez plutôt scheduler.yield() (voir la section ci-dessous). Pour des modèles qui ciblent spécifiquement la gestion du défilement en JavaScript, consultez notre guide dédié.

Utiliser requestAnimationFrame pour les mises à jour visuelles

Lorsque votre gestionnaire d'événements doit déclencher une mise à jour visuelle, requestAnimationFrame() garantit que votre code s'exécute au moment optimal : juste avant que le navigateur n'effectue son prochain rendu (repaint). C'est particulièrement utile lorsque vous devez regrouper les lectures et écritures DOM pour éviter le layout thrashing.

// Utilisez requestAnimationFrame pour regrouper les mises à jour visuelles
button.addEventListener('click', () => {
  // Lisez d'abord les propriétés de mise en page (en dehors du rAF)
  const containerWidth = container.offsetWidth;

  requestAnimationFrame(() => {
    // Écrivez les propriétés de mise en page à l'intérieur du rAF
    items.forEach(item => {
      item.style.width = containerWidth + 'px';
    });
  });

  // Planifiez le travail non visuel pendant le temps d'inactivité
  requestIdleCallback(() => {
    trackButtonClick();
    updateSessionState();
  });
});

Ce modèle sépare les lectures DOM des écritures DOM, empêchant ainsi une mise en page synchrone forcée. La mise à jour visuelle s'exécute au moment idéal dans le pipeline de rendu du navigateur, et le travail non visuel s'exécute pendant le temps d'inactivité.

Comment prioriser le code critique

"Prioriser le code critique et planifier l'autre code" semble abstrait, voici donc à quoi cela ressemble dans la pratique. Nous pouvons prioriser le code critique en utilisant requestIdleCallback() et en cédant la place au thread principal (yielding).

Nous utilisons requestIdleCallback pour les tâches moins importantes qui n'ont pas besoin de s'exécuter immédiatement. Voici un exemple avant/après de planification d'un événement GTM :

/* avant : exécuter le code immédiatement */
gtag('event', '<event_name>', {
   'event_category': '<event_category>',
 });

/* après : exécuter le même code pendant l'inactivité du navigateur */
requestIdleCallback(() => {
  gtag('event', '<event_name>', {
    'event_category': '<event_category>',
  });
}, { timeout: 1000 });

L'inconvénient de requestIdleCallback est que le code peut ne pas s'exécuter aussi vite que vous le souhaiteriez. Dans ce cas, vous pouvez "céder la place au thread principal" (yield to the main thread) après l'exécution du code le plus important, donnant au navigateur un moment pour effectuer la mise à jour de la mise en page. Voici un exemple de la façon de diviser les tâches en cédant au thread principal :

async function yieldToMain() {
  if ('scheduler' in window && 'yield' in window.scheduler) {
    return await window.scheduler.yield();
  }
  return new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
}

async function handleClick() {
  // Effectuez les mises à jour de mise en page les plus importantes ici
  await yieldToMain();
  // Effectuez les autres tâches qui doivent s'exécuter dès que possible après la mise à jour de la mise en page
}

Planification fine avec scheduler.postTask()

La fonction scheduler.postTask() offre une planification plus fine des tâches en définissant des priorités, ce qui aide le navigateur à prioriser le travail afin que les tâches de faible priorité cèdent la place au thread principal. Consultez le tableau de compatibilité des navigateurs avant d'utiliser cette API en production.

La fonction postTask() accepte trois paramètres de priorité : "background" pour les tâches de priorité la plus faible, "user-visible" pour les tâches de priorité moyenne, et "user-blocking" pour les tâches critiques nécessitant une priorité élevée.

En attribuant la bonne priorité à chaque élément de travail à l'intérieur de votre gestionnaire d'événements, vous pouvez vous assurer que le navigateur gère les interactions des utilisateurs de manière réactive tout en accomplissant toutes les tâches nécessaires :

// Planifier le travail critique de l'interface utilisateur en priorité élevée
scheduler.postTask(() => {
  updateCartBadge();
  showConfirmation();
}, { priority: 'user-blocking' });

// Planifier la synchronisation des données en priorité moyenne
scheduler.postTask(() => {
  syncCartWithServer();
}, { priority: 'user-visible' });

// Planifier l'analyse (analytics) en priorité faible
scheduler.postTask(() => {
  gtag('event', 'add_to_cart', { item: productId });
  fbq('track', 'AddToCart');
}, { priority: 'background' });

Implications pratiques

Voici comment aborder l'optimisation du temps de traitement sur WordPress et React/Next.js.

WordPress

WordPress offre un contrôle limité en ce qui concerne les scripts tiers. De nombreux scripts sont ajoutés via des plugins. La plupart du temps, ces scripts ajouteront des écouteurs d'événements (event listeners) à la page qui ne feront rien d'autre que retarder l'Interaction to Next Paint (INP). Si votre site WordPress rencontre des problèmes d'INP causés par un temps de traitement long, suivez ces étapes :

  • Vérifiez les paramètres du thème. Décochez toutes les options inutiles telles que le "défilement fluide (smooth scroll)" ou le "menu animé". Les paramètres de ce type ont tendance à causer des problèmes d'INP.
  • Vérifiez quels scripts sont responsables du long temps de traitement (conseil : utilisez le panneau de performances de Chrome). Si ces scripts sont liés à un plugin, envisagez de trouver un autre plugin qui fait à peu près la même chose avec moins de JavaScript.
  • Souvent, il y a des scripts personnalisés qui s'exécutent sur la page. Vérifiez ces scripts et assurez-vous qu'ils cèdent souvent la place au thread principal et enveloppent les rappels moins importants dans une fonction requestIdleCallback.
  • Déchargez les scripts inutilisés page par page (conseil : utilisez wp_deregister_script). Certains plugins ont tendance à injecter des scripts sur chaque page, même lorsque la fonctionnalité n'est pas nécessaire.
  • Vérifiez votre Tag Manager et supprimez les balises inutilisées ou non nécessaires.
  • Utilisez des thèmes légers et propres. Les thèmes polyvalents qui "font tout" ont tendance à avoir plus de scripts et des gestionnaires d'événements plus lourds.
  • Évitez les constructeurs de pages (page builders) car ils s'appuient souvent fortement sur JavaScript pour présenter les pages à l'utilisateur final.

React / Next.js

Les hooks et les fonctionnalités de concurrence de React permettent de réduire considérablement le temps de traitement de l'INP. Voici les principales techniques :

Prioriser l'interaction de l'utilisateur avec les fonctionnalités de concurrence de React :

React 18 a introduit des fonctionnalités de concurrence qui optimisent le rendu pour une expérience utilisateur plus fluide, en particulier lors de la saisie.

  • useTransition et startTransition : marquent les mises à jour non critiques pour un rendu ultérieur. Cela empêche les mises à jour importantes de bloquer l'interaction de l'utilisateur. Par exemple, enveloppez la mise à jour des résultats de recherche dans un startTransition pour que la saisie dans le champ de recherche reste réactive.
  • useDeferredValue : divisez votre interface utilisateur en sections essentielles et moins critiques. React peut interrompre le rendu des parties moins critiques pour une expérience plus réactive. C'est idéal pour rendre des listes filtrées ou des résultats de recherche.
  • useOptimistic (React 19+) : affichez un état temporaire et optimiste pendant que des opérations asynchrones (comme des requêtes réseau) sont en cours. Cela permet de garder l'interface utilisateur réactive même pendant la récupération de données.

Suspense pour la récupération de données (React 18+)

Suspense dans React 18 peut être utilisé pour améliorer l'INP en permettant au navigateur de prioriser les interactions des utilisateurs et d'optimiser le rendu. Bien que React 16 ait introduit Suspense pour le fractionnement du code, React 18 étend cette fonctionnalité pour englober la récupération de données.

  • Un composant de repli (fallback), comme un indicateur de chargement, s'affiche pendant le chargement des données.
  • Une fois les données arrivées, React reprend le rendu du composant suspendu.
  • Suspense, combiné au rendu interruptible (interruptible rendering) dans Concurrent React, priorise les interactions des utilisateurs. Si un utilisateur interagit avec un composant suspendu, React priorise le rendu de ce composant, maintenant ainsi la réactivité.

Ces fonctionnalités aident React à donner la priorité aux interactions des utilisateurs par rapport au travail de rendu en arrière-plan.

Explorez les autres phases de l'INP

Le temps de traitement n'est qu'une partie de l'Interaction to Next Paint. Pour optimiser pleinement vos scores INP, vous devez également vous pencher sur les deux autres phases :

Pour un flux de travail de diagnostic complet, consultez notre guide sur la façon de trouver et résoudre les problèmes d'INP, et retournez à la page principale de l'INP pour une vue d'ensemble complète.

Performance degrades unless you guard it.

I do not just fix the metrics. I set up the monitoring, the budgets, and the processes so your team keeps them green after I leave.

Start the Engagement
Temps de traitement de l'INP : causes, optimisation et exemples de codeCore Web Vitals Temps de traitement de l'INP : causes, optimisation et exemples de code