Nowoczesna alternatywa dla funkcji importScripts().
Tło
Moduły ES są od jakiegoś czasu ulubionymi modułami programistów. Oprócz wielu innych zalet oferują one uniwersalny format modułu, w którym wspólny kod może być publikowany raz i uruchamiany w przeglądarkach oraz w alternatywnych środowiskach wykonawczych, takich jak Node.js. Chociaż wszystkie nowoczesne przeglądarki oferują obsługę modułów ES, nie wszystkie oferują obsługę wszędzie, gdzie można uruchomić kod. W szczególności obsługa importowania modułów ES w usługach workera przeglądarki dopiero zaczyna być bardziej dostępna.
Z tego artykułu dowiesz się, jak obecnie wygląda obsługa modułów ES w usługach workera w popularnych przeglądarkach, a także jakie pułapki należy unikać i jakie są najlepsze metody publikowania kodu usługi workera zgodnego ze starszymi wersjami.
Przypadki użycia
Najlepszym zastosowaniem modułów ES w usługach workerów jest wczytywanie nowoczesnej biblioteki lub kodu konfiguracyjnego, który jest udostępniany innym środowiskom wykonawczym obsługującym moduły ES.
Próba udostępnienia kodu w ten sposób przed wprowadzeniem modułów ES wymagała użycia starszych formatów „uniwersalnych” modułów, takich jak UMD, które zawierają niepotrzebne szablony, oraz napisania kodu, który wprowadzał zmiany w globalnie udostępnionych zmiennych.
Skrypty zaimportowane za pomocą modułów ES mogą wywołać aktualizację workera usługi, jeśli ich zawartość ulegnie zmianie, zgodnie z zachowaniem importScripts()
.
Obecne ograniczenia
tylko importowanie statyczne;
Moduły ES mogą być importowane na 2 sposoby: statycznie, za pomocą składni import ... from '...'
, lub dynamicznie, za pomocą metody import()
. W przypadku usług działających w tle obsługiwana jest obecnie tylko składnia statyczna.
To ograniczenie jest analogiczne do podobnego ograniczenia dotyczącego korzystania z importScripts()
. Dynamiczne wywołania do importScripts()
nie działają w ramach usługi wtyczki. Wszystkie wywołania importScripts()
, które są z zasady synchroniczne, muszą zostać zakończone, zanim usługa wtyczki zakończy fazę install
. To ograniczenie zapewnia, że przeglądarka wie o istnieniu i może domyślnie zapisać w pamięci podręcznej cały kod JavaScriptu potrzebny do implementacji usługi w ramach procesu instalacji.
Ostatecznie to ograniczenie może zostać zniesione, a dynamiczne importowanie modułów ES może zostać dozwolone. Na razie używaj tylko składni statycznej w ramach usługi workera.
A co z innymi pracownikami?
Obsługa modułów ES w „wyznaczonych” workerach (zbudowanych za pomocą new Worker('...', {type: 'module'})
) jest bardziej rozpowszechniona i jest obsługiwana w Chrome i Edge od wersji 80, a także w najnowszych wersjach przeglądarki Safari.
W przypadku dedykowanych pracowników obsługiwane są zarówno importy statycznych, jak i dynamicznych modułów ES.
Chrome i Edge obsługują moduły ES w wspólnych wątkach od wersji 83, ale żadna inna przeglądarka nie oferuje obecnie takiej obsługi.
Brak obsługi map importowanych
Mapy importowania umożliwiają środowiskom uruchomieniowym przepisywanie specyfikatorów modułów, np. dołączanie na początku adresu URL preferowanej sieci CDN, z której można wczytywać moduły ES.
Chociaż Chrome i Edge w wersji 89 i wyższych obsługują mapy importu, obecnie nie można ich używać w procesie obsługi.
Obsługa przeglądarek
Moduły ES w usługach działających w tle są obsługiwane w Chrome i Edge od wersji 91.
Safari dodało obsługę w wersji 122 wersji Technology Preview, a deweloperzy powinni spodziewać się, że ta funkcja zostanie w przyszłości udostępniona w stabilnej wersji Safari.
Przykładowy kod
Oto podstawowy przykład użycia udostępnionego modułu ES w kontekście window
aplikacji internetowej, a także rejestracji pracownika usługi, który używa tego samego modułu ES:
// Inside config.js:
export const cacheName = 'my-cache';
// Inside your web app:
<script type="module">
import {cacheName} from './config.js';
// Do something with cacheName.
await navigator.serviceWorker.register('es-module-sw.js', {
type: 'module',
});
</script>
// Inside es-module-sw.js:
import {cacheName} from './config.js';
self.addEventListener('install', (event) => {
event.waitUntil((async () => {
const cache = await caches.open(cacheName);
// ...
})());
});
Zgodność wsteczna
Powyższy przykład działałby dobrze, gdyby wszystkie przeglądarki obsługiwały moduły ES w usługach, ale w momencie pisania tego artykułu tak nie jest.
Aby uwzględnić przeglądarki, które nie mają wbudowanego wsparcia, możesz uruchomić skrypt service workera za pomocą pakera zgodnego z modułami ES, aby utworzyć service workera, który zawiera cały kod modułu w postaci inline i będzie działać w starszych przeglądarkach. Jeśli moduły, które próbujesz zaimportować, są już dostępne w pakiecie w formatach IIFE lub UMD, możesz je zaimportować za pomocą importScripts()
.
Gdy masz już 2 wersje usługi workera – jedną, która korzysta z modułów ES, a drugą, która z nich nie korzysta – musisz wykryć, co obsługuje bieżąca przeglądarka, i zarejestrować odpowiedni skrypt usługi workera. Sprawdzone metody wykrywania pomocy są obecnie w procesie zmian, ale możesz śledzić dyskusję w tym problemie na GitHubie, aby uzyskać rekomendacje.
_Zdjęcie autorstwa Vlado Paunovic z Unsplash_