Браузер и фронтенд-рантайм
Event loop: вытащи взаимодействие из INP-ада
Читать про long task — не то же, что вытащить взаимодействие из него. Собери страницу с намеренно дёргающимся взаимодействием, измерь его INP под реалистичным троттлингом, диагностируй виновный кадр через LoAF и применяй дисциплину yield из юнита, пока ввод не станет отвечать за один кадр — с доказательством на каждом шаге.
Преврати модель тайминга юнита в воспроизводимый инженерный цикл: воспроизведи long task, атрибутируй его из телеметрии, поделить под планку 50 мс реальным task-уровневым yield, защити выигрыш CI-гейтом и проверь числами INP до/после.
Возьми взаимодействие, блокирующее main thread (своё приложение или стартер ниже), и снизь его INP до уровня под 200 мс p75 на троттленном железе — не удаляя фичу — доказывая каждый шаг измерениями, а не оценками.
- Таблица до/после: INP p75, самый долгий task на main thread (мс) и число пропущенных кадров во время фиксированной последовательности набора — всё измерено при троттлинге CPU 4x, не оценено.
- Ни один task на main thread не превышает 50 мс в трассе после; поток LoAF больше не репортит медленный кадр для взаимодействия.
- INP p75 держится под 200 мс для взаимодействия на устойчивой скорости набора.
- Абзац-описание с указанием, какой yield-примитив ты использовал и почему microtask-yield (await Promise.resolve()) не сработал бы, со ссылкой на твою трассу.
- Добавь INP CI-гейт: Playwright-тест в headless Chrome с --cpu-throttling-rate=4, проигрывающий последовательность набора, измеряющий INP тем же кодом PerformanceObserver и валящий сборку, если p75 пересекает бюджет. Покажи, что он ловит регрессию, которую ты намеренно вернул.
- Добавь guard от starvation: напиши классическую заморозку Promise.resolve().then(self), наблюдай ноль отрисованных кадров и INP свыше 1 с в трассе, затем разорви цикл одним task-уровневым yield и покажи восстановление страницы.
- Перенеси тот же тяжёлый обработчик на Node HTTP-эндпоинт, измерь event-loop lag через perf_hooks.monitorEventLoopDelay() под нагрузкой и покажи, что фикс с Worker-потоком снижает p99 lag так же, как браузерный фикс снизил INP.
- Прогони LoAF sourceCharPosition через реальный sourcemap (библиотека source-map или резолвер уровня Sentry), чтобы телеметрия репортила исходную file:line, а не позицию в бандле.
Это цикл, который ты будешь прогонять в каждом реальном инциденте INP: воспроизведи long task под троттлингом, атрибутируй медленный кадр через LoAF плюс sourcemap, поделить работу под планку 50 мс настоящим task-уровневым yield (никогда microtask), вынеси CPU-bound работу на Worker, когда деления мало, и проверь числами INP до/после при идентичной нагрузке. Закрой это в CI тем же троттлингом, чтобы выигрыш не откатился тихо. Сделав это однажды на игрушечной странице, ты превращаешь production-версию в мышечную память.