Rejestracja skryptu service worker

Sprawdzone metody czasowania rejestracji procesów Service Worker.

Skrypty service worker mogą znacznie przyspieszyć wielokrotne wizyty w Twojej aplikacji internetowej, ale musisz zadbać o to, aby początkowa instalacja skryptu service worker nie pogarsza komfortu korzystania przez użytkownika przy pierwszej wizycie.

Ogólnie rzecz biorąc, odroczenie rejestracji skryptów service worker do czasu wczytania pierwszej strony zapewnia użytkownikom najlepsze wrażenia, zwłaszcza użytkownikom urządzeń mobilnych z wolniejszym połączeniem sieciowym.

Powszechny schemat rejestracji

Na pewno zdarzyło Ci się natrafić na mechanizm Service Worker, który jest podobny do tego:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
}

Czasami towarzyszy im kilka instrukcji console.log() lub kodu, które wykrywają aktualizację wcześniejszej rejestracji skryptu service worker, aby użytkownicy wiedzieli, że powinni odświeżyć stronę. To jednak tylko drobne zmiany w porównaniu z kilkoma standardowymi wierszami kodu.

Czy navigator.serviceWorker.register ma jakiś niuans? Czy są jakieś sprawdzone metody? Nic dziwnego, że ten artykuł nie kończy się na końcu), więc odpowiedź na oba pytania brzmi: „tak!”.

Pierwsza wizyta użytkownika

Przyjrzyjmy się teraz pierwszej wizycie użytkownika w aplikacji internetowej. Nie ma jeszcze skryptu service worker, a przeglądarka nie jest w stanie przewidzieć z wyprzedzeniem, czy jakiś skrypt service worker zostanie zainstalowany w przyszłości.

Jako programista musisz zadbać o to, by przeglądarka szybko pobierała minimalny zestaw kluczowych zasobów potrzebnych do wyświetlenia strony interaktywnej. Wszystko, co spowalnia pobieranie tych odpowiedzi, jest przeciwnikiem zbyt długiego procesu interaktywnego.

Teraz wyobraź sobie, że podczas pobierania kodu JavaScript lub obrazów, które musi wyświetlić Twoja strona, przeglądarka decyduje się uruchomić wątek lub proces w tle (dla zachowania zwięzłości zakładamy, że to wątek). Wyobraźmy sobie, że nie jest to wydajny komputer, tylko telefon o niskiej wydajności, który większość ludzi na świecie uważa za swoje podstawowe urządzenie. Rozwinięcie tego dodatkowego wątku zwiększa rywalizację o czas procesora i pamięć, którą przeglądarka mogłaby wykorzystać na renderowanie interaktywnej strony internetowej.

Bezczynny wątek w tle raczej nie spowoduje znaczącej różnicy. Co jednak, jeśli wątek nie jest bezczynny, tylko zadecyduje, że zacznie też pobierać zasoby z sieci? Jeśli chodzi o rywalizację z procesorami lub pamięcią, warto się martwić o ograniczoną przepustowość dostępną na wielu urządzeniach mobilnych. Przepustowość to podstawa, dlatego nie musisz obniżać krytycznych zasobów, pobierając jednocześnie zasoby dodatkowe.

Wszystko to wskazuje na to, że uruchomienie w tle nowego wątku skryptu service worker do pobrania zasobów z pamięci podręcznej w tle może nie spełniać Twojego celu, którym jest najkrótszy czas interakcji użytkownika przy pierwszej wizycie użytkownika w witrynie.

Ulepszanie gotowego modelu

Rozwiązaniem jest sterowanie uruchomieniem skryptu service worker przez wybór czasu wywoływania funkcji navigator.serviceWorker.register(). Najprostszą zasadą jest opóźnienie rejestracji do window po uruchomieniu tagu load event. Na przykład:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}

Odpowiedni moment na rozpoczęcie rejestracji mechanizmu Service Worker może też zależeć od tego, co robi aplikacja internetowa zaraz po jej wczytaniu. Na przykład aplikacja internetowa Google I/O 2016 zawiera krótką animację, która pojawia się przed przejściem na ekran główny. Nasz zespół stwierdził, że uruchomienie rejestracji mechanizmów Service Worker w trakcie animacji może spowodować problemy z ruchem na słabszych urządzeniach mobilnych. Aby zapewnić użytkownikom dobre wrażenia, opóźniliśmy rejestrację mechanizmu Service Worker do czasu zakończenia animacji, kiedy to w przeglądarce prawdopodobnie wystąpiło kilka sekund bezczynności.

Podobnie jeśli aplikacja internetowa korzysta z platformy, która przeprowadza dodatkową konfigurację po wczytaniu strony, poszukaj zdarzenia związanego z tą platformą, które sygnalizuje zakończenie zadania.

Kolejne wizyty

Do tej pory koncentrowaliśmy się na pierwszej wizycie, ale jaki wpływ na wielokrotne wizyty w witrynie ma opóźniona rejestracja tych pracowników? Choć może to być zaskakujące, nie powinno to mieć żadnego wpływu.

Zarejestrowany skrypt service worker przechodzi przez zdarzenia cyklu życia install i activate. Po aktywowaniu skrypt service worker może obsługiwać zdarzenia fetch w przypadku kolejnych wizyt w aplikacji internetowej. Skrypt service worker uruchamia się przed wysłaniem żądania dotyczącego stron z danego zakresu, co ma sens, jeśli się nad nim zastanowić. Gdyby istniejący skrypt service worker nie był uruchomiony przed odwiedzeniem strony, nie miałby szans na realizację zdarzeń fetch w przypadku żądań nawigacji.

Gdy masz aktywny mechanizm service worker, nie ma znaczenia, kiedy dzwonisz do navigator.serviceWorker.register() ani czy w ogóle je wywołujesz. Jeśli nie zmienisz adresu URL skryptu skryptu service worker, podczas kolejnych wizyt navigator.serviceWorker.register() będzie w praktyce brakiem operacji. Użytkowanie nie ma znaczenia.

Powody wcześniejszej rejestracji

Czy są jakieś sytuacje, w których sensowne jest zarejestrowanie skryptu service worker jak najwcześniej? Jeden z nich kojarzy się z sytuacją, w której mechanizm Service Worker wykorzystuje clients.claim() do przejęcia kontroli nad stroną podczas pierwszej wizyty, a są to agresywne przechowywanie w pamięci podręcznej w czasie działania w obrębie modułu obsługi fetch. W takiej sytuacji warto jak najszybciej aktywować mechanizm Service Worker, aby zapełnić pamięci podręczne środowiska wykonawczego zasobami, które mogą się później przydać. Jeśli Twoja aplikacja internetowa należy do tej kategorii, warto się cofnąć i upewnić się, że moduł obsługi install skryptu service worker nie żąda zasobów, które walczą o przepustowość z żądaniami strony głównej.

Testowanie różnych rozwiązań

Świetnym sposobem na symulowanie pierwszej wizyty jest otwarcie aplikacji internetowej w oknie incognito w Chrome i sprawdzenie ruchu sieciowego w Narzędziach deweloperskich w Chrome. Jako programista stron internetowych dziesiątki i dziesiątki razy dziennie odświeżasz lokalną instancję swojej aplikacji internetowej. Gdy jednak odwiedzisz witrynę z skryptem service worker i w pełni zapełnioną pamięcią podręczną, nie uzyskasz dostępu do tych samych możliwości, jakie widział nowy użytkownik. Łatwo też zignorujesz potencjalny problem.

Oto przykład ilustrujący różnicę w czasie rejestracji. Oba zrzuty ekranu są robione podczas korzystania z przykładowej aplikacji w trybie incognito z wykorzystaniem ograniczania przepustowości sieci w celu symulowania powolnego połączenia.

Ruch w sieci z wcześniejszą rejestracją.

Powyższy zrzut ekranu przedstawia ruch w sieci z momentu zmodyfikowania próbki tak, aby jak najszybciej przeprowadziła rejestrację skryptu service worker. Widać żądania wyprzedzenia (obok pozycji z ikoną koła zębatego, które pochodzą z modułu obsługi install skryptu service worker), są przeplatane żądaniami innych zasobów potrzebnych do wyświetlenia strony.

Ruch w sieci z późną rejestracją.

Na zrzucie ekranu powyżej rejestracja skryptu service worker została opóźniona do czasu wczytania strony. Jak widać, żądania wstępnego buforowania rozpoczynają się dopiero wtedy, gdy wszystkie zasoby zostaną pobrane z sieci, co eliminuje rywalizację o przepustowość. Co więcej, ponieważ niektóre z wstępnie zdefiniowanych elementów znajdują się już w pamięci podręcznej HTTP przeglądarki (elementy z wartością (from disk cache) w kolumnie Rozmiar), możemy zapełnić pamięć podręczną instancji roboczej bez konieczności ponownego przechodzenia do sieci.

Otrzymasz dodatkowe punkty, jeśli uruchomisz takie testy na słabszym urządzeniu działającym w prawdziwej sieci komórkowej. Dzięki funkcji zdalnego debugowania w Chrome możesz podłączyć telefon z Androidem do komputera przez USB, by mieć pewność, że przeprowadzone testy odzwierciedlają rzeczywiste doświadczenia wielu użytkowników.

Podsumowanie

Podsumowując, najwyższym priorytetem jest dbanie o jak najlepsze wrażenia użytkowników przy pierwszej wizycie. Można to osiągnąć, opóźniając rejestrację skryptu service worker do czasu, gdy strona się wczyta podczas pierwszej wizyty. W dalszym ciągu masz dostęp do wszystkich korzyści, jakie daje korzystanie z mechanizmów Service Worker w przypadku kolejnych wizyt.

Prostym sposobem na opóźnienie wstępnej rejestracji skryptu service worker do momentu wczytania pierwszej strony jest użycie:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}