Узнайте, что такое Web Worker и Service Worker, в чём их отличия и когда использовать каждый для ускорения страниц, фоновых задач, кеширования и офлайн‑поддержки.

Браузеры выполняют большую часть вашего JavaScript на главном потоке — том же месте, где обрабатываются ввод пользователя, анимации и отрисовка страницы. Когда там выполняется тяжёлая работа (парсинг больших данных, обработка изображений, сложные расчёты), интерфейс может дергаться или «зависать». Воркеры существуют, чтобы переместить часть задач с главного потока или вне прямого контроля страницы, чтобы приложение оставалось отзывчивым.
Если ваша страница занята 200‑мс вычислением, браузер не сможет плавно прокручивать, реагировать на клики или держать анимации на 60fps. Воркеры позволяют выполнять фоновую работу, пока главный поток сосредоточен на интерфейсе.
Web Worker — это фоновый JavaScript‑поток, который вы создаёте из страницы. Он пригодится для задач с высокой нагрузкой на CPU, которые в противном случае блокировали бы UI.
Service Worker — специальный тип воркера, который располагается между вашим веб‑приложением и сетью. Он может перехватывать запросы, кешировать ответы и включать такие возможности, как офлайн‑режим и push‑уведомления.
Думайте о Web Worker как о помощнике, который выполняет вычисления в другой комнате. Вы отправляете ему сообщение, он работает и отправляет ответ.
Думайте о Service Worker как о привратнике у входной двери. Запросы к страницам, скриптам и API проходят мимо него, и он может решить: получить из сети, отдать из кэша или сформировать свой ответ.
К концу вы узнаете:
postMessage) вписывается в модель воркеров и почему важен Cache Storage API для офлайнаЭтот обзор задаёт «почему» и мысленную модель — дальше мы углубимся в поведение каждого типа воркера и где их стоит применять в реальных проектах.
Когда вы открываете веб‑страницу, большая часть того, что вы «ощущаете», происходит на главном потоке. Он отвечает за отрисовку пикселей (rendering), реакцию на нажатия и клики (input) и выполнение большинства JavaScript.
Поскольку рендеринг, обработка ввода и JavaScript часто выполняются по очереди на одном и том же потоке, одна медленная задача может заставить ждать всё остальное. Поэтому проблемы с производительностью часто проявляются как проблемы с отзывчивостью, а не просто «медленный код».
Что ощущает пользователь при блокировке:
В JavaScript есть много асинхронных API — fetch(), таймеры, события — которые помогают не ждать впустую. Но асинхронность не заставляет тяжёлую работу выполняться одновременно с рендерингом.
Если вы делаете дорогие вычисления (обработка изображений, парсинг большого JSON, криптооперации, сложная фильтрация) на главном потоке, они всё равно будут конкурировать с обновлениями UI. «Асинхронность» может отложить когда это выполняется, но выполнение может всё так же происходить на главном потоке и вызывать jank.
Воркеры нужны, чтобы браузеры могли сохранять отзывчивость страницы и при этом выполнять полезную работу.
Коротко: воркеры защищают главный поток, чтобы ваше приложение оставалось интерактивным, пока фоновые задачи выполняются отдельно.
Web Worker — способ запустить JavaScript вне главного потока. Вместо того, чтобы конкурировать с работой UI (отрисовка, прокрутка, отклик на клики), воркер выполняется в собственном фоновом потоке, поэтому тяжёлые задачи заканчиваются, не заставляя страницу «залипать».
Думайте об этом так: страница остаётся сосредоточенной на взаимодействии с пользователем, а воркер обрабатывает CPU‑интенсивную работу — парсинг большого файла, вычисления для графиков или подготовку данных.
Web Worker работает в отдельном потоке с собственной глобальной областью видимости. Он по‑прежнему имеет доступ ко многим веб‑API (таймеры, fetch во многих браузерах, crypto и т.д.), но намеренно изолирован от страницы.
Есть несколько распространённых вариантов:
Если вы никогда не использовали воркеры, большинство примеров будут про dedicated workers.
Воркеры не могут напрямую вызывать функции на странице. Общение происходит через отправку сообщений:
postMessage().postMessage().Для больших бинарных данных можно ускорить работу, передавая владение ArrayBuffer (чтобы его не копировали), что делает передачу сообщений быстрой.
Из‑за изоляции у воркера есть несколько ключевых ограничений:
window или document. Воркеры работают в self (глобальная область воркера), и доступные API могут отличаться от главного потока.При правильном использовании Web Worker — один из самых простых способов улучшить производительность главного потока, просто изменив место выполнения тяжёлой работы.
Web Workers отлично подходят, когда страница «зависает», потому что JavaScript делает слишком много работы на главном потоке. Главный поток отвечает за взаимодействие с пользователем и рендер, поэтому тяжёлые задачи там приводят к jank, задержкам кликов и заморозке прокрутки.
Используйте Web Worker, когда у вас есть CPU‑интенсивная работа, которой не нужен прямой доступ к DOM:
Практический пример: если вы получаете большой JSON и его парсинг вызывает подвисание UI, вынесите парсинг в воркер и отправляйте результат обратно.
Обмен с воркером происходит через postMessage. Для больших бинарных данных предпочитайте transferable objects (например, ArrayBuffer), чтобы браузер мог передать владение памятью воркеру вместо копирования.
// main thread
worker.postMessage(buffer, [buffer]); // передаёт ArrayBuffer
Это особенно полезно для аудиобуферов, байтов изображений или других крупных блоков данных.
У воркеров есть накладные расходы: отдельные файлы, передача сообщений и иной процесс отладки. Не используйте их, когда:
postMessage‑пинг‑понг может свести пользу на нет.Если задача может вызвать заметную паузу (часто ~50мс+) и может быть выражена как «ввод → вычисление → вывод» без доступа к DOM, Web Worker обычно стоит использовать. Если задача в основном про обновления UI — оставайтесь на главном потоке и оптимизируйте там.
Service Worker — специальный JS‑файл, который выполняется в фоне браузера и действует как программируемый сетевой слой для вашего сайта. Вместо того чтобы работать в контексте страницы, он располагается между вашим приложением и сетью, позволяя решать, что делать при запросах ресурсов (HTML, CSS, API‑вызовы, изображения).
Service Worker имеет жизненный цикл, отделённый от любой вкладки:
Поскольку он может быть остановлен и перезапущен в любой момент, рассматривайте его как событийно‑управляемый скрипт: выполняйте работу быстро, сохраняйте состояние в постоянном хранилище и не предполагайте, что он всегда запущен.
Service Workers ограничены тем же происхождением (origin) и контролируют страницы в пределах своей scope — обычно папки, из которой обслуживается файл воркера (и вложенных путей). Они также требуют HTTPS (кроме localhost) из‑за того, что могут влиять на сетевые запросы.
Service Worker в основном нужен, чтобы находиться между вашим приложением и сетью. Он может решить, когда обращаться в сеть, когда отдавать кешированные данные и когда выполнить небольшую работу в фоне — не блокируя страницу.
Самая распространённая задача — обеспечить офлайн‑или «плохое соединение» за счёт кеширования ассетов и ответов.
Несколько практических стратегий кеширования:
Обычно это реализуют с помощью Cache Storage API и обработки события fetch.
Service Workers улучшают воспринимаемую скорость при повторных визитах за счёт:
В итоге меньше сетевых запросов, быстрее запуск и более стабильная работа при плохом подключении.
Service Workers могут включать фоновые возможности: push‑уведомления и background sync (поддержка зависит от браузера и платформы). Это означает, что вы можете уведомлять пользователей или повторно отправлять неудачные запросы позже — даже если страница сейчас не открыта.
Если вы строите прогрессивное веб‑приложение, Service Workers — ключевая деталь для:
Если запомнить только одно: Web Workers помогают странице выполнять тяжёлую работу без блокировки UI, а Service Workers дают приложению контроль над сетевыми запросами и возможность вести себя как устанавливаемое приложение (PWA).
Web Worker — для CPU‑интенсивных задач: парсинг больших данных, генерация миниатюр, численные расчёты — чтобы главный поток оставался отзывчивым.
Service Worker — для обработки запросов и задач жизненного цикла приложения: офлайн‑поддержка, стратегии кеширования, background sync и push. Он может находиться между приложением и сетью.
Web Worker обычно связан со страницей/вкладкой. При закрытии страницы воркер, как правило, завершается (если не используется SharedWorker и подобное).
Service Worker — событийно‑ориентирован. Браузер может запускать его для обработки событий (fetch, push) даже при отсутствии открытых вкладок, затем выгружать при простое.
Web Worker не может перехватывать сетевые запросы, выполняемые страницей. Он сам может выполнять fetch(), но не может переписывать, кешировать или напрямую обслуживать ответы для других частей сайта.
Service Worker может перехватывать запросы (через fetch‑событие), решать, идти ли в сеть, отдать ли ответ из кэша или вернуть запасной вариант.
Web Worker не управляет HTTP‑кешем вашего приложения.
Service Worker часто использует Cache Storage API для хранения и отдачи пар «запрос/ответ» — это основа офлайн‑кеширования и «мгновенных» повторных загрузок.
Запустить воркер — это в основном вопрос где он выполняется и как загружается. Web Workers создаются напрямую страницей. Service Workers регистрируются страницей, а браузер устанавливает их и ставит перед сетевыми запросами.
Web Worker живёт, когда страница его создаёт. Указываете отдельный JS‑файл и общаетесь через postMessage.
// main.js (выполняется на странице)
const worker = new Worker('/workers/resize-worker.js', { type: 'module' });
worker.postMessage({ action: 'start', payload: { /* ... */ } });
worker.onmessage = (event) => {
console.log('From worker:', event.data);
};
Хорошая мысль: файл воркера — это просто ещё один URL‑скрипт, который страница может загрузить, но он выполняется в фоне.
Service Worker регистрируется со страницы, которую пользователь посещает:
// main.js
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
После регистрации браузер сам обрабатывает install/activate жизненные шаги. В sw.js вы можете слушать события install, activate и fetch.
Service Workers могут перехватывать сетевые запросы и кешировать ответы. Если регистрация была бы разрешена по HTTP, злоумышленник в сети мог бы подменить sw.js и получить контроль над будущими визитами. HTTPS (или http://localhost во время разработки) защищает скрипт и трафик, которым он может управлять.
Браузеры обновляют и кешируют воркеры иначе, чем обычные скрипты. Планируйте обновления:
sw.js/сборка воркера).activate, чтобы старые кэши не оставались.Если нужен более плавный rollout, см. /blog/debugging-workers для практик тестирования, которые ловят краевые случаи обновлений на ранней стадии.
Воркеры могут падать иначе, чем «обычный» JavaScript страницы: они выполняются в отдельных контекстах, имеют собственную консоль и могут перезапускаться браузером. Налаженная рутина отладки экономит часы.
Откройте DevTools и найдите цели воркеров. В Chrome/Edge воркеры часто отображаются в Sources (или через запись «Dedicated worker») и в селекторе контекста консоли.
Используйте те же инструменты, что и для главного потока:
onmessage и долгим функциям.Если сообщения «теряются», проверьте обе стороны: вызываете ли вы worker.postMessage(...), есть ли в воркере self.onmessage = ... и совпадает ли структура сообщения.
Service Workers удобнее отлаживать в панели Application:
Также следите за Console на предмет ошибок во время install/activate/fetch — они часто объясняют, почему кеширование или офлайн‑поведение не работают.
Проблемы с кешированием — самая большая трата времени: кеширование неправильных файлов (или слишком агрессивное) может оставить старый HTML/JS. Во время тестов делайте жёсткую перезагрузку и подтверждайте, что реально отдаётся.
Для реалистичного тестирования используйте DevTools, чтобы:
Если вы быстро итераируете PWA, полезно сгенерировать базовое приложение (с предсказуемым Service Worker и выходом сборки), а затем настраивать стратегии кеширования. Платформы вроде Koder.ai помогают прототипировать React‑приложение из чат‑промпта, экспортировать код и быстро отладить настройку воркеров и правил кеширования с быстрым циклом обратной связи.
Воркеры делают приложения плавнее и функциональнее, но они меняют место выполнения кода и доступные ресурсы. Небольшая проверка по безопасности, приватности и производительности избавит от неожиданных багов и недовольных пользователей.
И Web Workers, и Service Workers ограничены same‑origin policy: они могут взаимодействовать только с ресурсами того же схемы/хоста/порта (если сервер явно не разрешил кросс‑доступ через CORS). Это предотвращает тихое подтягивание данных с другого сайта и их смешивание в вашем приложении.
Service Workers имеют дополнительные предохранители: они обычно требуют HTTPS (или localhost при разработке), потому что могут перехватывать запросы. Обращайтесь с ними как с привилегированным кодом: минимизируйте зависимости, избегайте динамической загрузки кода и аккуратно версиями управляйте логикой кеширования, чтобы старые кэши не продолжали отдавать устаревшие файлы.
Фоновые возможности должны быть предсказуемы. Push‑уведомления мощные, но запросы разрешений легко злоупотребить.
Просите разрешение только когда есть явная польза (например, после включения уведомлений в настройках) и объясняйте, что и когда пользователь получит. Если вы синхронизируете или предзагружаете данные в фоне, сообщайте об этом простым языком — пользователи замечают неожиданную сетевую активность или уведомления.
Воркеры не «бесплатны». Чрезмерное их использование может навредить:
postMessage (особенно с большими объектами) могут стать узким местом. Предпочитайте пакетирование и transferables.Не все браузеры поддерживают каждую возможность (или пользователь может блокировать разрешения). Делайте feature‑detect и корректно деградируйте:
if ('serviceWorker' in navigator) {
// регистрируем сервис‑воркер
} else {
// работаем без офлайн‑возможностей
}
Цель: базовый функционал должен работать, а «приятные дополнения» (оффлайн, push, тяжёлые вычисления) добавляются там, где доступны.
Web Workers и Service Workers решают разные задачи, поэтому они хорошо дополняют друг друга, когда приложению нужны и тяжёлые вычисления, и быстрая надёжная загрузка. Мысленная модель: Web Worker = вычисления, Service Worker = сеть + кеш, главный поток = UI.
Представьте приложение для редактирования фото (изменение размера, фильтры, удаление фона) и просмотра галереи без подключения.
Подход «вычисли → закешируй» держит обязанности разделёнными: воркер производит выходные данные, сервис‑воркер решает, как их хранить и обслуживать.
Для приложений с лентами, формами или полевыми данными:
Даже без полного background sync service worker улучшает восприятие скорости, отдавая кешированные ответы, пока приложение обновляет данные в фоне.
Не смешивайте роли:
postMessage).Нет. Service Worker выполняется в фоне, отдельно от вкладок, и не имеет прямого доступа к DOM (элементам страницы).
Это сделано специально: Service Worker должен уметь работать, даже если документ закрыт (например, чтобы ответить на push‑событие или отдать закешированные файлы). Поэтому браузер изолирует его.
Если Service Worker должен повлиять на отображение, он общается со страницами через сообщения (например, postMessage), а уже страница обновляет UI.
Нет. Web Worker и Service Worker независимы.
Они могут работать отдельно или вместе, если вашему приложению нужны и вычисления, и сетевые возможности.
В современных браузерах Web Workers широко поддержаны и обычно являются безопасной базовой опцией.
Service Workers тоже поддерживаются в актуальных версиях большинства крупных браузеров, но есть дополнительные требования и тонкости:
localhost при разработке).Если нужна широкая совместимость, рассматривайте Service Worker как прогрессивное улучшение: сначала делайте рабочую базу, потом добавляйте офлайн/push там, где доступно.
Не автоматически.
Настоящий выигрыш приходит от использования правильного воркера для реального узкого места и измерения результата до и после.
Используйте Web Worker, когда у вас есть тяжёлая по CPU задача, которую можно выразить как ввод → вычисление → вывод, и ей не нужен доступ к DOM.
Подходящие случаи: парсинг и трансформация больших объёмов данных, сжатие/распаковка, криптография, обработка изображений/аудио и сложная фильтрация. Если задача в основном обновляет UI или часто читает/пишет в DOM, воркер не поможет (и в любом случае не может получить доступ к DOM).
Используйте Service Worker, когда вам нужен контроль над сетью: офлайн‑поддержка, стратегии кеширования, ускорение повторных посещений, маршрутизация запросов и (где поддерживается) push/background sync.
Если ваша проблема — «интерфейс зависает при вычислениях», это вопрос для Web Worker. Если проблема — «медленная загрузка / офлайн не работает», это задача для Service Worker.
Нет. Web Worker и Service Worker — независимые возможности.
Можно использовать только один из них или оба одновременно, если приложению нужны и вычисления, и сетевые/офлайн‑возможности.
Это в основном про область видимости и время жизни.
fetch) даже если страница не открыта, а затем выгрузить при простое.Нет. Web Worker не имеет доступа к window/document.
Если нужно повлиять на UI, отправьте данные обратно в главный поток через postMessage(), а обновление DOM выполняйте в коде страницы. Воркер должен фокусироваться на чистых вычислениях.
Нет. Service Worker не имеет доступа к DOM.
Чтобы повлиять на то, что видит пользователь, общайтесь с контролируемыми страницами через messaging (например, Clients API + postMessage()), и пусть страница обновляет UI.
Используйте postMessage() с обеих сторон.
worker.postMessage(data)self.postMessage(result)Для больших бинарных данных предпочтительны transferable objects (например, ArrayBuffer), чтобы избежать копирования:
Service Worker сидит между приложением и сетью и может отвечать на запросы, используя Cache Storage API.
Типичные стратегии:
Выбирайте стратегию для каждого типа ресурса (app shell vs API‑данные), а не одной глобальной политики.
Да, но важно разделять обязанности.
Распространённый паттерн:
Это помогает не смешивать логику интерфейса и фоновые задачи и делает производительность предсказуемой.
Используйте соответствующий инструмент и отлаживайте в нужной панели DevTools.
onmessage, профилируйте, чтобы убедиться, что главный поток остаётся отзывчивым.При отладке кеширования всегда проверяйте, что реально возвращается (сеть vs кэш) и тестируйте в режиме Offline / с троттлингом.
worker.postMessage(buffer, [buffer]);