Gestionnaire d'événement lourd : pourquoi un clic prend 500 ms et comment le corriger
Ce qui se passe
Quand un utilisateur clique, le navigateur exécute votre gestionnaire d'événement jusqu'au bout avant de pouvoir peindre le frame suivant. Si le gestionnaire effectue des centaines de millisecondes de travail synchrone — filtrer un grand tableau, construire du DOM, parser du JSON — la page est figée exactement ce temps-là. L'utilisateur ne voit rien tant que le gestionnaire n'a pas rendu la main.
C'est le problème d'INP le plus courant ; il apparaît dans la décomposition de l'INP comme une longue phase de processing time.
Comment le reconnaître
- Le processing time domine la décomposition de l'INP (input delay et presentation delay sont faibles).
- Dans DevTools Performance, une tâche longue démarre pile au moment de l'événement et est attribuée à votre fonction gestionnaire.
- La lenteur croît avec la taille des données : plus il y a de lignes/éléments, plus le clic semble lent.
Comment corriger
- Mettez d'abord à jour l'UI (état pressé, spinner), puis rendez la main au navigateur avec scheduler.yield() (ou setTimeout(0) en repli) avant de faire le travail lourd.
- Découpez les grandes boucles en morceaux, en rendant la main entre les morceaux pour que le navigateur puisse peindre.
- Déplacez le calcul pur (parsing, filtrage, diffing) dans un Web Worker — le thread principal n'envoie que l'entrée et reçoit le résultat.
Problème
button.addEventListener("click", () => {
const results = filterRows(allRows) // 400 ms of sync work
renderTable(results) // user saw nothing until now
})
Correctif
button.addEventListener("click", async () => {
button.classList.add("loading") // instant feedback, painted first
await scheduler.yield() // let the browser paint
const results = filterRows(allRows)
renderTable(results)
button.classList.remove("loading")
})
Analysez votre site gratuitement →