Пара слов о веб-воркерах

О сервис-воркерах слышали все. А вот когда разговор заходит о веб-воркерах, часто я встречаю вопрос «А что это?». В этом посте расскажу подробнее, что это такое и когда эту технологию стоит использовать.

Что за зверь

Веб-воркер — штука, которая умеет выполняться в браузере параллельно с основным скриптом. А значит — выполняться, не блокируя отрисовку страницы. Проще говоря, если запустить что-то тяжёлое в основном скрипте, то страница будет тормозить, а если в веб-воркере — то не будет.

Что нужно знать перед началом

  • Джаваскрипт всё-таки однопоточный, поэтому если мы хотим запустить какую-то задачу параллельно, то она должна лежать в отдельном файле.
  • Веб-воркер не имеет доступа ни к ДОМ-дереву, ни к объекту window. Напрямую к локальному хранилищу обратиться внутри него тоже нельзя. Всё потому, что работа с ДОМ-деревом и локальным хранилищем — последовательная, а веб-воркер работает параллельно.
  • Общаться с веб-воркером придётся через сообщения, которые нужно пересылать между ним и основным скриптом. Но стоит учитывать, что передача объектов по ссылке внутрь воркера не сработает, объекты будут скопированы перед отправкой.

АПИ

У веб-воркеров простое АПИ. Чтобы проверить, поддерживается ли технология браузером:

if (window.Worker) {...}

Чтобы создать воркер:

const worker = new Worker('./path/to/file.js')
// путь должен быть прописан относительно .html, 
// в котором подключается основной скрипт

Чтобы отправить сообщение из основного скрипта в воркер:

worker.postMessage({key: 'value'})

Чтобы подписаться на сообщение внутри воркера:

self.onmessage = e => 
  console.log(e)
// self — глобальный объект внутри воркера,
// как window в основном скрипте

Чтобы отправить сообщение из воркера в основной скрипт:

self.postMessage({key: 'value'})

И чтобы подписаться на сообщение от воркера в основном скрипте:

worker.onmessage = e =>
  console.log(e)

Пример

Я написал небольшой пример, где запустил сложные вычисления вначале в основном скрипте, а затем в веб-воркере. После этого сравнил, как ведёт себя анимация, с помощью отладчика в Хроме.

Вначале попробовал сделать анимацию без ЦСС-трансформаций, чтобы результат был нагляднее. Получилось так.

Без применения веб-воркера анимация стопорится, и ФПС падает до 0. Так происходит потому, что процессор занят сложной задачей. На скриншоте видно, сколько места занял response — это вычисления:

Веб-воркер выполняется параллельно, поэтому анимация в среднем держится на уровне 60 ФПС. На скриншоте видно, что вычисления теперь выполняются отдельно:

Результат для анимации без ЦСС-трансформаций видно и невооружённым глазом. Попробуйте покликать на разные кнопки сами.

ЦСС-трансформации спасают положение, страница становится отзывчивее, а анимация глаже. Но даже с ними при чуть больших нагрузках ФПС падает до 45–50. С веб-воркером ФПС стабильно держится на 60.

Зачем это

Выносить сложные вещи в отдельный скрипт кажется чем-то надуманным, пока не столкнёшься с обработкой потоковых данных, больших текстов или чисел в браузере. На одном из проектов нашей команде потребуется анализ текста на клиенте, поэтому мы думаем в сторону веб-воркеров.

Кто уже использует

Покедекс использует веб-воркер для обзора изменений в shadow DOM. Из-за этого приложение плавно скроллится и работает без подмерзаний даже на старых телефонах.

И на сладкое

Веб-воркеры поддерживаются всеми браузерами, кроме Оперы Мини. Они работают даже в 11-м ИЕ:

Поэтому пользуйтесь, классная же технология :–)

Доп. материалы