Прогрессивные веб-приложения: работа с работниками

1. Добро пожаловать

В этой лабораторной работе вы добавите к существующему веб-приложению веб-воркер для обмена состоянием между двумя открытыми окнами. Это восьмая из серии сопутствующих практических работ для семинара Progressive Web App . Предыдущая лабораторная работа была посвящена включению сервис-воркера . Это заключительная лабораторная работа в этой серии.

Чему вы научитесь

  • Добавить общий рабочий процесс между несколькими открытыми окнами
  • Используйте Comlink, чтобы упростить работу с работниками

Что вам следует знать

  • JavaScript

Что вам понадобится

2. Подготовка

Начните с клонирования или загрузки начального кода, необходимого для выполнения этой лабораторной работы:

Если вы клонируете репозиторий, убедитесь, что вы находитесь на ветке pwa06--working-with-workers . ZIP-архив также содержит код для этой ветки.

Для этой кодовой базы требуется Node.js 14 или выше. После того, как код будет готов, выполните команду npm ci из командной строки в папке с кодом, чтобы установить все необходимые зависимости. Затем выполните npm start , чтобы запустить сервер разработки для этой кодовой лаборатории.

Файл README.md исходного кода содержит пояснения ко всем распространяемым файлам. Кроме того, ниже перечислены основные существующие файлы, с которыми вы будете работать в ходе этой лабораторной работы:

Ключевые файлы

  • js/preview.js — файл JavaScript страницы предварительного просмотра
  • js/main.js — Основной файл JavaScript приложения

3. Напишите рабочий файл

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

Для начала создайте файл js/worker.js со следующим кодом:

import { expose } from 'comlink';
import { marked } from 'marked';

class Compiler {
  state = {
    raw: '',
    compiled: '',
  };
  subscribers = [];

  async set(content) {
    this.state = {
      raw: content,
      compiled: marked(content),
    };

    await Promise.all(this.subscribers.map((s) => s(this.state)));
  }

  subscribe(cb) {
    this.subscribers.push(cb);
  }
}

const compiler = new Compiler();

onconnect = (e) => expose(compiler, e.ports[0]);

Объяснение

Этот код создаёт класс Compiler , позволяющий настраивать контент и вызывать подписки после его компиляции. Поскольку это общий воркер, должен использоваться только один экземпляр этого класса, поэтому создаётся новый экземпляр Compiler . Затем, чтобы работа с этим классом извне воркера была бесперебойной, используется Comlink для предоставления экземпляра компилятора, позволяя использовать все его методы, как если бы они были объявлены в коде, использующем его. Поскольку это общий воркер, а не выделенный, он должен быть доступен для всех подключений.

4. Отправка контента работнику

После создания воркера нам нужно отправить в него контент. Для этого обновите js/main.js следующим образом:

  • Импортируйте именованную экспортную wrap из comlink
  • Создайте новый Shared Worker с типом модуля, назовите его worker , задайте ему тип module и укажите на него, используя new URL ( new URL('./worker.js', import.meta.url) ).
  • Создайте переменную compiler , которая wrap worker.port
  • В функции обновления редактора ( editor.onUpdate ) после сохранения содержимого в базе данных дождитесь завершения compiler.set , передавая содержимое

Объяснение

Обёртывание экспорта Comlink позволяет использовать такие вещи, как методы открытого класса, как если бы они не были общими для всего рабочего процесса, за исключением того, что теперь всё асинхронно. Поскольку это общий, а не выделенный рабочий процесс, Comlink необходимо обёртывать порт рабочего процесса, а не сам рабочий процесс. Теперь при каждом обновлении редактора содержимое будет отправляться в рабочий процесс для обработки!

5. Обновите страницу предварительного просмотра.

Последний шаг — перенести скомпилированный контент из общего воркера в предварительный просмотр! Настройка в целом та же, но поскольку функции не могут передаваться между границами воркера, вместо этого необходимо использовать прокси-сервер для функции. Comlink, опять же, готов помочь. Обновите js/preview.js чтобы сделать следующее:

  • Импортируйте именованные экспорты wrap и proxy из comlink
  • Создайте и оберните общий воркер, как вы это сделали в js/main.js
  • Вызовите метод subscribe компилятора с прокси-функцией, которая устанавливает compiled свойство входящих данных для внутреннего HTML-кода области предварительного просмотра.

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

6. Поздравляем!

Вы узнали, как использовать общий рабочий процесс для совместного использования состояния несколькими экземплярами PWA.