Nasza strona używa cookies. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Jak zacząć z PWA?

Kamil Rogala Programista Front-end / Agora SA
Dowiedz się, czym jest Progressive Web App oraz jak w prosty sposób zacząć pracę z PWA.
Jak zacząć z PWA?

Progressive Web Apps, zwane skrótowo PWA, zyskują na popularności i coraz więcej stron oraz aplikacji internetowych wprowadza elementy PWA do siebie. W tym artykule dowiesz się czym są progresywne aplikacje internetowe, jak w prosty sposób zacząć pracę z nimi oraz jakie możliwości otwierają przed Tobą techniki powiązane z PWA.


PWA - co to za dziwny twór?

Na wstępie określmy czym są Progressive Web Apps. Tak jak wcześniej napisałem- jest to specyficzny typ strony/aplikacji internetowej, która może (ale nie musi) imitować zachowanie natywnej aplikacji mobilnej, przy jednocześnie zapewnieniu odpowiedniej obsługi naszej aplikacji bądź strony w trybie offline.

Gdy wejdziemy na naszym urządzeniu mobilnym na stronę internetową, która jest PWA to dostaniemy propozycję umieszczenia wygodnego skrótu na pulpicie.

Co ważne, my sami jako developerzy, decydujemy jak bardzo nasza aplikacja ma się rozwijać w kierunku offline, w kierunku imitacji aplikacji natywnej czy możliwości dodatkowych dla samego PWA- stąd też nazwa „progresywne aplikacje internetowe”, gdyż możemy stale je rozwijać.

Co ważne - samo PWA nie oznacza pisanie strony od zera w jakiejś technologii czy rezygnacji z naszego ulubionego frameworka- to dodatkowa możliwość, tak jak np. zastosowanie media queries (sprawdź TUTAJ). Oznacza to, że wdrożyć możemy PWA zarówno na nowe strony, jak i na te, które istnieją już od dłuższego czasu

Warto wspomnieć, że sam termin PWA powstał w 2015 roku i został przedstawiony przez dwójkę ludzi- byli nimi developer Alex Russel oraz designer Frances Berriman (w TYM artykule), jednak za „ojca” idei PWA wielu (w tym i ja) uważa się... Steve'a Jobs'a! Jeśli Cię zaciekawiłem to tutaj znajdziesz nagranie z 11 czerwca 2007 roku, gdzie Steve mówi o czymś co łudząco przypomina to co dziś znamy pod mianem PWA.


Czego potrzebujemy do pracy?

Najprościej jak się da: potrzebujemy naszej strony internetowej (wraz z dostępem do jej kodu oraz FTP), edytora tekstowego (nada się naprawdę każdy, choć zalecałbym edytor z podświetlaniem składni- osobiście korzystam z Visual Studio Code) oraz przynajmniej podstawowej znajomości języka Javascript.


Wymagania dla PWA

By nasza strona internetowa kwalifikowała się do miana PWA musi spełnić kilka wymogów:

  1. Połączenie ze stroną musi być bezpieczne tj. szyfrowane. Oznacza to że nasza domena musi posiadać certyfikat SSL. Więcej informacji o tym znajdziesz tutaj.
  2. Strona musi być responsywna, czyli dostosowana do urządzeń mobilnych. PWA są skierowane głównie do urządzeń mobilnych (aczkolwiek w niedługim czasie powinniśmy się spodziewać wsparcia także dla urządzeń desktop'owych) i co za tym idzie, musimy zapewnić dla nich wsparcie. Tutaj możesz dowiedzieć się na ten temat więcej. 
  3. Musimy podpiąć do naszej strony plik manifestu. Jest to plik zawierający informacje dotyczące naszej aplikacji PWA, sposobu otwierania, ikony aplikacji itd.
  4. Musimy posiadać tzw. service worker. W skrócie jest to plik Javascript, który zawiera w sobie logikę dotyczącą wsparcia PWA przy stanie offline oraz zachowania związane z pamięcią podręczną oraz stanem online. Uwaga, service worker zadziała jedynie jeśli posiadasz certyfikat SSL podpięty pod domenę lub testujesz swoją witrynę na localhost!
  5. Dodać odpowiedni wpis meta:theme-color w sekcji head naszej strony
  6. W narzędziu Google Lighthouse musimy osiągnąć wynik przynajmniej 75% procent. W tym punkcie znajduje się więcej kruczków jak np. odpowiednie ikony, prędkość ładowania się strony itd. Z mojego doświadczenia mogę powiedzieć, że większość stron spełnia „z automatu” praktycznie wszystkie z tych punktów i z samym PWA nie powinno być problemów. Jednak gdyby Lighthouse wykrył nam jakieś niedociągnięcia to w miarę prosto możemy poprawić błędy, gdyż wszelkie uwagi są dobrze opisane.


Uwagi przed startem

Zakładam, że Twoja strona jest gotowa pod kątem responsywności oraz Twoja domena posiada certyfikat bezpieczeństwa. Jeśli nie spełniasz obu tych warunków- popraw je jak najszybciej, gdyż są one nieodzowne by Twoja strona zamieniła się w PWA. Reszta punktów jest całkowicie nieważna pod względem Progressive Web App, jeśli nie spełnisz tych dwóch podstawowych wymagań.


Tag meta:theme-color

Pierwszą rzeczą jaką zrobimy będzie dodanie motywu kolorystycznego do naszej strony, a dokładniej do UI mobilnej przeglądarki.

Zapewne nie raz rzuciło Ci się w oczy, że wchodzisz witrynę na Bulldogjob i nagle Twoja przeglądarka zyskuje przyjemny ciemny pasek nawigacyjny:

To zasługa jednego meta tagu. Możesz go zastosować nawet jeśli jeszcze nie myślisz o PWA- zadziała.

Dodanie koloru oznacza dodanie... 1 linijki w kodzie:
<meta name="theme-color" content="KOLOR">

gdzie KOLOR jest kolorem w notacji HEX. Tak wygląda on dla mojej strony:
<meta name="theme-color" content="#016188">

Tag ten dodajemy w sekcji head naszego dokumentu (lub dokumentów) HTML.

To tylko jedna linijka, a nasza strona zyska naprawdę fajny feature!


Manifest

Plik manifestu, tak jak wspomniałem wcześniej, to plik z rozszerzeniem .json zawierający informacje dotyczący naszej PWA. Możemy umieścić tu m.in. nazwę aplikacji, linki do ikon, sposób otwierania naszej aplikacji, informacje o języku, kolor tzw. splash screena, powiązane aplikacje i mnóstwo innych rzeczy.

Skupmy się jednak na podstawowej wersji pliku manifest.json, dzięki której postawimy pierwsze kroki na drodze ku PWA. Poniższe pola to absolutne minimum:

{
  "name": "",
  "short_name": "",
  "icons": [
    {
      "src":"",
      "sizes": "",
      "type": ""
    }
  ],
  "start_url": "",
  "background_color": "",
  "theme_color": "",
  "display": ""
}


Powyżej widzisz podstawowy „szablon” dla naszego pliku, zaś niżej w artykule będzie możliwość podglądu uzupełnionego pliku manifest.json.

Na wstępie jednak objaśnijmy sobie czym są poszczególne elementy.

Pierwsza właściwość name to nazwa naszej aplikacji. Jest ona domyślnie używaną właściwością do popup’ów i komunikatów zawierających odwołania do naszej aplikacji.

Drugą właściwością jest short_name to skrócona nazwa naszej aplikacji i posiada rolę wspomagającą - gdy name się nie mieści w komunikatach to używana jest wartość short_name. Miejmy to zatem na uwadze - warto tak dobrać te 2 wartości by się nie dublowały, a raczej jedna dopełniała drugą.

Kolejna właściwość to icons i zawiera informacje o ikonach dostępnych dla naszej aplikacji. Każdy wpis zawiera w sobie dane dotyczące adresu do ikony, jej rozszerzenia oraz wielkości - urządzenie mobilne samo dobiera sobie odpowiednią wielkość z podanego przez nas zestawu. 

Rozszerzenie jest dowolne - obsługiwane są wszystkie typy MIME dla obrazków, więc możemy tu wymienić np. image/gif, image/jpg, image/png, image/svg+xml, image/webp i inne.

Niestety nie ma jasno sprecyzowanego zakresu wielkości naszych ikon, gdyż PWA mogą być dostosowane tak naprawdę do każdej wielkości ekranu - tutaj zostawiona jest decyzja developerowi. Dla celów demonstracyjnych zastosuję taki zakres: 16x16, 32x32, 48x48, 72x72, 76x76, 96x96, 120x120, 144x144, 152x152, 180x180, 192x192, 512x512. Dzięki temu jestem pewny, że praktycznie każde urządzenie da sobie radę z pobraniem miniatury.

Warto dodać, że nie musimy stosować wszędzie takiego samego rozszerzenia. Możemy użyć np. .ico dla wielkości 16x16 co ma znacznie więcej sensu niż ładowanie znacznie cięższego .png .

A co z sytuacją, gdy podamy kilka tych samych wielkości, ale do różnych plików np. mamy, powiedzmy, trzy razy wymieniony 16x16 i jeden ma rozszerzenie .ico, drugi .png, a trzeci .jpg? To proste - jest brany pod uwagę ten pierwszy.

Co się stanie, gdy te rozszerzenie nie jest obsługiwane w danej przeglądarce (np. .webp)? Brany pod uwagę jest kolejny zasób dla tej konkretnej wielkości - można w ten wygodny sposób zapewnić fallback dla niektórych kłopotliwych rozszerzeń.

Jest jeszcze jedna ciekawa sprawa, która znacznie ułatwia pracę z ikonami - możemy grupować wielkości. Wystarczy w sizes podać kolejne zakresy, oddzielone spacją.

Zarówno nazwę jak i ikony zobaczymy podczas procesu „instalacji” jak i na liście naszych aplikacji w telefonie.

Wykorzystanie short_name

Wykorzystanie name

Wykorzystanie short_name oraz icons

Następna właściwość, start_url jest bardzo użyteczna - to adres pod jakim ma startować aplikacja, co za tym idzie po podłączeniu narzędzia zbierającego statystyki (np. Google Analytics) wiemy dokładnie, ile osób korzysta na co dzień z naszej PWA, a ile z natywnej strony internetowej. Jeśli nie potrzebujesz statystyk to możesz wstawić adres URL swojej strony lub wartość / mówiącą „zacznij od strony startowej”.

Kolejne 2 właściwości theme_color oraz background_color odnoszą się do kolorów naszej aplikacji. Pierwsza jest używana do elementów toolbara i jej wartość powinna być taka sama jak wartość tagu meta:theme-color. Druga właściwość to tło splash screenu, czyli ekranu powitalnego naszej aplikacji.

Wykorzystanie name, icons, theme_color oraz background_color

Końcową właściwością jest display, która określa typ wyświetlania naszej aplikacji. Może ona przyjąć następujące właściwości: fullscreen, standalone, minimal-ui, browser. Każda z nich da inne doświadczenie użytkownikowi końcowemu.

Gdy ustawimy wartość na fullscreen, to nasza aplikacja zajmie cały nasz ekran, włącznie z toolbarem czy przyciskami pomocniczymi na komórce, sprawiając wrażenie, że jest to natywna aplikacja mobilna - bardzo przydatna opcja dla np. gier. Jeśli opcja ta nie jest z jakichś względów dostępna, to automatycznie używany jest fallback w postaci wartości standalone.

Sama aplikacja standalone świetnie imituje aplikację natywną, i jest bardzo podobna w działaniu jak fullscreen, z tą różnicą że zyskuje elementy UI naszego urządzenia mobilnego jak np. toolbar czy przyciski pomocnicze - polecam tę opcję dla standardowych stron internetowych, które chcą się stać PWA. Fallbackiem jest tutaj minimal-ui.

Jeśli chcemy udostępnić użytkownikowi jeszcze więcej elementów UI, to opcja minimal-ui będzie tutaj dosyć pomocna - w zależności od urządzenia i domyślnej przeglądarki, mogą się pojawić przyciski „do przodu”, „do tyłu”, „odśwież”, a nawet opcja drukowania czy udostępniania. Ta właściwość także ma swój fallback, jakim jest browser.

Wartość browser sprawi, że nasza aplikacja otworzy się w domyślnej przeglądarce użytkownika, zatem nasze PWA jest w odczuciu bardziej skrótem internetowym niż samodzielną aplikacją. Opcja ta nie posiada fallbacku.

Wykorzystanie theme_color oraz display

A oto uzupełniony manifest.json o dane, które możesz powyżej zauważyć na screenach:

{
    "name": "Kamil Rogala- Front-end Developer.",
    "short_name": "Kamil Rogala",
    "icons": [
        {
            "src": "/templates/intro/app/16.ico",
            "type": "image/ico",
            "sizes": "16x16"
        },
        {
            "src": "/templates/intro/app/32.ico",
            "type": "image/ico",
            "sizes": "32x32"
        },
        {
            "src": "/templates/intro/app/48.png",
            "type": "image/png",
            "sizes": "48x48"
        },
        {
            "src": "/templates/intro/app/72.png",
            "type": "image/png",
            "sizes": "72x72"
        },
        {
            "src": "/templates/intro/app/76.png",
            "type": "image/png",
            "sizes": "76x76"
        },
        {
            "src": "/templates/intro/app/96.webp",
            "type": "image/webp",
            "sizes": "96x96"
        },
        {
            "src": "/templates/intro/app/96.png",
            "type": "image/png",
            "sizes": "96x96"
        },
        {
            "src": "/templates/intro/app/hi_res.svg",
            "type": "image/svg+xml",
            "sizes": "120x120 144x144 152x152 180x180 192x192 512x512"
        }
    ],
    "start_url": "/?utm_source=app",
    "theme_color": "#016188",
    "background_color": "#eeeeee",
    "display": "standalone"
}


Teraz zostają nam dwie rzeczy: wrzucić nasz plik manifest.json na FTP oraz odpowiednio umieścić go w kodzie HTML naszej strony, a dokładniej w sekcji head:
<link rel="manifest" href="/manifest.json">

Mała podpowiedź - warto wersjonować swój plik manifest.json, tak, by w razie zmian łatwo wymusić od przeglądarki wczytanie najnowszej wersji naszego PWA. To proste:
<link rel="manifest" href="/manifest.json?v=1.0.0">

Gdy coś edytujemy wystarczy podnieść numer wersji, by większość przeglądarek wczytała najnowsze zmiany w pliku. Sztuczka ta działa także z innymi plikami, warto więc ją zapamiętać.


Obsługa online i offline- service worker

Nasza strona powoli staje się PWA. Pozostaje nam jeszcze ustalić jak ma się zachowywać w stanie online i/lub offline, a do określenia tego służy mechanizm o nazwie service worker - jest to skrypt napisany w JavaScript.

Jest wiele strategii dotyczących tego co ma zrobić ten mechanizm gdy użytkownik jest online oraz co ma zrobić gdy jest offline i nie będę się tutaj skupiał na omówieniu ich wszystkich - to już kwestia osobnego artykułu, gdyż temat jest naprawdę obszerny. Mogę tylko wspomnieć, że jest 8 strategii omówionych przez Google, ale developerzy sami dostosowują te mechanizmy pod swoje strony z wykorzystaniem np. Network Information API do mierzenia prędkości łącza. 

Przy pierwszym wejściu na stronę cykl życia service workera rozpoczyna się od jego instalacji (dzieje się to w tle), a następnie staje się on aktywny. 

Od tej pory będzie on działał w danej przeglądarce użytkownika niezmiennie dopóki go nie zdezaktywujemy (lub użytkownik tego nie zrobi) lub gdy „nie nakażemy” mu się zaktualizować.


Jak wygląda przykładowy service worker?

Strategia, którą Wam pokażę zwie się „Network falling back to cache”. W skrócie - podczas ładowania strony service worker sprawdza czy użytkownik ma dostęp do internetu. Jeśli tak - zasoby ładują się normalnie z Internetu, a dodatkowo trafiają do cache. Jeśli nie - service worker spróbuje wczytać zasoby z cache. Dopiero w przypadku braku plików w cache oraz braku internetu, użytkownik zobaczy stronę błędu. To od nas zależeć będzie, czy będzie to domyślna strona błędu czy strona, którą sami stworzymy.


źródło

Powyższa strategia polecana jest dla serwisów z dużą ilością artykułów, szczególnie z bardzo dynamicznie zmieniającymi się zasobami.

Rozpoczynamy od stworzenia pliku service-worker.js, a następnie piszemy w nim trochę kodu:

// nazywamy nasze cache- w zmiennej będzie wygodniej
const MY_CACHE = 'cache-name';
// w tej tablicy lądują wszystkie pliki, które chcemy dodać do cache
const MY_FILES = [
        '/css/file.css',
        '/css/images/file.png',
        '/css/fonts/file.woff',
        '/js/file.js'
];

// instalujemy nasz service worker
self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(MY_CACHE).then(function(cache) {
      return cache.addAll(MY_FILES);
    })
  );
});
// po aktywacji chcę skasować wszystkie cache w naszej domenie, które nie są naszym cache (to opcjonalne)
self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.filter(function(cacheName) {
          return cacheName !== MY_CACHE;
        }).map(function(cacheName) {
          return caches.delete(cacheName);
        })
      );
    })
  );
});
// strategia 'Network falling back to cache'
self.addEventListener('fetch', function(event) {
  event.respondWith(
    fetch(event.request).catch(function() {
      return caches.match(event.request);
    })
  );
});


Pozostaje nam jedno - odpowiednio podłączyć nasz nowy skrypt do strony.

W tym celu udajemy się do naszego pliku HTML i tuż przed zamykającym tagiem body umieszczamy nasz kod:

<script>
// sprawdzamy czy przeglądarka posiada wsparcie dla service workera
if ('serviceWorker' in navigator) {
    // próba instalacji
    navigator.serviceWorker.register('/service-worker.js').then(function () {
        console.log('Service worker zainstalowany');
    }).catch(function (err) {
        // jeśli coś pójdzie nie tak- konsola nam powie co trzeba poprawić
        console.log('Service worker nie zainstalowany, sprawdź błąd:', err)
    });
}
</script>


Jeśli boisz się, że Twój service worker nie zadziała, możesz spróbować gotowych rozwiązań takich jak np. TO.


PWA we frameworkach i bibliotekach JS

PWA sprawdzi się świetnie przy wszelkiej maści aplikacjach napisanych z użyciem Javascript, a także frameworków czy bibliotek.

Framework Angular oferuje nam taką możliwość- podczas tworzenia aplikacji dodajemy parametr --service-worker:

ng new my-app --service-worker
cd my-app
ng add @angular/pwa


Dodatkowo musimy utworzyć plik manifest.json, podłączyć go w plikach HTML oraz w angular.json.

Biblioteka Vue.js - już podczas samego tworzenia aplikacji z wykorzystaniem vue-cli można zaznaczyć opcję tworzenia PWA. Wszystko jest tworzone w locie, a już gotowe service worker (w katalogu src) i manifest.json (w katalogu public) edytujemy w miarę naszych potrzeb.

Biblioteka React jest jeszcze szybsza - wystarczy użyć standardowego create-react-app by „z automatu” otrzymać manifest.json (w katalogu public) oraz service-worker (w katalogu src).

PWA + JS FRAMEWORK = ♥


Podsumowanie

Dla mnie osobiście PWA to obecnie coś więcej, niż sam typ aplikacji. To bardziej idea przewodnia przy tworzeniu stron oraz dostarczanie nowych wartości dla użytkownika końcowego. To następstwo rozwoju Internetu - kiedyś zwykłe tworzenie stron ewoluowało w Responsive Web Design, dziś z kolei naturalnie przechodzi w Progressive Web Apps. Kiedyś wychodziliśmy z desktopu w stronę mobilności - dziś zmierzamy w stronę supportu stanu offline.

Trend ten będzie się utrzymywał, w to nie wątpię - wątpię tylko, czy za kilka lat będziemy używać terminu PWA jako coś niesamowicie odmiennego, gdyż stanie się to takim standardem jak dziś RWD. Gorąco zachęcam do przyjrzenia się temu tematowi bliżej oraz o namówienie innych osób do codziennego pochylania się nad progresywnością doświadczeń w aplikacjach webowych.

Lubisz dzielić się wiedzą i chcesz zostać autorem?

Podziel się wiedzą z 160 tysiącami naszych czytelników

Dowiedz się więcej