Браузер и фронтенд-рантайм
Воркеры: собери отзывчивый конвейер выноса работы
Читать про воркеры — не то же самое, что держать страницу на 60 fps, пока она перемалывает реальную работу. Собери небольшое приложение, которое выносит тяжёлую задачу в пул воркеров, перемещает данные без clone-налога и кэширует свой shell за service worker, из которого реально можно восстановиться — доказывая каждое утверждение измерениями, а не словами.
Преврати ментальную модель юнита в работающий конвейер: вынеси тяжёлые вычисления с главного потока, передай данные через transfer вместо клонирования, ограничь работу пулом и backpressure и добавь service worker для мгновенных повторных загрузок, который можно откатить, когда он ломается — всё с проверкой числами до/после.
Собери браузерное приложение с одной действительно тяжёлой операцией (фильтр изображения, парсинг-и-агрегация крупного CSV/JSON или хэширование), которое держит 60 fps при повторных запусках, перемещает данные через границу воркера без structured-clone-налога и отдаёт свой shell из восстанавливаемого service worker — доказывая отзывчивость и экономию transfer измерениями.
- Таблица до/после: длительность длинной задачи главного потока, число сброшенных кадров во время операции и время блокировки postMessage на стороне отправителя — измеренные под одним и тем же запуском, по значению против transfer, главный поток против пула воркеров.
- Трейс DevTools Performance при устойчивой нагрузке, показывающий, что главный поток делает только UI-работу (нет длинных задач от тяжёлой операции), а поток воркера несёт вычисления.
- Под быстрым всплеском запусков число активных воркеров и память вкладки остаются ограниченными — backpressure видимо отклоняет или дропает лишнюю работу, а не спавнит воркеры безгранично.
- Повторный визит загружает shell мгновенно из кэша, и показано, как kill switch снимает сломанный service worker с клиента без ручной очистки данных сайта.
- Абзац-разбор: какой транспорт использован для нагрузки (clone, transfer или SAB) и почему, и почему боттлнек вообще выносился.
- Рендери результат через OffscreenCanvas: передай canvas воркеру рендера через transfer и рисуй вывод (2D или WebGL) вне главного потока; подтверди в трейсе, что главный поток показывает нулевую работу рендеринга для него.
- Добавь многопоточный WASM-кодек или хэшер за кросс-доменной изоляцией: выкати COOP: same-origin + COEP: require-corp (с аудитом через report-only сначала), подтверди, что self.crossOriginIsolated равно true, и используй SharedArrayBuffer с Atomics для координации producer/consumer между потоками.
- Оберни пул воркеров в Comlink и покажи, что грубый batch-API бьёт болтливый поэлементный API в тесном цикле — измерь стоимость task-hop каждого.
- Добавь on-call runbook: как читать телеметрию воркеров, обнаружить утёкший воркер (DevTools Performance → Threads), распознать version skew и дёрнуть kill switch.
Это цикл, который ты будешь гонять на каждой реальной проблеме с воркерами: убедись, что боттлнек — это выносимое вычисление (а не мутация DOM), перенеси его в пул воркеров, передай данные через transfer вместо клонирования, ограничь работу backpressure и закэшируй shell за service worker, который можно восстановить kill switch’ем — проверяя каждый шаг трейсами и числами до/после под одинаковой нагрузкой. Сделав это раз на небольшом приложении, ты доводишь production-версию до мышечной памяти.