:sparkles: PWA :sparkles:
Twarz autora bloga

Piotr Kowalski

Organizator WarsawJS Trener YouTuber

Jak przerobić stronę na Progressive Web App?

Kilka dni temu postanowiłem, że spróbuję przerobić tego bloga na aplikacje typu PWA (Progressive Web App). Chciałbym w tym artykule opowiedzieć Ci co to jest za typ aplikacji, opisać jego wady i zalety oraz przedstawić Ci jaką drogę przeszedłem, aby ten blog stał się właśnie taką aplikacją.

Nieoficjalne logo PWA
Nieoficjalne logo Progressive Web Apps

Co to jest PWA?

Aplikacja typu PWA charakteryzuje się tym, że spełnia zasady dostępności oraz bezpieczeństwa oraz cechuje się takimi głównymi warunkami:

  1. Wykorzystywanie protokółu HTTPS
  2. Serwowanie treści bez połączenia do sieci, tzw. obsługa trybu Offline

    Wskazówka

    Aby mieć “co” wyświetlać w trybie offline, trzeba na początku “to” mieć, dlatego też aplikacja musiała być wcześniej uruchomiona normalnie, aby pobrać treść.

  3. Dostosowanie się do szerokości urządzenia, tj. obsługa responsywności

Pełna checklista

Aby zakwalifikować aplikację jako PWA, musi ona spełnić większość punktów z checklisty. Poprzez większość, mam na myśli spełnienie warunków na poziomie 75%. Liczba ta, zdefiniowana jest w specyfikacji narzędzia Lighthouse.

Lighthouse

Lighthouse to narzędzie stworzone przez Google przeznaczone do audytu strony internetowej, sprawdzając kilkadziesiąt warunków które musi ona spełniać aby być zakwalifikowana jako aplikacja PWA.

Kategorie audytu:

  • “Good” - Wynik zawiera się w przedziale 75-100
  • “Average” - Wynik zawiera się w przedziale 45-74
  • “Poor” - Wynik poniżej < 45

Przykładowe aplikacje

Lista przykładowych aplikacji PWA znajduje się tutaj. Na szczególne wyróżnienie zasługują:

Wskazówka

Jak przerobisz swoją stronę na PWA to możesz zgłosić ją do tej listy tworząc Pull Request w tym projekcie.

Zaczynamy!

Dobra, dosyć tej teorii!
Zacznijmy wreszcie przerabiać stronę internetową na aplikację PWA!


Wynik audytu mojego bloga przed zmianami wygląda następująco. Nie jest źle, ale nie można powiedzieć, że strona w takim stanie jest aplikacją typu PWA.

Lighthouse: 50/100
Tak wygląda wynik pracy Lighthouse bez żadnych modyfikacji bloga.

Krok 1. Instalacja wtyczki Lighthouse

Korzystając z Google Chrome zainstaluj wtyczkę Lighthouse.
Możesz to zrobić na 2 sposoby:

Rekomenduję pierwszy sposób z uwagi na to, że na stronie domowej tego narzędzia jest o nim wiele ciekawych informacji.

Krok 2. Zapoznanie się z przewodnikiem

Google jako autorzy pomysłu aplikacji PWA przygotowali pewnego rodzaju zadanie - przewodnik, które pokazuje jak krok po kroku dodać do prościutkiej aplikacji podstawowe elementy tak, aby stała się ona Progressive Web App.

Zanim zabierzesz się za modyfikacje swojej aplikacji spróbuj przejść przez ten przewodnik. Masz na to 30 minut. Czas start!

Krok 3. Dodanie manifest-u

Kolejne kroki opierają się na modyfikacji kodu źródłowego aplikacji.

Krok 3.1. Stworzenie pliku /manifest.json

Pierwszą rzeczą jaką trzeba dodać do projektu jest manifest.json. Plik ten opisuje aplikację poprzez definicję m.in. jej nazwy oraz ikonek w różnych rozmiarach.

Dobra rada

Dobrą praktyką jest, aby ten plik był w katalogu głównym projektu (/).

Zawartość pliku manifest.json przed uzupełnieniem. Skopiuj ten kawałek kodu i uzupełnij wpisując dane odpowiednie dla Twojej aplikacji.

{
    "short_name": "",
    "name": "",
    "icons": [
        {
            "src": "",
            "sizes": "144x144",
            "type": "image/png"
        },
        {
            "src": "",
            "sizes": "192x192",
            "type": "image/png"
        }
    ],
    "start_url": "/?utm_source=homescreen",
    "background_color": "",
    "theme_color": "",
    "display": "fullscreen"
}

Zobacz jak wygląda manifest.json dla tego bloga.

Krok 3.2. Wskazanie ścieżki w pliku /index.html

Po tym jak plik został stworzony, musisz poinformować przeglądarkę, gdzie on się znajduje. Mówiłem, że nie musi to być katalog główny, jednak dla spójności warto aby był.

Poniższą linijkę dodaj w sekcji <head> aktualizując ścieżkę do manifestu.

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

Krok 4. Dodanie Service Workera

Drugim bardzo ważnym składnikiem aplikacji PWA jest Service Worker, który odpowiedzialny jest za zapisywanie plików aplikacji do Cache Storage-a.

Kiedy plik został pobrany przez przeglądarkę, to Service Worker zapisuje go do cache-a, aby w przyszłości wykorzystać, kiedy użytkownik nie będzie miał połączenia z siecią.

Przyjęta przeze mnie strategia nazywa się Network falling back to cache, która zdefiniowana jest tutaj. Strategia ta polecana jest przez autora posta - Jake-a - jako najlepsza do stron zawierających artykuły, czyli pięknie pasuje do aplikacji blogowej.

Zasady strategii Network falling back to cache

  1. Pobierz plik z serwera i jeśli się uda to zapisz do cache-a.
  2. Jeśli próba pobrania pliku się nie powiedzie to spróbuj pobrać go z cache-a.
  3. Jeśli i ta próba się nie powiedzie, to dopiero wtedy użytkownik nie dostanie żądanej treści.

Plusy

  • użytkownik ma większą szansę, że otrzyma to o co prosi ponieważ jest stworzony fallback zapytania HTTP na cache
  • użytkownik zawsze dostaje najnowsze wersje plików (prosto z serwera) jeśli ma połączenie z internetem

Minusy

  • na początku zawsze jest zapytanie do serwera, które może trwać kilka sekund
  • użytkownik nie dostaje treści zapisane w cache-u pomimo tego, że ją posiada
Diagram prezentujący przedstawione rozwiązanie z cache-em
Jak wygląda działania Service Workera w połączeniu z CacheStorage-em? Copyright by Google @ 2017

Do kiedy ważne są pliki w cache-u?

Nie zdefiniowałem, żadnego limitu cache-a. Traktuję go jako fallback, czyli takie dobro, które benefitem dla czytelników bloga.

Ile jest miejsca w cache-u?

  • Chrome - < 6% wolnego miejsca na dysku
  • Firefox - < 10% wolnego miejsca na dysku
  • Safari - < 50MB
  • IE10 - < 250MB
  • Edge - w zależności od dysku

Krok 4.1. Stworzenie pliku /service-worker.js

Stwórz plik service-worker.js o następującej treści. Oczywiście zaktualizuj listę plików, które chcesz aby były zapamiętane przez przeglądarkę użytkownika.

const CACHE_NAME = 'wpisz-tutaj-dowolny-string';

// List of files which are store in cache.
let filesToCache = [
    '/',
    '/styles/main.css',
    '/images/logo.png',
    '/scripts/main.js'
];

self.addEventListener('install', function (evt) {
    evt.waitUntil(
        caches.open(CACHE_NAME).then(function (cache) {
            return cache.addAll(filesToCache);
        }).catch(function (err) {
            // Snooze errors...
            // console.error(err);
        })
    );
});

self.addEventListener('fetch', function (evt) {
    // Snooze logs...
    // console.log(event.request.url);
    evt.respondWith(
        // Firstly, send request..
        fetch(evt.request).catch(function () {
            // When request failed, return file from cache...
            return caches.match(evt.request);
        })
    );
});

Zobacz jak plik service-worker.js wygląda na blogu.

Krok 4.2. Dołączenie go w /index.html

Proponuję dodać go do pliku głównego pliku, który na pewno będzie w cache-u więc pomimo tego, że nie będzie połączenia to i tak Service Worker uruchomi się.

<script>
const PATH = '/service-worker.js';

let isServiceWorkersSupport = ('serviceWorker' in navigator);

if (isServiceWorkersSupport) {
    console.log('Will service worker register?');
    navigator.serviceWorker.register(PATH).then(function () {
        console.log("Yes it did.");
    }).catch(function (err) {
        console.log("No it didn't. This happened: ", err)
    });
}
</script>

Po dodaniu manifestu oraz Service Workera uruchomiłem Lighthouse, aby zobaczyć o ile procent blog stał się bardziej aplikacją typu PWA. Zaskoczyłem się pozytywnie. Wystarczy dodanie dwóch prostych plików i już moja strona internetowa stała się aplikacją typu PWA!

Lighthouse: 86/100
Tak wygląda wynik pracy Lighthouse po dodaniu manifestu oraz Service Workera.

Krok 5. Inne opcje

Dodanie manifestu oraz Service Workera nie spowodowało, że blog osiągnął wynik 100/100 w audycie przeprowadzonym przez narzędzie Lighthouse.

Musiałem jeszcze zrobić kilka rzeczy.

Krok 5.1. Kolor górnego paska

Lighthouse wymienił, że w aplikacji brakuje zdefiniowanego koloru paska z adresem do strony. Nie mam żadnego telefonu z Androidem, aby sprawdzić jak strona wygląda na tym systemie. Wybrałem kolor górnego kontenera i użyłem go do definicji tego parametru.

<meta name="theme-color" content="#96b3bc"/>

Krok 5.2. Kolor tekstu - odpowiedni kontrast

Kolejnym problemem, był niepoprawny kontrast między kolorem tła a kolorem tekstu. Wiadomo, że szary tekst na białym tle wygląda strasznie. Całe szczęście znam ten problem i staram się, aby tekst zawsze dobrze się prezentował.

Jednak nie wszystkie elementy strony były przystosowane i współczynnik kolorystyczny nie był akceptowalny.

Lighthouse korzysta z algorytmu zdefiniowanego przez Lea Verou w projekcie contrast-ratio. Świetny projekt, który pokazuje jaki jest stosunek kolorystyczny tła oraz fontu.

Dobra rada

Na filmie poniżej znajdziesz więcej informacji na temat Web Content Accessibility Guidelines (WCAG) 2.0. Film opublikowany w piątek, 5 maja.

Lighthouse zakłada, że kontrast między tłem i kolorem tekstu musi być większy od przyjętej normy przez “contrast-ratio”, czyli 4.5. Niestety więc, musiałem zmienić błękit tła kontenera nagłówkowego na ciemniejszy niebieski.

Zdefiniowałem kolor tła na #2A7DB3 oraz tekstu white. Aplikacja “contrast-ratio” pokazała, że wynik takiej pary to 4.5, jednak Lighthouse dalej krzyczało.

Ocena 4.5 w badaniu kontrastu
Wynik narzędzia doa badania kontrakstu.

Ustawiłem więc jeszcze ciemniejszy background. Tym razem na #2a6fa5. Koloru fontu nie zmieniałem, czyli dalej jest white. Tym razem ocena 5.4

To było na tyle, jeśli chodzi o kolory. Lighthouse zaakceptował taki stan rzeczy!

Krok 5.3. Opóźnij ładowanie skryptów

Wykorzystałem atrybut async w tagu <script> to tego, aby nie blokować rysowania layoutu poprzez ładowane skrypty, które i tak niczego nie zmieniały w DOM-ie.

Czas na testy!

Lighthouse: 98/100
Tak wygląda wynik pracy Lighthouse po wprowadzeniu wszystkich opisanych ulepszeń.

Dlaczego nie 100/100?

Brak paginacji, czego efektem jest długa lista postów na stronie głównej. Nie chcę robić paginacji, z tego powodu, że na 1 stronie mogę znaleźć wszystkie napisane przeze mnie artykuły. Uważam to za duży plus mojego bloga.

Największy problem
Problem, który nie został jeszcze rozwiązany.

To, że strona nie jest dostępna po upływie 50ms tylko po 120ms nie wydaje mi się dużym problemem. Może na komórkach czeka się trochę dłużej na załadowanie tej długiej listy, ale trudno.

Profil wybranego przeze mnie losowego postu jest oceniany przez Lighthouse 100/100, więc misję uważam za zakończoną z pełnym sukcesem :tada:

Lighthouse: 100/100
Profil pierwszego lepszego postu jest oceniony przez Lighthouse-a maksymalną oceną, co mnie osobiście niezmiernie cieszy. Człowiek, zawsze czuje się spełniony, kiedy widzi, że osiągnął szczyt!

A co ze stroną domową?

Przerabiając bloga na aplikację typu PWA postanowiłem, że i moja strona domowa, również powinna być progresywna. Jej też się coś od życia należy :smiley:

Wykorzystując moje obecne doświadczenie, to po kilkudziesięcio minutowej pracy, strona domowa jest w 100% #PWA. Efekt możesz zobaczyć na obrazku poniżej.

Lighthouse: 100/100
Najlepszy możliwy wynik - 100%.

Jak wyświetlić aplikacje PWA które już odwiedziłem?

Na zakończenie pokażę Ci jak wyświetlić wszystkie strony które odwiedziłeś, a który korzystają z Service Worker-ów. Prawdopodobnie te strony są aplikacjami typu PWA.

Źródła na zakończenie