Progresywne aplikacje internetowe: praca z instancjami roboczymi

1. Witamy

W tym module dodasz do istniejącej aplikacji internetowej instancję roboczą, aby udostępniać stan między dwoma otwartymi oknami. To ósme z serii powiązanych ćwiczeń z kodem do warsztatów na temat progresywnych aplikacji internetowych. Poprzedni codelab to Service Worker Includes. To ostatni codelab z tej serii.

Czego się nauczysz

  • Dodawanie udostępnianej instancji roboczej między wieloma otwartymi oknami
  • Używanie Comlink do ułatwiania pracy z instancjami roboczymi

Co warto wiedzieć

  • JavaScript

Wymagania

2. Pierwsze kroki

Zacznij od sklonowania lub pobrania kodu startowego potrzebnego do ukończenia tego ćwiczenia:

Jeśli klonujesz repozytorium, upewnij się, że jesteś w gałęzi pwa06--working-with-workers. Plik ZIP zawiera też kod tej gałęzi.

Ten kod wymaga Node.js w wersji 14 lub nowszej. Gdy kod będzie dostępny, uruchom npm ci z wiersza poleceń w folderze kodu, aby zainstalować wszystkie potrzebne zależności. Następnie uruchom npm start, aby uruchomić serwer programistyczny dla tego laboratorium.

Plik README.md kodu źródłowego zawiera wyjaśnienie wszystkich rozpowszechnianych plików. Oto najważniejsze pliki, z którymi będziesz pracować w trakcie tego ćwiczenia:

Kluczowe pliki

  • js/preview.js – plik JavaScript strony podglądu
  • js/main.js – główny plik JavaScript aplikacji

3. Tworzenie pracownika

Obecnie funkcja podglądu aplikacji internetowej wyświetla tylko najnowsze treści podczas wczytywania. Najlepiej, gdyby podczas pisania użytkownik widział podgląd na żywo. Wymaga to zebrania potencjalnie dużej ilości danych i przeniesienia ich między 2 różnymi otwartymi oknami. Z tego powodu nie chcemy tego robić w głównym wątku żadnego z otwartych okien. Zamiast tego użyjmy udostępnionego procesu roboczego.

Aby rozpocząć, utwórz plik js/worker.js z tym kodem:

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]);

Wyjaśnienie

Ten kod tworzy klasę o nazwie Compiler, która umożliwia ustawianie treści i wywoływanie subskrypcji po skompilowaniu tych treści. Ponieważ jest to współdzielony proces roboczy, powinna być używana tylko jedna instancja tej klasy, więc tworzona jest nowa instancja Compiler. Aby praca z tą klasą była płynna z zewnątrz procesu roboczego, używamy Comlink do udostępniania instancji kompilatora, co pozwala nam używać wszystkich jej metod tak, jakby były zadeklarowane w kodzie, który ich używa. Ponieważ jest to współdzielony, a nie dedykowany proces roboczy, musi być dostępny dla wszystkich połączeń.

4. Wysyłanie treści do wykonawcy

Po utworzeniu procesu roboczego musimy przesłać do niego treści. Aby to zrobić, zaktualizuj js/main.js w ten sposób:

  • Zaimportuj eksport o nazwie wrap z comlink
  • Utwórz nowy moduł Shared Worker o nazwie worker, ustaw jego typ na module i wskaż go za pomocą wzorca new URL (new URL('./worker.js', import.meta.url)).
  • Utwórz zmienną compiler, która wrap worker.port
  • W funkcji aktualizacji edytora (editor.onUpdate) po zapisaniu treści w bazie danych poczekaj na zakończenie działania funkcji compiler.set, przekazując do niej treść.

Wyjaśnienie

Zawijanie eksportu Comlink umożliwia używanie np. udostępnionych metod klasy tak, jakby nie były udostępniane poza granicami procesu roboczego, z wyjątkiem tego, że wszystko jest teraz asynchroniczne. Ponieważ jest to współdzielony, a nie dedykowany proces roboczy, Comlink musi opakować port procesu roboczego, a nie sam proces roboczy. Teraz, gdy tylko wprowadzisz zmiany w edytorze, treść zostanie wysłana do procesu roboczego, aby ją przetworzyć.

5. Aktualizowanie strony podglądu

Ostatnim krokiem jest przeniesienie skompilowanej treści z udostępnionego pracownika do podglądu. Konfiguracja jest w dużej mierze taka sama, ale ponieważ funkcje nie mogą być przekazywane między granicami procesu roboczego, zamiast nich należy użyć proxy funkcji. Comlink znowu przychodzi z pomocą. Zaktualizuj js/preview.js, aby:

  • Zaimportuj nazwane eksporty wrap i proxy z comlink
  • Utwórz i opakuj współdzielony element roboczy tak jak w js/main.js.
  • Wywołaj metodę subscribe kompilatora za pomocą funkcji proxy, która ustawia właściwość compiled danych przychodzących na wewnętrzny kod HTML obszaru podglądu.

Gdy to zrobisz, otwórz podgląd, zacznij pisać w edytorze i obserwuj, jak Twój kod Markdown jest automatycznie kompilowany i pojawia się w czasie rzeczywistym w obszarze podglądu, a wszystko to bez blokowania głównego wątku żadnej ze stron.

6. Gratulacje!

Wiesz już, jak używać współdzielonego procesu roboczego do udostępniania stanu między wieloma instancjami PWA.