Fonctionnement du thread principal

Le thread principal regroupe toutes les opérations visibles depuis le code JavaScript : exécution du script, gestion des événements, callbacks réseau et logique du framework. Il assure également la première moitié du pipeline de rendu, à savoir le calcul des styles, le layout (reflow) et le paint. Ces étapes ne sont exécutées que lorsqu’une modification du DOM ou des styles l’exige ; sinon elles sont sautées. Le compositing final, qui assemble les calques, est délégué au thread de composition.

Contraintes de temps et métriques de performance

Sur un écran 60 Hz, chaque image doit être produite en 16,6 ms. Après déduction du temps consommé par le navigateur lui‑même, le budget exploitable est généralement estimé à 10 ms par frame. Un même thread qui exécute une fonction JavaScript pendant 200 ms empêche toute mise à jour d’affichage ou réception d’interaction pendant cette période, ce qui dépasse largement le budget et provoque un gel perceptible. Les tâches dépassant 50 ms sont qualifiées de « long tasks ». Les indicateurs INP (Interaction to Next Paint) et TBT (Total Blocking Time) quantifient respectivement le délai de réponse après une interaction et le cumul du temps bloqué pendant le chargement, reflétant directement la charge du thread principal.

Techniques d’optimisation du thread principal

Deux familles d’approches permettent de réduire l’impact du thread principal. La première reste sur le même thread mais restructure le travail : splitting (fractionner les tâches longues en sous‑tâches), batching (regrouper les opérations fréquentes), prioritizing (ordonnancer les tâches selon leur importance) et deferring (reporter les travaux non urgents). Le fractionnement crée des points d’interruption où le navigateur récupère le contrôle, ce qui autorise le rafraîchissement de l’écran et le traitement des entrées utilisateur. Le batching minimise le nombre d’appels au pipeline de rendu en traitant plusieurs changements en une seule passe. La priorisation utilise des APIs comme requestIdleCallback ou les priorités de scheduler pour placer les tâches critiques en tête de file. Le report se réalise via setTimeout ou requestAnimationFrame afin de différer les calculs qui ne modifient pas immédiatement le rendu.

La seconde famille délègue le travail hors du thread principal, par exemple en employant les Web Workers pour les calculs intensifs ou en externalisant le rendu via le compositor thread grâce aux animations CSS. Dans le scénario d’un chat en direct où des centaines de messages arrivent en rafale, le rendu synchronisé de chaque message entraînerait plusieurs cycles de style‑layout‑paint consécutifs, bloquant l’entrée utilisateur. En découpant le flux en lots de quelques messages et en insérant des pauses via await ou requestAnimationFrame, le navigateur peut intercaler des rafraîchissements, conservant ainsi une expérience fluide même sur des écrans 120 Hz où le budget par frame chute à 8,3 ms.