Progressive Web Apps – wprowadzenie do aplikacji progresywnych

Progressive web apps

Wprowadzenie do aplikacji progresywnych

Progressive Web Apps (PWA) to rozwiązanie pozwalające na zainstalowanie aplikacji webowej na ekranie głównym smartfona bez konieczności korzystania ze sklepu z aplikacjami (np. App Store). Tego typu aplikacje wyglądają i działają podobnie do natywnych aplikacji mobilnych, posiadają jednak ograniczenia wynikające z tego że ich środowiskiem uruchomieniowym jest przeglądarka internetowa.

Termin Progressive Web Apps został wymyślony przez Frances Berrimana i Alexa Russella inżyniera odpowiedzialnego za Google Chrome. Mianem progresywnej aplikacji webowej określili oni w 2015 roku stronę internetową, która używa nowych funkcjonalności wprowadzonych do przeglądarek internetowych. Mowa tutaj między innymi o Service Workerach i Web App Manifest.

PWA opiera się na trzech podstawowych założeniach:

  1. solidność – strona ładuje się niemal natychmiastowo i działa nawet w przypadku braku połączenia z internetem,
  2. szybkość – strona reaguje błyskawicznie na interakcję z użytkownikiem,
  3. wrażenie „natywności” – strona daje pełne wrażenie pracy z aplikacją natywną, do tego stopnia że można ją zainstalować a jej ikona będzie pokazywana w ten sam sposób na ekranie telefonu co aplikacji natywnych. Ponadto po otwarciu strona pracuje w trybie pełnoekranowym i umożliwia wysyłanie notyfikacji „push”.

Aby móc spełnić powyższe założenia konieczna jest implementacja dwóch nowych funkcjonalności.

Service Worker

Service Worker (SW) jest skryptem uruchomionym w tle i działa niezależnie od skryptów zamieszczonych na stronie. Jego działanie podobne jest do serwera proxy. Przechwytuje on zapytania wysyłane z aplikacji do serwera, potrafi zapisać je w pamięci cache, synchronizuje stan aplikacji ze stanem serwera i wysyła użytkownikowi powiadomienia push.

W przypadku braku połączenia z internetem, dzięki treściom zapisanym w pamięci cache nadal będziemy w stanie prezentować zawartość strony.

Zasada działania Servce Workera
Zasada działania Service Workera

Przejdźmy zatem do przykładowej implementacji Service Workera.

Rejestracja Service Workera w Progressive Web Apps

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw-test/sw.js', {scope: '/sw-test/'})
  .then(function(reg) {
    // registration worked
    console.log('Registration succeeded. Scope is ' + reg.scope);
  }).catch(function(error) {
    // registration failed
    console.log('Registration failed with ' + error);
  });
}

Pierwsza linia kodu sprawdza czy Service Worker jest wspierany przez przeglądarkę. Następnie rejestrujemy nasz Service Worker za pomocą ServiceWorkerContainer.register(). Parametr scope jest opcjonalny i używamy go do wskazania zakresu, kontrolowanego przez Service Worker’a.

Aktywacja cache

Aby nasza aplikacja była dostępna w trybie offline, musimy skorzystać z Cache API i wskazać, które elementy strony chcemy przechowywać w cache.

W naszym pliku sw.js dokonujemy następującego wpisu:

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('v1').then(function(cache) {
      return cache.addAll([
        '/sw-test/',
        '/sw-test/index.html',
        '/sw-test/style.css',
        '/sw-test/app.js',
        '/sw-test/image-list.js',
        '/sw-test/star-wars-logo.jpg',
        '/sw-test/gallery/',
        '/sw-test/gallery/bountyHunters.jpg',
        '/sw-test/gallery/myLittleVader.jpg',
        '/sw-test/gallery/snowTroopers.jpg'
      ]);
    })
  );
});

Dodajemy install event listener i dołączamy metodę ExtendableEvent.waitUntil(). Dzięki temu mamy pewność że Service Worker nie dokona instalacji dopóki kod zawarty w waitUntil() nie zakończy działania. Wewnątrz waitUntil() używamy metody caches.open() do stworzenia nowego cache’a o nazwie v1 i za pomocą addAll() dodajemy relatywne URL do naszych zasobów.

Teraz aby móc korzystać z scachowanych zasobów musimy jeszcze zwrócić je do lokalnego cache’a. W tym celu dodamy event listenter na zdarzenie fetch.

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request);
    })
  );
});

W powyższym przypadku sprawdzamy czy zapytanie wysyłane do serwera nie znajduje się w naszym cache’u, jeśli tak jest, to zwrócimy scachowaną odpowiedź.

Dobrze by było, aby w przypadku pojawienia się na serwerze nowych zasobów, były one w momencie połączenia dodawane do naszego cache’a. W tym celu możemy posłużyć się następującym przykładem.

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(resp) {
      return resp || fetch(event.request).then(function(response) {
        return caches.open('v1').then(function(cache) {
          cache.put(event.request, response.clone());
          return response;
        });  
      });
    })
  );
});

W powyższym przykładzie return fetch(event.request) zwróci promise, gdy zostanie on spełniony metoda caches.open(„v1”) także zwróci promise i skoleji gdy on zostanie spełniony użyjemy metody cache.put() aby dodać zasoby do cache’a. Zasoby w tym przypadku są brane z event.request odpowiedź jest natomiast klonowana i zapisana do cache’a. Oryginalna odpowiedź zostaje zwrócona do przeglądarki.

Klonowanie odpowiedzi jest konieczne ponieważ żądanie (request) i odpowiedź (response) mogą być odczytywane tylko raz. Aby zachować odpowiedź oraz zwrócić ją do przeglądarki należy ją sklonować.

Powyższy przykład Service Workera jest jednym z prostszych. Jeśli chcesz bardziej rozbudować swój SW polecam zapoznać się z dokumentacją na stronie Using Service Workers lub użyć generatora Service Workerów.

Jeśli z jakiś przyczyn Twój Service Worker nie działa, sprawdź czy obsługa Service Workerów jest włączona w Twojej przeglądarce.

Firefox: Przejdź do about:config i ustaw dom.serviceWorkers.enabled na true.
Chrome: Przejdź do chrome://flags i włącz experimental-web-platform-feature.
Opera: Przejdź do opera://flags i włącz Support for ServiceWorker.
Microsoft Edge: Przejdź do about://flags i zaznacz Enable service workers.

Web App Manifest

Kolejną funkcjonalnością do zaimplementowania jest Web App Manifest. Jest to zwykły plik w formacie JSON opisujący podstawowe elementy aplikacji, które wykorzystane zostaną do instalacji naszej aplikacji na ekranie głównym telefonu użytkownika. W manifeście deklarujemy nazwę aplikacji, ikony, sposób wyświetlania aplikacji i wiele innych.

Poniżej zamieszczono przykładowy manifest.

{
  "name": "Start Wars App",
  "short_name": "Star Wars",
  "start_url": ".",
  "display": "standalone",
  "background_color": "#000",
  "description": "A simply Star Wars App",
  "icons": [{
    "src": "images/touch/homescreen48.png",
    "sizes": "48x48",
    "type": "image/png"
  }, {
    "src": "images/touch/homescreen72.png",
    "sizes": "72x72",
    "type": "image/png"
  }, {
    "src": "images/touch/homescreen96.png",
    "sizes": "96x96",
    "type": "image/png"
  },  {
    "src": "images/touch/homescreen168.png",
    "sizes": "168x168",
    "type": "image/png"
  }, {
    "src": "images/touch/homescreen192.png",
    "sizes": "192x192",
    "type": "image/png"
  }]
}

Powyższy manifest osadzamy na stronie HTML używając taga link:

<link rel="manifest" href="/manifest.webmanifest">

Szczegółowe informacje odnośnie poszczególnych elementów manifestu można znaleźć w dokumentacji.

Aby strona internetowa była w pełni uznana za PWA nie wystarczy tylko implementacja manifestu oraz Service Workerów. Google przygotowało szczegółową checklistę definiującą wymagania stawiane stroną aspirującym do miana PWA.

  • Strona PWA musi być obsługiwana poprzez protokół HTTPS. Odpowiedni certyfikat można wykupić u dostawcy hostingowego lub skorzystać z darmowego certyfikatu letsencrypt.org.
  • Strony muszą być responsywne i dobrze się prezentować na urządzeniach mobilnych. Tutaj z pomocą mogą nam przyjść dedykowane narzędzia do sprawdzania responsywności stron np. Test Mobile Friendly.
  • Wszystkie URLe powinny być dostępne nawet w przypadku braku połączenia internetowego. W tym celu używamy wcześniej opisanego Service Workera.
  • Strona musi posiadać zaimplementowany Web App Manifest.

Checklista jest o wiele dłuższa a pełną jej wersję można znaleźć tutaj.

Lighthouse

Jeśli chcesz sprawdzić na ile Twoja obecna strona spełnia wyżej wymienione wymagania użyj narzędzia Lighthouse.

Lighthouse to narzędzie do generowania raportu o stanie kompatybilności z PWA. Dla strony devenv.pl która nie była tworzona z myślą o PWA raport ten przedstawia się następująco.

Audyt strony devenv.pl za pomocą Lighthouse

Podsumowanie

Progressive Web Apps to ciekawy kierunek rozwoju stron internetowych. Programiści na pewno docenią łatwość wdrożenia aplikacji na wszystkie platformy. Dotychczasowe rozwiązania takie jak Cordova czy Ionic również wspierały multiplatformowość ale tworzone za ich pomocą aplikację można było uruchamiać tylko na urządzeniach mobilnych. Niewątpliwą zaletą aplikacji progresywnych są aktualizacje. Gdy chcemy zaktualizować aplikację mobilną najczęściej oprócz przygotowania kodu aktualizacji, musimy ją zgłosić do App Store, przejść review a następnie użytkownik telefonu po otrzymaniu notyfikacji o aktualizacji musi wyrazić zgodę na jej instalację. W przypadku PWA wgrywamy nowe pliki na serwer a aplikacja zostanie zaktualizowana przy kolejnej wizycie użytkownika.

PWA ma również swoje ograniczenia. Progressive Web Apps nie są w stanie w pełni zastąpić aplikacji natywnych ponieważ nie mają dostępu do danych na telefonie użytkownika, to znaczy, do naszego numeru telefonu, książki kontaktów, kalendarza i innych. Także PWA nie będzie w stanie skorzystać ze wszystkich modułów telefonu tj, modułu komunikacji NFC lub Bluetooth.

Ponadto należy też wspomnieć o braku wsparcia dla PWA w systemie iOS. Safari nie obsługuje Service Workerów oraz nie pozwala na obsługę notyfikacji „push”.

Safari brak wsparcia dla Service Workerów

Główne obszary zastosowań PWA

Progressive Web Apps sprawdzi się świetnie wszędzie tam gdzie głównym elementem aplikacji jest konsumpcja treści dostarczonej z zewnątrz a sama aplikacja nie wymaga obsługi niedostępnych dla przeglądarki funkcji urządzeń mobilnych.

PWA będzie świetnym rozwiązaniem dla sklepów internetowych, tutaj za przykład może posłużyć serwis Alibaba, który po wprowadzeniu aplikacji progresywnej zwiększył wskaźnik celów konwersji o 76% a ilość aktywnych użytkowników wzrosła o 14% na iOS i 30% na Androidzie. Link do casestudy.

Aplikacja progresywna to bardzo dobre rozwiązanie dla różnego rodzaju wydawnictw internetowych. Washington Post i Forbes zanotowały duży wzrost prędkości ładowania treści przechodząc na PWA w stosunku do tradycyjnej strony mobilnej.

Wiele raportów z wdrożenia Progressive Web Apps jest dostępnych w sieci, jeśli chcesz zgłębić temat polecam kilka z nich.

Z zawodu i zamiłowania programista. Jara mnie wszystko, co potrafi zmienić nieciekawy input w ciekawy output, czyli m.in. programowanie, gotowanie, muzyka i fotografia.
PODZIEL SIĘ

4 KOMENTARZE

  1. Cześć! Bardzo dobry, inspirujący artykuł. Nie ukrywam jednak , że przeżyłem spore rozczarowanie, gdy pod koniec wpisu dowiedziałem się o braku wsparcia dla PWA na iOS. Tym bardziej, że już w pierwszym zdaniu wspominasz o App Store, czyli sklep na iOS. Tak czy inaczej, wielkie dzięki za to wprowadzenie. Pozdrawiam!

Comments are closed.