Włącz obsługę offline w aplikacjach internetowych za pomocą Service Workers
Pracownicy usług i Cache API sprawiają, że strona ładuje się natychmiastowo i może funkcjonować offline. Pisanie kodu pracownika, jego rejestracja oraz wybór strategii cacheowania.
Źródła: ☕ JavaScript Hack That Makes Any Website Work Offline
Załóżmy, że ktoś przegląda twoją stronę podczas jazdy pociągiem, a jego połączenie co kilka sekund się urywa i przywraca. Na większości stron internetowych takie niestabilne połączenie oznacza problem – błąd przeglądarki informuje go, że jest poza siecią. A co, jeśli twoja strona mogłaby całkowicie uniknąć tego problemu i nadal funkcjonować?
To nie jest jakaś eksperymentalna funkcja przyszłości. Można to osiągnąć już teraz dzięki technologii przeglądarki zwanej Service Worker. Service Worker działa jak skryptowy pośrednik pomiędzy twoją aplikacją internetową a siecią. Może przechwytywać żądania przed tym, jak dotrą do serwera, i samodzielnie na nie odpowiadać za pomocą plików przechowywanych lokalnie, dzięki czemu twoja strona może nadal funkcjonować nawet bez żadnego połączenia.
Ten trik służy nie tylko do zapewnienia przydatnego rozwiązania awaryjnego — może znacznie przyspieszyć czas ładowania i sprawić, że twoja aplikacja będzie znacznie bardziej odporna na problemy z siecią. I chociaż brzmi to skomplikowanie, jego konfiguracja jest dość prosta.
Czym napędza ten trik: Service Workers w połączeniu z Cache API
Dwie funkcje przeglądarki współpracują ze sobą, aby to umożliwić:
- Service Worker: skrypt działający w tle, niezależnie od głównej nitki strony, pełniący rolę warstwy sieciowej.
- Cache API: wbudowana interfejs przeglądarki, która umożliwia programowe przechowywanie i odzyskiwanie zasobów, podobnie jak magazyn typu klucz-wartość. To tutaj przechowujesz pliki HTML, CSS, JavaScript, obrazy oraz inne zasoby, od których zależy twoja strona.
Oto ogólny przebieg: za pierwszym razem, gdy ktoś odwiedza twoją stronę podłączony do Internetu, Service Worker instaluje się i pobiera ważne pliki do swojej pamięci cache. Od tego momentu każde żądanie sieciowe wysyłane przez stronę przechodzi najpierw przez Service Worker. Gdy odwiedzający traci połączenie, worker reaguje, korzystając z tego, co już ma w cache, zamiast próbować – i ponosić porażkę – połączenia z serwerem, dzięki czemu strona nadal renderowana jest niemal natychmiast.
Krok 1: Napisz skrypt Service Worker
Zacznij od stworzenia pliku o nazwie sw.js w korzeniu swojego projektu. To właśnie ten skrypt jest odpowiedzialny za instalację pamięci cache oraz przechwytywanie przyszłych żądań.
// sw.js
const CACHE_NAME = 'my-website-cache-v1';
const urlsToCache = [
'/',
'/index.html',
'/styles.css',
'/script.js',
'/images/logo.png'
];
// The 'install' event is fired when the service worker is first installed.
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
// The 'fetch' event is fired for every network request.
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
// If the request is in the cache, serve the cached version.
if (response) {
console.log('Serving from cache:', event.request.url);
return response;
}
// Otherwise, fetch from the network.
console.log('Fetching from network:', event.request.url);
return fetch(event.request);
})
);
});
Plik ten głównie przysłuchuje się do dwóch zdarzeń cyklu życia:
install: tutaj otwierasz nazwany cache i wypełniasz go listą plików, które chcesz mieć dostępne nawet bez połączenia sieciowego.fetch: to zdarzenie powstaje przy każdej prośbie wysyłanej przez stronę. Procesor sprawdza, czy w cache już istnieje odpowiadająca odpowiedź; jeśli tak, zwraca tę zapisaną kopię, a jeśli nie, prośba jest wysyłana do sieci jak zwykle.
Krok 2: Zarejestruj procesor w swojej aplikacji
Gdy skrypt procesora już istnieje, nadal trzeba poinformować przeglądarkę o jego użyciu. Dodaj następujący fragment do swojego głównego pliku skryptowego lub wstaw go bezpośrednio do tagu <script> w pliku HTML.
// Register the service worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('Service Worker registered successfully:', registration);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
});
}
Ten blok najpierw sprawdza, czy aktualny przeglądarka w ogóle obsługuje API Service Worker, a jeśli tak, to rejestruje plik sw.js. Zwróć uwagę na ścieżkę używaną do jego rejestracji: /sw.js musi znajdować się w korzeniu strony, ponieważ Service Worker może kontrolować tylko te strony, które należą do zakresu katalogu, z którego został zarejestrowany.
Weryfikacja poprawności działania
Aby zobaczyć to w praktyce, otwórz swoją stronę w przeglądarce, która obsługuje Service Workers — nadają się Chrome, Firefox i Edge.
- Otwórz narzędzia deweloperskie przeglądarki (F12 lub Ctrl+Shift+I).
- Przejdź do panelu Application.
- W pasku bocznym znajdź Service Workers. Twój plik
sw.jspowinien tam być widoczny jako aktywny.
Jeśli wszystko jest poprawnie skonfigurowane, strona załaduje się natychmiast, mimo braku dostępu do sieci. Wyniki z konsoli w narzędziach deweloperskich potwierdzą, że żądania są przekierowywane i obsługiwane bezpośrednio z pamięci cache, a nie z sieci.
Rozszerzanie tego podejścia: alternatywne strategie cacheowania
To, co właśnie opisano, nazywane jest podejściem cache-first, network-fallback – doskonałym rozwiązaniem dla zasobów, które rzadko się zmieniają, takich jak statyczne obrazy lub spakowane skrypty. Jednak Service Workers nie są ograniczone tylko do tego jednego wzorca; istnieje kilka innych powszechnych strategii:
- Network-first, cache-fallback: nadaje się do treści, które zmieniają się często i muszą pozostawać aktualne. Procesor najpierw próbuje pobrać dane z sieci, a tylko w przypadku niepowodzenia tej próby, na przykład z powodu słabej łączności, korzysta z treści z pamięci cache.
- Stale-while-revalidate: procesor natychmiast odpowiada za pomocą treści już zapisanej w pamięci cache dla szybkości, jednocześnie wysyłając w tle żądanie do sieci w celu odświeżenia cache przed kolejnym załadowaniem strony. Dzięki temu otrzymujesz szybkie odpowiedzi już teraz, a aktualne treści wkrótce potem.
Opanowanie tego podstawowego wzorca pracy offline umożliwia również tworzenie pełnych aplikacji Progressive Web Apps, w których obsługa pracy offline łączy się z funkcjami takimi jak powiadomienia typu push oraz możliwością instalacji strony na ekranie głównym urządzenia jak aplikacji natywnej.
Dodanie tego wzorca do twojego projektu to stosunkowo niewielka inwestycja przynosząca znaczące korzyści: zamiast nieprawidłowego połączenia całkowicie psującego doświadczenie użytkownika, oni ledwo zauważają tę przerwę.
Literatura pokrewna
- Przestań synchronizować stan z useEffect: bezpieczniejszy wzorzec Reacta — Dowiedz się, dlaczego używanie useEffect do synchronizacji stanu powoduje sytuacje konkurencyjne i dodatkowe renderowania, oraz jak zastąpić to metodą wyprowadzania stanu w czasie renderowania i użyciem atrybutu key.
- Zarządzanie stanami interfejsu w praktyce za pomocą warunkowego renderowania Reacta — Poznaj, jak budować interfejsy autoryzacji, ról, uprawnień, stanów ładowania, błędów i stanu pustego w React przy użyciu praktycznych wzorców warunkowego renderowania.