Czym są Progressive Web Apps i do czego można użyć Service Worker-ów ?

Z raportów takich jak 2016 US Mobile App (link) wynika, że już 2/3 naszej internetowej aktywności pochodzi z tabletów i smartfonów.

Każdy szanujący się portal internetowy ma dziś swoją dedykowaną aplikację mobilną. Przewagi pracy z takimi aplikacjami nad pracą bezpośrednio z przeglądarkami mobilnymi to m.in:

  • działanie w trybie pełnoekranowym (bez paska przeglądarki)
  • możliwość dodania skrótu do głównego ekranu urządzenia
  • wykorzystanie notyfikacji
  • natychmiastowy czas ładowania pierwszego ekranu
  • możliwość pracy offline (przeważnie w ograniczonym zakresie).

Badania pokazują jednak, że mnóstwo użytkowników zniechęca się przechodząc przez kolejne kroki instalacji nowych aplikacji w app storach. Według innych badań ciężko się przebić nowym markom, gdyż większość czasu użytkowników pochłaniają najpopularniejsze aplikacje.

abc

Progressive Web Applications

Pomysł na aplikacje przyszłości mocno promowany przez m.in. Google jest inny. Rozbudujmy obecne przeglądarki o kilka dodatkowych funkcjonalności tak, by zwykłe aplikacje webowe dorównywały mobilnym pod względem User Experience. Aplikacje tworzone w nowym stylu nazwano progresywnymi. Kilka najczęściej pojawiających się cech takich aplikacji:

szybkie i responsywne – wiele zależy od umiejętności programistów, frameworków, jakie używamy itd.
używające szyfrowanej komunikacji – projekt Let’s Encrypt od jakiegoś czasu umożliwia generowanie darmowych certyfikatów SSL
możliwość dodania do “home screen”
notyfikacje typu push
krótki czas ładowania

i wreszcie ostatnia czyli praca offline. Obecnie dla większości domen brak internetu skutkuje w Chrome tym:

aaa

W przypadku aplikacji progresywnych brak internetu chcemy wykryć i przełączyć użytkownika w inny tryb pracy z aplikacją. Mechanizmem, który to umożliwia jest Service Worker.

Service Workers

Idea wydaje się zgodna z intuicją. Jeśli chcemy wykrywać brak sieci zanim użytkownikowi pojawi się dinozaur, to musimy użyć czegoś działającego jak proxy pomiędzy przeglądarką a siecią. Mechanizm taki przechwytuje wszystkie żądania HTTP i potrafi odpowiednio obsłużyć niepowodzenia.

Service Worker działa podobnie do obecnego już od kilku lat w przeglądarkach Web Workera. Podobnie jak w przypadku starszego kolegi, całą logikę definiujemy w osobnym pliku .js, który nie ma bezpośredniego dostępu do drzewa DOM i jest uruchamiany z innego skryptu. Działa on w pełni asynchronicznie, a co za tym idzie nie blokuje wykonania głównego skryptu aplikacji.

Service Worker działa jak proxy, a zatem teoretycznie można go używać do zabawy w man-in-the-middle, łapiąc requesty i podmieniając ich zawartość. Aby zapobiec atakom typu “website defacement” ustalono wymóg używania SW przez HTTPS (z wyjątkiem localhosta).

W związku z tym, że SW nie są jeszcze dostępne w każdej przeglądarce (caniuse), powinniśmy je rejestrować w bezpieczny sposób: Całe API opiera się o wygodny mechanizm promise. Rejestracja workera w dowolnym pliku .js:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js', {scope: '/'}).then(function(registration) {
    console.log('Service worker registered successfully');
  }).catch(function(err) {
    console.log('Service worker registration failed: ', err);
  });
}

Sam kod service-worker.js, dla aplikacji, która przechowuje cały swój kod po stronie przeglądarki wygląda tak:

var CACHE_NAME = 'cache-v1';
var CACHED_URLS = [
  '/index.html',
  '/script.js',
  '/dog.jpg'
];

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(CACHE_NAME).then(function(cache) {
      return cache.addAll(CACHED_URLS);
    })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    fetch(event.request).catch(function() {
      return caches.match(event.request).then(function(response) {
        if (response) {
          return response;
        } else if (event.request.headers.get('accept').includes('text/html')) {
          return caches.match('/index.html'); //obsługa wejścia pod rootowy adres domeny
        }
      });
    })
  );
});

Nasłuchujemy na dwa zdarzenia. Pierwsze wejście na stronę odbywa się w trybie online, dlatego na zdarzeniu install zapisujemy wszystkie statyczne pliki z listy wykorzystując CacheStorage API. Każdy cache może mieć swoją nazwę, grupującą logicznie zasoby. Zawartość CacheStorage można podejrzeć w Chrome Dev Toolsach:

awww

Nasłuchując na zdarzeniu fetch otrzymujemy kontrolę nad tym, jakie odpowiedzi zostaną zwrócone do naszej aplikacji.Przykład powyżej obsługuje tylko niepowodzenia (catch).

Co dalej ? Możliwości jest sporo. Service Workera można wykorzystać do przyspieszenia ładowania statycznych plików w trybie online (serwując je natychmiastowo z cache). Idąc dalej, jeżeli pobieramy dane za pomocą zapytań AJAX-owych, to możemy również cache’ować wyniki takich zapytań i wyświetlać je kiedy użytkownik jest offline.

Warto pamiętać o tym, że plik workera jest asynchroniczny, a więc mamy w nim dostęp tylko do asynchronicznych API. Nie możemy w związku z tym przechowywać danych w synchronicznym localStorage, ale mamy do dyspozycji np. IndexedDB udostępniający asynchroniczne (choć dość skomplikowane) API.

Lighthouse

Ekipa z Google udostępniła narzędzie Lighthouse, pomagające developerom w dostosowywaniu aplikacji Webowych do bycia progresywnymi. Można go zainstalować jako rozszerzenie Chrome lub pakiet npm-a.

abv

Po wejściu na stronę, która nas interesuje możemy wygenerować raport wraz z punktacją i sugestiami, co powinniśmy poprawić.

abb

Mój blog na wordpress otrzymał 47 na 100 punktów, między innymi przez … brak zainstalowanych Service Workerków.

One thought on “Czym są Progressive Web Apps i do czego można użyć Service Worker-ów ?

  1. Wszystko było by pięknie gdyby nie to, że Service Workers to na razie draft W3C i zanim stanie się częścią oficjalnej specyfikacji to mogą minąć lata. Poza tym jak na razie service workers są dostępny w ograniczonej ilości przeglądarek i co najważniejsze, jeżeli chodzi o webkit – to jak na razie nie ma planów implementacji – mamy więc rozwiązanie które może nigdy nie zostać zaimplementowane na jednej z najpopularniejszych platform mobilnych: iOS.
    http://caniuse.com/#feat=serviceworkers

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s