Важкий обробник події: чому клік займає 500 мс і як це виправити
Що відбувається
Коли користувач клікає, браузер виконує обробник події до кінця, перш ніж зможе відмалювати наступний кадр. Якщо обробник робить сотні мілісекунд синхронної роботи — фільтрує великий масив, будує DOM, парсить JSON — сторінка заморожена рівно на цей час. Користувач не бачить жодної реакції, поки обробник не повернеться.
Це найчастіша проблема INP; у розбивці INP вона видно як довга фаза processing time.
Як розпізнати
- Processing time домінує в розбивці INP (input delay і presentation delay малі).
- У DevTools Performance одна довга задача починається прямо на події й атрибутується вашій функції-обробнику.
- Гальмування зростає з обсягом даних: що більше рядків/елементів, то гірше відчувається клік.
Як виправити
- Спершу оновіть UI (натиснутий стан, спінер), потім віддайте керування браузеру через scheduler.yield() (або setTimeout(0) як запасний варіант) — і лише потім робіть важку роботу.
- Розбийте великі цикли на частини, віддаючи керування між частинами, щоб браузер встиг відмалювати кадр.
- Винесіть чисті обчислення (парсинг, фільтрацію, діфи) у Web Worker — головний потік лише надсилає вхід і отримує результат.
Проблема
button.addEventListener("click", () => {
const results = filterRows(allRows) // 400 ms of sync work
renderTable(results) // user saw nothing until now
})
Виправлення
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")
})
Просканувати свій сайт безкоштовно →