Web Worker и Service Worker в браузере: что это и зачем
Понятно объясняем, что такое Web Worker и Service Worker: чем они отличаются, как работают, когда нужны, и примеры типичных сценариев в веб‑приложениях.

Введение: два «воркера», две разные задачи
Когда веб‑приложение начинает «тормозить», у проблемы часто две причины.
-
CPU: тяжёлые вычисления (обработка больших массивов, шифрование, генерация отчётов) блокируют главный поток, и интерфейс перестаёт отвечать.
-
Сеть: запросы, кэш и офлайн‑поведение работают непредсказуемо — из‑за этого страница грузится медленно или вовсе не открывается без интернета.
В браузере для этих случаев есть два разных инструмента с похожими названиями — и их легко перепутать.
Коротко о разнице
Web Worker — способ вынести вычисления из основного потока JavaScript. Он помогает сохранить плавность UI, когда нужно много считать, парсить, преобразовывать или фильтровать данные.
Service Worker — «прокси» между страницей и сетью. Он перехватывает запросы (через Fetch API), управляет кэшем, включает офлайн‑режим, ускоряет повторные загрузки и поддерживает возможности PWA вроде push‑уведомлений.
Важно: оба воркера работают не «вместо» вашего приложения, а рядом с ним — и каждый решает свою задачу.
Что нужно знать, чтобы читать дальше
Достаточно базовых навыков:
- JavaScript на уровне функций, промисов/async‑await;
- понимание, что такое DOM и почему долгие задачи «замораживают» интерфейс;
- основы HTTP: запрос/ответ, кэширование, статус‑коды.
Что будет в статье
Разберём, как устроено выполнение JavaScript в браузере, что умеют Web Worker и Service Worker, какие у них ограничения, и в каких сценариях они действительно дают выигрыш по performance фронтенда. В конце — короткие примеры кода и чек‑лист выбора.
Как устроено выполнение JavaScript в браузере
Почему JavaScript обычно «однопоточный»
Когда вы открываете страницу, браузер создаёт для неё главный поток выполнения. В нём по очереди выполняются задачи: обработка кликов и скролла, запуск JavaScript‑кода, пересчёт стилей, раскладка элементов и отрисовка. Такой подход упрощает модель программирования: меньше гонок данных и неожиданных конфликтов, потому что в один момент времени выполняется одна «порция» JS.
Важно: «однопоточность» здесь — практическое правило для кода страницы. Внутри самого браузера много параллельных процессов и потоков (сеть, декодирование, композитинг), но ваш JS на странице обычно живёт в одном основном контексте.
Что такое главный поток: UI, события и рендеринг
Главный поток — это место, где решается всё, что пользователь видит и ощущает:
- обработчики событий (клик, ввод текста, touch);
- выполнение таймеров и колбэков;
- вычисление стилей и layout;
- рисование и компоновка кадров.
Браузер старается выдавать кадры регулярно (условно около 60 раз в секунду). Чтобы анимации и прокрутка были плавными, на подготовку одного кадра остаются миллисекунды. Если JS занимает главный поток слишком долго, браузер просто не успевает вовремя перерисовать интерфейс.
Как «тяжёлые» задачи вызывают лаги и jank
Под «тяжёлыми» задачами обычно понимают:
- большие циклы и сортировки;
- обработку больших массивов данных;
- сложные вычисления (например, криптография, обработка изображений);
- массовые операции с DOM.
Если такой код выполняется, скажем, 200–500 мс без пауз, пользователь увидит задержку: клики «не срабатывают», прокрутка рвётся, анимации дёргаются. Это и есть jank — визуальная «неровность», вызванная блокировкой главного потока.
Что реально даёт параллельность — и почему это не «настоящие потоки JS»
Параллельность в вебе обычно достигается не запуском второго «потока JavaScript» внутри той же страницы, а переносом части работы в отдельный контекст. Например, Web Worker выполняет код отдельно от главного потока и общается с ним сообщениями.
Это даёт практический эффект: тяжёлые вычисления не мешают UI. Но есть нюанс: воркер не делит со страницей память и DOM напрямую (чаще всего данные копируются или передаются как transferable). Поэтому это не «два потока, которые одновременно меняют одни и те же переменные», а два изолированных окружения с явным обменом данными.
Что такое Web Worker и какие виды существуют
Web Worker — способ выполнять JavaScript «в фоне», в отдельном потоке, не блокируя основной поток страницы. Если в основном потоке вы рисуете интерфейс, обрабатываете клики и анимации, то воркеру можно поручить тяжёлые вычисления: парсинг больших данных, фильтрацию, работу с криптографией, подготовку отчётов.
Важно: Web Worker не ускоряет JavaScript «магически» — он просто позволяет вынести часть работы из главного потока, чтобы интерфейс оставался отзывчивым.
Основные виды Web Worker
Dedicated Worker (выделенный) — самый популярный вариант. Привязан к конкретной вкладке/странице (контексту), которая его создала. Если страницу закрыть — воркер завершится.
Shared Worker (общий) — может быть разделяемым между несколькими вкладками/iframe одного происхождения (origin). Полезен, когда нужно единое «фоновое состояние» на несколько открытых страниц (например, общий канал обмена или единый расчётный процесс).
Worklet (упоминание) — близкая, но отдельная история: специальные мини‑воркеры для конкретных задач (например, AudioWorklet для аудио или PaintWorklet для кастомной отрисовки). Их чаще используют точечно и не как универсальную «фоновую машину».
Как запускается воркер
Воркер создают из основного кода так:
const worker = new Worker('/workers/calc-worker.js', { type: 'module' });
Ключевой момент: код воркера живёт в отдельном файле (или модуле). Это помогает браузеру изолировать выполнение и не давать воркеру прямого доступа к DOM.
Как воркер общается со страницей
Связь идёт сообщениями:
- со страницы в воркер:
worker.postMessage(data) - из воркера обратно:
postMessage(result) - получение сообщений: обработчик события
message
Модель похожа на «почтовый ящик»: вы отправляете данные и получаете ответ асинхронно, не блокируя UI.
Какие данные можно передавать
По умолчанию используется механизм structured clone — браузер копирует поддерживаемые структуры данных (объекты, массивы, строки, Map/Set, даты и т. п.).
Если данные большие, лучше использовать Transferable (например, ArrayBuffer): тогда владение буфером передаётся воркеру без копирования, что заметно ускоряет обмен.
Ограничение для ожиданий: функции и DOM‑элементы так передавать нельзя — воркер работает в отдельной среде и не имеет доступа к дереву страницы.
Ограничения и особенности Web Worker
Web Worker часто воспринимают как «второй поток для JavaScript», но у него есть важные ограничения. Это не недостатки, а осознанные правила безопасности и предсказуемости: воркер должен считать данные, не ломая интерфейс.
Нет доступа к DOM — и почему это важно
Воркеры не видят window, document, элементы страницы и не могут напрямую менять верстку. Любые результаты нужно возвращать в основной поток сообщениями (postMessage), а уже там обновлять интерфейс.
Ограничения по API
Доступный набор API отличается от основного потока. Обычно доступны таймеры, fetch, работа с бинарными данными, Web Crypto, иногда — WebSocket.
Зато часто недоступны или ограничены:
localStorageи другие синхронные хранилища (ориентируйтесь наIndexedDB);- синхронные блокирующие операции: в воркерах стараются избегать всего, что может «залипнуть» надолго;
- некоторые UI-ориентированные API (очевидно — ведь UI нет).
Практическое правило: если API «про интерфейс» или «про синхронные блокировки», скорее всего, в воркере его не будет.
CORS и правила загрузки скрипта воркера
Скрипт воркера загружается как отдельный ресурс и подчиняется правилам происхождения (origin). Если вы пытаетесь подключить воркер с другого домена, понадобятся корректные CORS‑заголовки. В сборках с модулями удобнее создавать воркер через URL относительно текущего файла — так меньше сюрпризов с путями.
Отладка и профилирование
Логи из воркера попадают в DevTools, но в отдельный контекст. Ищите разделы вроде Sources → Workers и запускайте профилирование в Performance, чтобы увидеть, где именно тратится время: в основном потоке или в воркере.
Типичные ошибки
Две самые частые проблемы:
- Гонки сообщений: ответы приходят не в том порядке, в котором вы ожидаете. Помогают
requestId, явные состояния и протокол сообщений. - Большие копирования данных:
postMessageкопирует объекты (structured clone), и большие массивы могут стать узким местом. Для бинарных данных используйте Transferable (например,ArrayBuffer), чтобы передавать владение без копии.
Когда использовать Web Worker: практические сценарии
Web Worker стоит подключать там, где код реально нагружает CPU и из‑за этого «заикается» интерфейс: прокрутка, ввод, анимации, клики. Воркеры помогают вынести вычисления в отдельный поток и вернуть отзывчивость странице — особенно заметно на слабых устройствах.
Тяжёлые вычисления, которые блокируют UI
Типичные кандидаты:
- большие сортировки и агрегации данных (например, таблицы на десятки тысяч строк);
- компрессия/декомпрессия, работа с архивами;
- криптография: хеширование, подписи, шифрование (где это уместно и безопасно);
- любые длительные циклы и сложные алгоритмы, которые занимают сотни миллисекунд и больше.
Если вы видите в профилировщике длинные Long task на основном потоке — это почти прямой сигнал попробовать Web Worker.
Парсинг больших JSON/CSV без подвисаний
Частый сценарий — импорт данных: пользователь загружает CSV/JSON, а страница на несколько секунд перестаёт реагировать. Парсинг, валидацию и предварительную обработку удобно делать в воркере, а в основной поток отправлять только результат (например, уже нормализованные записи или статистику).
Обработка медиа (когда возможно)
Декодирование, ресайз, фильтры и другие операции над изображениями/медиа тоже нередко упираются в CPU. В браузере это зависит от API: часть операций можно ускорить через воркеры, но иногда удобнее полагаться на встроенные механизмы (например, аппаратное декодирование) и не усложнять архитектуру.
Ускорение обмена данными: Transferable
Если вы передаёте большие бинарные массивы (аудио, данные для графиков, результаты вычислений), используйте Transferable‑объекты, например ArrayBuffer. В отличие от копирования, «передача владения» почти не тратит время и память, что напрямую влияет на performance фронтенда.
Когда воркер не нужен
Web Worker не ускорит задачу, которая:
- короткая (десятки миллисекунд) — накладные расходы на запуск и обмен сообщениями могут быть больше выгоды;
- упирается в сеть (ожидание ответа API) — здесь важнее кэширование, оптимизация запросов и, возможно, Service Worker;
- требует частого доступа к DOM (воркеры не работают с DOM напрямую).
Практичное правило: выносите в Web Worker всё, что «жжёт CPU» и мешает интерфейсу, а в основном потоке оставляйте то, что связано с отображением и быстрыми реакциями.
Что такое Service Worker и как он работает
Service Worker — специальный скрипт, который браузер запускает в фоне и использует как «прокси» между вашими страницами и сетью. Он не имеет доступа к DOM (не может напрямую менять HTML), зато умеет перехватывать сетевые запросы и выполнять фоновые задачи по событиям.
Роль «прокси» между страницей и сетью
Когда страница делает запрос (например, через fetch или загрузку ресурсов), Service Worker может получить событие и решить, что вернуть: ответ из сети, из кэша или сгенерировать ответ самостоятельно. Это не «ускоритель по умолчанию», а управляемый механизм: логику выбираете вы.
Жизненный цикл: register → install → activate
- register: страница регистрирует воркер (обычно один раз), и браузер скачивает файл Service Worker.
- install: воркер устанавливается. На этом шаге часто подготавливают базовую инфраструктуру (например, создают кэши).
- activate: воркер активируется и начинает контролировать страницы в своём диапазоне. На активации обычно делают «уборку» старых данных (например, устаревших кэшей).
Жизненный цикл сделан так, чтобы обновления происходили контролируемо: новый воркер устанавливается отдельно от активного и включается по правилам браузера.
События: fetch, push, sync
Service Worker реагирует на события. Самые известные:
- fetch — перехват запросов и формирование ответа.
- push — получение push‑сообщений (если включено и разрешено пользователем).
- sync — фоновая синхронизация, когда сеть снова доступна.
Поддержка отдельных возможностей может отличаться между браузерами и платформами.
Scope: какие URL контролируются
Service Worker действует только в пределах scope — набора URL, обычно это путь, где лежит файл воркера, и всё «ниже» по дереву. Поэтому размещение файла и параметры регистрации напрямую определяют, какие страницы и запросы он сможет контролировать.
Почему он работает независимо от вкладки
Service Worker не привязан к конкретной вкладке: его может запустить браузер «по событию» даже когда сайт не открыт на экране. Он живёт отдельной фоновой сущностью и просыпается, когда нужно обработать событие, после чего может быть выгружен для экономии ресурсов.
Зачем нужен Service Worker: кэш, офлайн и скорость
Service Worker полезен там, где хочется контролировать сеть: ускорять загрузку, переживать нестабильный интернет и точнее управлять обновлениями. По сути это «сетевой прокси» внутри браузера: он может перехватывать запросы (fetch) и решать, откуда отдать ресурс — из сети или из кэша.
Кэширование: Cache Storage и стратегии
В отличие от обычного HTTP‑кэша, Cache Storage управляется вашим кодом. Это позволяет выбрать стратегию под конкретный тип данных:
- Cache-first: сначала кэш, потом сеть. Подходит для статических файлов (CSS, шрифты, иконки).
- Network-first: сначала сеть, при ошибке — кэш. Хорошо для «живых» данных, где важна актуальность.
- Stale-while-revalidate: мгновенно отдаём кэш, параллельно обновляем его из сети. Часто лучший компромисс для интерфейса.
Важно: кэшировать можно не только ассеты, но и ответы API — если вы осознанно задаёте срок жизни и правила инвалидации.
Офлайн и «плохая сеть»
Service Worker позволяет:
- показывать офлайн‑страницу или «облегчённый» режим, когда сеть пропала;
- использовать кэш как запасной вариант при таймауте;
- сохранять базовую работоспособность (открытие приложения, навигация, история).
Но офлайн — это не магия: если данные не были заранее закэшированы или сохранены (например, в IndexedDB), показать их будет нечем.
Предзагрузка и обновление ресурсов
Можно заранее прогреть кэш при установке воркера (precache) и обновлять его при активации новой версии. Это ускоряет повторные визиты и уменьшает «дрожание» интерфейса при загрузке.
Фоновая синхронизация: идея и ограничения
Концепция background sync — отложить отправку действий пользователя до момента, когда сеть снова станет стабильной. На практике поддержка и поведение зависят от браузера и настроек энергосбережения, поэтому это скорее улучшение, а не гарантированный канал доставки.
Опасные места
Главные риски — устаревший кэш и неочевидные обновления. Пользователь может долго оставаться на старых файлах, если не продуманы версионирование и очистка. Хорошее правило: обновлять кэш предсказуемо, явно удалять старые записи и иметь понятную стратегию отката, если новая версия сломалась.
Безопасность и обновления Service Worker
Service Worker получает особые права: он может перехватывать сетевые запросы страницы и отвечать из кэша. Поэтому у него строгая модель безопасности и отдельный жизненный цикл обновлений — важно понимать оба аспекта, чтобы не получить «сломанный офлайн» или неожиданные баги.
Почему нужен HTTPS (кроме localhost)
Service Worker работает только на защищённом контексте: HTTPS обязателен, исключение — localhost для разработки.
Причина проста: если бы воркер мог регистрироваться по HTTP, злоумышленник в сети (Wi‑Fi в кафе, корпоративный прокси) смог бы подменить скрипт воркера и надолго закрепиться в браузере пользователя.
Риски неправильной конфигурации
Перехват через fetch даёт большую силу — и большой риск:
- можно случайно закэшировать персональные ответы (например,
/profile) и показать их не тому пользователю; - можно «закольцевать» стратегию кэша и получить вечные 404/500 из-за неправильной обработки исключений;
- можно сделать приложение уязвимым к XSS‑сценариям, если кешировать непроверенный HTML.
Хорошая практика: кэшировать только то, что действительно публично и версионируется (статику), а для API — аккуратные правила и явные исключения.
Обновления: waiting, skipWaiting, clients.claim
Когда вы публикуете новую версию, браузер скачивает новый Service Worker, но часто оставляет его в состоянии waiting, пока все вкладки со старой версией не будут закрыты.
skipWaiting()уместен, если исправление критичное и вы готовы к возможному «перезапуску» логики в активной вкладке.clients.claim()полезен, чтобы новый воркер сразу начал контролировать открытые страницы после активации.
Не включайте их «по умолчанию» без понимания UX: внезапная смена кэша посреди сессии может привести к несовместимости ресурсов.
Инвалидация кэша и версионирование
Используйте версионированные имена кэшей (например, app-cache-v3) и удаляйте старые в обработчике activate. Тогда обновления становятся предсказуемыми.
Диагностика в DevTools
Проверяйте состояние воркера и содержимое хранилищ в DevTools → Application → Service Workers / Cache Storage: там видно, кто активен, кто ждёт, какие кэши созданы и что именно лежит внутри.
Web Worker vs Service Worker: ключевые отличия
Оба «воркера» запускаются отдельно от основного потока страницы, но решают разные задачи.
Цель: вычисления vs контроль сети и офлайна
Web Worker нужен, чтобы вынести тяжёлые вычисления (парсинг, обработку данных, кодирование, поиск, криптографию) из UI‑потока и не «фризить» интерфейс.
Service Worker — прослойка между страницей и сетью. Он перехватывает запросы, управляет кэшем, включает офлайн‑режим, ускоряет повторные загрузки и обслуживает PWA‑сценарии.
Жизненный цикл и время жизни
Web Worker обычно живёт пока живёт страница (или пока вы его не остановите). Он привязан к конкретной вкладке.
Service Worker устанавливается и активируется для origin (сайта) и может переживать перезагрузки страниц. Он запускается «по событию» (fetch, push, sync) и может быстро завершаться, когда не нужен — поэтому в нём важно думать событиями, а не бесконечными циклами.
Доступ к API: DOM недоступен, но возможности разные
И Web Worker, и Service Worker не имеют прямого доступа к DOM.
При этом Web Worker ориентирован на вычисления и работу с данными (например, ArrayBuffer/TypedArray).
Service Worker работает с сетевыми и офлайн‑API: перехват запросов, Cache Storage, интеграция с push‑уведомлениями и фоновыми задачами (в зависимости от поддержки браузера). При этом он плохо подходит для длительных вычислений «в фоне»: для CPU‑задач логичнее Web Worker.
Коммуникация: как они общаются со страницей
Web Worker общается со страницей через postMessage и события message. Для обмена между несколькими вкладками/контекстами можно использовать BroadcastChannel.
Service Worker тоже может отправлять сообщения клиентам (страницам) и принимать их. BroadcastChannel помогает синхронизировать состояние между вкладками, когда нужно уведомить UI об обновлённом кэше или о смене версии.
Производительность: где выигрывают и где есть накладные расходы
Web Worker выигрывает, когда нагрузка — CPU, и цена «передачи данных» оправдана. Накладные расходы возникают из‑за сериализации сообщений; их снижают transferables (передача владения буфером).
Service Worker ускоряет повторные визиты и офлайн, но добавляет сложность: установка/активация, стратегия кэширования и риск «устаревшего» контента при неправильном обновлении.
Короткие примеры кода: с чего начать
Ниже — два минимальных «скелета», которые помогают быстро проверить идею: Web Worker для тяжёлых вычислений и Service Worker для кэша/офлайна. Примеры намеренно простые, чтобы их легко было адаптировать под любой стек.
Мини‑пример Web Worker: выносим тяжёлую функцию
Структура файлов:
- /main.js — код страницы
- /worker.js — код воркера
worker.js:
self.onmessage = (e) => {
const { n } = e.data;
// Условно «тяжёлая» функция
let sum = 0;
for (let i = 0; i < n; i++) sum += Math.sqrt(i);
self.postMessage({ sum });
};
main.js:
const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module' });
worker.onmessage = (e) => {
console.log('Готово:', e.data.sum);
};
worker.postMessage({ n: 5_000_000 });
// Когда воркер больше не нужен
// worker.terminate();
Обмен идёт через postMessage и события message. Если передаёте большие массивы, изучите transferable objects (можно передать буфер без копирования).
Мини‑пример Service Worker: перехват fetch и простое кэширование
Важно про расположение: файл sw.js обычно кладут ближе к корню сайта (например, /sw.js), чтобы его область действия покрывала нужные страницы.
main.js (регистрация):
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
sw.js (кэшируем статические запросы):
const CACHE = 'static-v1';
self.addEventListener('install', (event) => {
event.waitUntil(caches.open(CACHE));
});
self.addEventListener('fetch', (event) => {
const req = event.request;
event.respondWith(
caches.match(req).then((cached) => {
return (
cached ||
fetch(req).then((resp) => {
const copy = resp.clone();
caches.open(CACHE).then((c) => c.put(req, copy));
return resp;
})
);
})
);
});
Подсказки по сборке и структуре
Web Worker часто удобнее подключать через new URL('./worker.js', import.meta.url) — так сборщик сам обработает путь.
Service Worker почти всегда должен быть доступен по фиксированному URL (/sw.js), поэтому проверьте, что сборка копирует его в корень.
Что протестировать и как «сбросить» при отладке
Проверьте: офлайн‑режим (в DevTools), поведение при обновлении файлов, запросы к большим данным, и не кэшируются ли случайно API‑ответы, которые должны быть свежими.
Чтобы аккуратно отключить/сбросить Service Worker: DevTools → Application → Service Workers → Unregister и Clear storage. Либо в консоли:
navigator.serviceWorker.getRegistrations()
.then((regs) => regs.forEach((r) => r.unregister()));
Web Worker сбрасывается проще: вызывайте worker.terminate() и пересоздавайте экземпляр.
Как выбрать подход: чек‑лист для проекта
Иногда выбор простой: вы либо разгружаете интерфейс, либо ускоряете сеть и делаете офлайн. Но в реальных приложениях часто нужны оба подхода — важно понять, где именно узкое место.
Быстрый выбор по задаче
Если главный вопрос звучит как «почему страница зависает, пока мы считаем/парсим/сжимаем данные?» — выносите работу из UI‑потока.
- Нужно вынести тяжёлую задачу из UI‑потока (вычисления, обработка больших массивов, парсинг, кодирование) → Web Worker.
- Нужно управлять сетью, офлайном и кэшем (перехват запросов, ускорение повторных загрузок, fallback‑страницы) → Service Worker.
Можно ли комбинировать
Да, и это частая схема:
- Service Worker отвечает за кэш и офлайн: отдаёт уже сохранённые ответы, обновляет их в фоне, снижает зависимость от сети.
- Web Worker обрабатывает данные: например, после получения JSON (из сети или кэша) считает статистику, строит индекс для поиска, подготавливает данные для графиков.
Вместе это даёт заметный эффект: быстрее загрузка и меньше «фризов» при работе.
Чек‑лист перед внедрением
- Поддержка браузеров и окружений. Нужны ли вам старые версии, встроенные браузеры, режимы инкогнито? Уточните ограничения для SW/WW в вашей аудитории.
- Отладка и наблюдаемость. Помимо DevTools, команде пригодятся логирование и метрики: время ответа, cache hit rate, время выполнения в worker.
- Стратегия обновлений (особенно для Service Worker). Продумайте, как пользователи получат новую версию: когда активируется новый SW, как сообщить о перезагрузке, что делать при несовместимости кэша.
- Объём и стоимость передачи данных. Между страницей и Web Worker данные копируются/передаются: оцените размер payload, используйте Transferable там, где это уместно.
- Риски и безопасность. Service Worker требует HTTPS и аккуратных правил кэширования, чтобы не закэшировать «лишнее» и не сломать авторизацию.
Как это применять на практике при разработке продукта
Если вы собираете приложение с PWA‑поведением (кэш, офлайн, быстрые повторные загрузки) и при этом у вас есть тяжёлая обработка данных на клиенте (например, импорт CSV, предобработка аналитики, подготовка данных для графиков), часто выгодно заложить оба инструмента сразу: Service Worker как управляемый слой сети и Web Worker как слой CPU‑задач.
В TakProsto.AI такие решения удобно продумывать «сверху вниз»: в режиме планирования (planning mode) заранее разделяете, какие операции должны жить в UI, какие — в Web Worker, а какие запросы и ресурсы имеет смысл отдавать через стратегии кэширования Service Worker. Поскольку TakProsto — vibe‑coding платформа для быстрого создания веб‑приложений (React на фронтенде, Go + PostgreSQL на бэкенде), подход с воркерами помогает сразу держать в фокусе performance и офлайн‑UX, не усложняя основной код интерфейса. А если захотите зафиксировать удачную архитектуру, пригодятся снапшоты и откат (rollback), чтобы безопасно экспериментировать со стратегиями кэша и обновлениями.
Идеи для продолжения
Если хотите углубиться, следующие темы обычно дают максимум практической пользы: PWA, стратегии кэширования (Cache First / Network First / Stale‑While‑Revalidate), оптимизация передачи данных между потоками, хранение в IndexedDB, а также push‑уведомления (когда они действительно оправданы).
FAQ
В чём главное отличие Web Worker и Service Worker?
Web Worker выносит CPU‑тяжёлые вычисления из главного потока, чтобы не «фризить» UI.
Service Worker перехватывает сетевые запросы и управляет кэшем/офлайном (и PWA‑возможностями вроде push).
Если «лагает интерфейс из‑за вычислений» — обычно нужен Web Worker. Если «медленно грузится/не работает без сети» — Service Worker.
Когда Web Worker реально улучшит производительность?
Используйте Web Worker, когда видите длинные задачи (Long task) на основном потоке и из‑за этого:
- рвётся прокрутка/анимации;
- задерживаются клики и ввод;
- подвисает импорт/обработка больших данных.
Типичные задачи: сортировки и агрегации больших массивов, парсинг JSON/CSV, криптография, компрессия, расчёты для графиков.
Когда Web Worker не поможет (и лучше думать про Service Worker)?
Когда узкое место — не CPU, а ожидание сети:
- запросы к API «долго едут», а JS при этом почти не загружен;
- нужно ускорить повторные визиты за счёт кэша;
- требуется офлайн‑fallback.
В таких случаях выигрывает Service Worker (стратегии кэширования, контроль fetch), а Web Worker почти ничего не даст.
Можно ли из Web Worker менять DOM или работать с window/document?
Нет: воркеры не имеют прямого доступа к window/document и дереву DOM.
Правильный паттерн такой:
- Web Worker считает/парсит/преобразует данные;
- основной поток получает результат через
postMessageи обновляет UI.
Это делает поведение предсказуемым и не даёт «тяжёлому» коду ломать рендеринг.
Как эффективно передавать большие данные между страницей и Web Worker?
По умолчанию postMessage использует structured clone — данные копируются. На больших массивах это может стать узким местом.
Для бинарных данных используйте Transferable (например, ArrayBuffer), чтобы передать владение без копирования:
- быстрее обмен;
- меньше пиков памяти.
Важно: после передачи буфер в отправителе обычно становится «обнулённым» (detached).
Что делает Service Worker и почему его называют прокси между страницей и сетью?
Это скрипт‑«прокси» внутри браузера, который:
- слушает события (чаще всего
fetch); - решает, отдать ресурс из сети или из
Cache Storage; - может показывать офлайн‑fallback;
- может работать по событиям даже без активной вкладки.
Он не ускоряет всё автоматически: ускорение появляется, когда вы задаёте подходящую стратегию кэширования.
Как устроен жизненный цикл Service Worker (register/install/activate)?
Базовая схема такая:
register— страница регистрирует воркер;install— можно подготовить кэши/прекэш;activate— воркер начинает контролировать клиентов (в рамках scope), часто здесь чистят старые кэши.
Обновления происходят контролируемо: новый воркер может попасть в состояние waiting, пока не исчезнут вкладки со старой версией.
Какие стратегии кэширования в Service Worker выбрать и для чего?
Популярные стратегии:
- Cache-first — статика (CSS/шрифты/иконки), максимум скорости, но важно версионирование.
- Network-first — «живые» данные, при сбое сети берём кэш.
- Stale-while-revalidate — сразу отдаём кэш, параллельно обновляем; часто лучший баланс UX/актуальности.
Для API кэшируйте только осознанно: продумайте TTL/инвалидацию и исключения для персональных ответов.
Почему Service Worker требует HTTPS (кроме localhost)?
Service Worker разрешён только в secure context:
- HTTPS обязателен;
- исключение —
localhostдля разработки.
Причина практическая: без HTTPS злоумышленник мог бы подменить файл воркера и надолго закрепиться в браузере пользователя (перехватывать запросы, отдавать фальшивые ответы из кэша).
Как отлаживать воркеры и что делать, если Service Worker кэширует «не то» или не обновляется?
Проверьте и отладьте так:
- DevTools → Application → Service Workers: статус, scope, waiting/active, кнопки обновления/Unregister.
- DevTools → Application → Cache Storage: что реально закэшировано.
- Тест офлайна: Network → Offline.
Если «залипла» старая версия:
- сделайте
Unregisterи Clear storage; - проверьте версионирование кэша и очистку старых кэшей в
activate.
Для Web Worker ищите отдельный контекст в DevTools (Sources/Workers) и профилируйте, где тратится время — в UI‑потоке или в воркере.