INP : réactivité, tâches longues et fil principal

Se connecter pour s'inscrire

Votre progression

Continuez pour débloquer la suite !
0 / 0 étapes complétées 0
%

Syllabus

  1. Description

  2. Objectifs

  3. Validations de compétences

  4. Public cible

    Aucun public cible spécifié pour ce module.

  5. Besoins techniques

  6. Prérequis

    • Aucun prérequis
  7. Niveau

  8. Historique du module

    Aucune action enregistrée

INP : la réactivité, du clic à l'image suivante

  1. Ce que INP mesure, et ce qu'il ne mesure pas

    INP évalue la réactivité globale d'une page en observant le délai de toutes les interactions qualifiantes sur la durée de la visite. La valeur finale est l'interaction la plus longue observée, hors valeurs aberrantes.

    Pourquoi « la plus longue » et pas la moyenne

    Parce que l'utilisateur ne se souvient pas de la moyenne. Il se souvient du clic qui n'a rien fait pendant une demi-seconde. INP retient donc le pire moment vécu — ce qui en fait une métrique de ressenti plutôt qu'une métrique de performance moyenne.

    Ce qui est qualifié d'interaction

    Clic, contact, touche, pointeur — les actions /volontaires de l'utilisateur qui déclenchent une réponse de la page. Les défilements, les survols et les chargements ne sont pas comptés. Une animation automatique non plus.

    La limite structurelle : le fil principal

    Le navigateur traite une tâche à la fois sur un fil principal. Toute interaction doit attendre que la tâche en cours se termine. Ce n'est pas perceptible en dessous d'un certain délai — l'utilisateur ne voit pas la file d'attente, il perçoit l'attente.

    Un détail important et souvent oublié : chaque iframe a son propre fil principal. INP est rapporté au niveau de la page, interactions dans les iframes comprises. Une publicité lente dans un cadre intégré dégrade la métrique de la page qui l'héberge. Il faut donc identifier dans quel cadre l'interaction a eu lieu avant d'aller chercher le fil principal responsable.

  2. Les trois temps d’une interaction

    Une interaction se décompose en trois temps, et chacun se corrige autrement. C'est la décomposition qui rend l'optimisation ciblée au lieu d'approximative.

    1. Le délai d'entrée

    Entre le geste de l'utilisateur et le moment où son gestionnaire d'événement commence à s'exécuter. C'est le temps d'attente, et il ne dépend pas du code du gestionnaire : il dépend de ce qui occupe le fil principal avant. Scripts qui se chargent et se compilent, traitements réseau, minuteries, interactions qui se chevauchent.

    Pendant le chargement d'une page, c'est la cause dominante : le navigateur analyse et compile chaque script récupéré avant de pouvoir l'exécuter, et ces tâches longues retardent la réponse à toute interaction.

    2. Le traitement

    Le temps pendant lequel le gestionnaire s'exécute. Le conseil de la documentation est sans finesse : faire le moins de travail possible dans un gestionnaire d'événement. Si la logique est complexe, ce n'est pas qu'il faut l'optimiser sur place, c'est qu'il faut la découper.

    3. Le temps d'affichage suivant

    Entre la fin du traitement et le prochain affichage. Il dépend du travail de rendu : mise en page, peinture, composition. C'est là que se paie le DOM volumineux — chaque élément supplémentaire rend le travail de rendu plus coûteux, à l'affichage initial comme après chaque interaction.

    Le Layout Thrashing, à connaître par son nom

    Un motif classique : mettre à jour un style, puis lire immédiatement une valeur de style en JavaScript. Le navigateur est forcé de faire un rendu synchrone qu'il aurait pu différer. Dans une boucle, ce motif transforme un rendu en un rendu par itération, et c'est l'une des causes principales d'INP élevé sans JavaScript visible.

    Le remède est structurel : séparer les lectures et les écritures — lire toutes les valeurs, puis écrire tous les styles.

  3. Tâches longues : la limite des 50 ms et comment rendre la main

    Une tâche est un morceau de travail que le navigateur traite d'un bloc : rendu, mise en page, analyse, compilation, exécution de script. Toute tâche de plus de 50 ms est une tâche longue, et son temps au-delà de 50 ms est ce que l'utilisateur perçoit comme un blocage.

    Pourquoi 50 ms

    C'est le seuil au-delà duquel l'attente devient perceptible. En dessous, l'utilisateur ne remarque rien ; au-dessus, l'interface semble figée. La limite est donc physiologique, pas technique — et c'est pourquoi le découpage fonctionne : ce n'est pas une réduction du travail total, c'est de la répartition.

    Rendre la main : l'API Scheduler

    La technique de base consiste à céder le fil principal au milieu d'une tâche : le navigateur peut alors traiter le rendu et les interactions en attente avant que le travail reprenne.

    • setTimeout(fn, 0) — simple, mais la continuation n'est pas priorisée : elle passe en fin de file d'attente.
    • scheduler.yield() — l'API conçue pour cela. Elle rend la main et garantit que la suite de la fonction sera replacée en priorité. C'est la différence qui compte quand la page est chargée.
    • scheduler.postTask() — planification par priorités explicites, pour les travaux à faible ou haute priorité.

    scheduler.yield() n'est pas encore disponible partout : un repli sur setTimeout enveloppé dans une promesse est nécessaire, et perd justement la priorisation. Un polyfill qui retombe sur les autres fonctions de planification est la solution robuste.

    Un piège d'usage : céder par lots, pas à chaque ligne

    Rendre la main systématiquement coûte : chaque cession a un surcoût, et si les travaux sont très courts, on passe plus de temps à céder et reprendre qu'à exécuter. La pratique recommandée est de céder par lots, environ toutes les 50 ms, pas à chaque opération. Le module cite la recommandation telle quelle, car elle est contre-intuitive : l'instinct est de céder dès qu'on peut.

    La recommandation retirée : isInputPending()

    La documentation ne recommande plus isInputPending(), qui consiste à ne céder que si une entrée est en attente. Trois raisons données : il peut renvoyer false à tort malgré une interaction réelle ; l'entrée n'est pas le seul cas où il faut céder, les animations et mises à jour régulières de l'interface comptent aussi ; et des API plus complètes existent désormais.

    Un cours qui cite cette recommandation transmet une consigne abandonnée. C'est le genre d'erreur qui survit des années parce qu'elle est vraie à sa date de publication.

  4. Les corrections qui rapportent le plus

    1. Réduire le JavaScript

    La cause racine la plus fréquente d'INP élevé : trop de JavaScript à analyser, compiler et exécuter. Chaque script récupéré est trois fois coûteux — transféré, analysé, compilé — et seul le transfert est visible dans le panneau réseau. Le poids total du JavaScript est le meilleur prédicteur de l'INP, davantage que la complexité logique.

    2. Découper les tâches longues

    Le gain immédiat : rendre la main permet au navigateur de traiter une interaction en attente au milieu d'un traitement de fond. La page ne fait pas moins de travail, elle devient réactive.

    3. Différer ce qui n'est pas nécessaire

    Une grande partie du JavaScript d'une page ne sert pas à l'affichage initial. Le différer — jusqu'au premier défilement, à une interaction, à l'inactivité — réduit à la fois le LCP et le délai d'entrée. Attention à ne pas décaler ce qui est nécessaire, sous peine de créer un défaut de contenu au moment où l'utilisateur en a besoin.

    4. Alléger le DOM

    Deux cas où le volume du DOM se paie : au premier rendu, et après chaque interaction. La propriété CSS content-visibility permet de rendre paresseusement les éléments qui approchent de la fenêtre d'affichage. Elle demande de la pratique, et le module le signale comme un piste plutôt que comme une correction automatique.

    Point de vigilance pour les applications à page unique : même sans changement d'URL, elles rendent du HTML via JavaScript à chaque interaction. C'est acceptable tant que le volume rendu reste raisonnable ; au-delà, c'est la cause principale du temps d'affichage suivant.

    5. Travailler sur le fil principal qui bloque

    Avant toute correction, identifier le cadre dans lequel l'interaction a eu lieu. Sur une page qui embarque une carte, une publicité ou un lecteur vidéo tiers, la réponse est souvent : le fil principal du tiers. Et ce qu'on peut faire est alors borné — ce qui est une bonne raison de le savoir avant d'investir.

    La nature de ce travail : itératif

    La documentation est honnête : corriger une interaction lente en fera souvent apparaître une autre, surtout sur un site très interactif. La persistance est la technique — le résultat vient d'une série de corrections mesurées, pas d'un réglage unique.

Exercices, examens et projets

Exercice

Audit performance d'un site réel

Relever les trois métriques, identifier la sous-partie défaillante et établir un plan de correction mesuré.

Obligatoire Consulter
Projet

Optimisation Core Web Vitals

Amener un groupe d'URL dans le seuil sur la métrique défaillante, avec journal de mesures avant/après.

Livrables :

  • Relevé initial des trois métriques, par groupe d'URL et par appareil
  • Décomposition de la métrique en échec
  • Journal des corrections avec mesure après chacune
Obligatoire Consulter