Przekształcenie aplikacji internetowej w PWA z powiadomieniami push
W niniejszym artykule omówimy proces przekształcania tradycyjnej aplikacji internetowej lub strony WWW w Progresywną Aplikację Internetową (PWA) z funkcją powiadomień push, wykorzystując do tego Firebase Cloud Messaging.
Współcześnie wiele aplikacji internetowych przechodzi transformację w PWA. Wynika to z korzyści, jakie oferują, takich jak tryb offline, powiadomienia push oraz synchronizacja danych w tle. Te cechy sprawiają, że aplikacje internetowe bardziej przypominają aplikacje natywne, dostarczając użytkownikom bogatsze wrażenia.
Znane przedsiębiorstwa, jak Twitter czy Amazon, wdrożyły PWA, aby zwiększyć interakcję użytkowników z ich usługami.
Czym jest PWA?
PWA to połączenie standardowej aplikacji internetowej z wybranymi funkcjami aplikacji natywnych.
PWA bazuje na tych samych technologiach co aplikacja internetowa (HTML, CSS, JavaScript) i działa w przeglądarkach w identyczny sposób. Jednakże, dzięki nowoczesnym przeglądarkom, może korzystać z funkcji typowych dla aplikacji natywnych. Zastosowanie PWA podnosi wydajność aplikacji internetowej i poprawia jej skalowalność, ponieważ zasoby interfejsu użytkownika mogą być pobierane i przechowywane lokalnie, co redukuje liczbę zapytań do serwera.
Różnice między PWA a tradycyjną aplikacją internetową
- Możliwość instalacji: PWA można zainstalować na urządzeniu, podobnie jak aplikację natywną.
- Progresywność: PWA działa tak jak zwykła aplikacja internetowa, ale z dodatkowymi funkcjami aplikacji natywnych.
- Interfejs zbliżony do aplikacji natywnej: Po zainstalowaniu PWA, użytkownik może nawigować i korzystać z niej jak z natywnej aplikacji.
- Łatwy dostęp: W przeciwieństwie do aplikacji internetowej, PWA nie wymaga od użytkownika wpisywania adresu URL przy każdej wizycie; uruchamia się za jednym kliknięciem.
- Buforowanie aplikacji: Tradycyjne aplikacje internetowe korzystają z buforowania HTTP w przeglądarce. PWA natomiast umożliwia buforowanie danych po stronie klienta, co w aplikacjach internetowych nie jest standardowo dostępne.
- Publikacja w sklepach: PWA mogą być publikowane w Google Play Store oraz w App Store.
Przekształcenie aplikacji w PWA zwiększa jej możliwości.
Dlaczego firmy powinny rozważyć PWA?
Często klienci najpierw zlecają wykonanie aplikacji internetowej, a następnie decydują się na stworzenie aplikacji na Androida i iOS. W takim przypadku te same funkcje są budowane w dwóch osobnych aplikacjach, co wiąże się z wyższymi kosztami i dłuższym czasem wprowadzenia produktu na rynek.
Jednak niektórzy klienci dysponują ograniczonym budżetem lub zależy im na szybkim wprowadzeniu produktu na rynek.
W większości przypadków funkcjonalność PWA jest wystarczająca. Dlatego proponujemy klientom PWA i sugerujemy przekształcenie PWA w aplikację na Androida za pomocą TWA, jeśli chcą udostępnić ją w Sklepie Play.
Jeśli wymagania klienta obejmują funkcje, których PWA nie obsługuje, mogą rozwijać zarówno PWA, jak i aplikację natywną. Nawet w takim scenariuszu PWA można udostępnić w Sklepie Play w okresie tworzenia aplikacji na Androida.
Przykład: Titan Eyeplus
Początkowo stworzyli PWA, którą udostępnili w Sklepie Play jako TWA. Po zakończeniu prac nad aplikacją na Androida, zastąpili ją natywną wersją. Dzięki temu osiągnęli szybsze wprowadzenie produktu na rynek i zoptymalizowali koszty.
Funkcje PWA
PWA wzbogacają aplikacje internetowe o funkcje zbliżone do tych, które oferują aplikacje natywne.
Do głównych funkcji należą:
- Instalacja: Aplikację internetową można zainstalować tak jak aplikację natywną.
- Buforowanie: Aplikacje można buforować, co umożliwia ich działanie w trybie offline.
- Powiadomienia push: Powiadomienia push wysyłane z serwera mogą zachęcać użytkowników do ponownego korzystania z aplikacji.
- Geofencing: Aplikacja może reagować na zmiany lokalizacji urządzenia.
- Obsługa płatności: W PWA można zaimplementować obsługę płatności, oferując użytkownikom równie płynne doświadczenie co w aplikacjach natywnych.
W przyszłości pojawią się kolejne funkcje.
Dodatkowe funkcje to:
- Skróty: Szybki dostęp do wybranych adresów URL, zdefiniowany w pliku manifestu.
- Web Share API: Aplikacja może przyjmować udostępnione dane z innych aplikacji.
- Badge API: Wyświetlanie liczby powiadomień na ikonie zainstalowanej PWA.
- API okresowej synchronizacji w tle: Umożliwia zapisywanie danych do czasu połączenia z siecią.
- Selektor kontaktów: Wybór kontaktów z urządzenia użytkownika.
- Selektor plików: Dostęp do plików w systemie lokalnym lub mobilnym.
Przewaga PWA nad aplikacjami natywnymi
Aplikacje natywne oferują lepszą wydajność i więcej funkcji niż PWA, ale PWA ma swoje zalety.
- Działanie na wielu platformach: PWA działają na Androidzie, iOS oraz komputerach.
- Redukcja kosztów rozwoju: Rozwój PWA jest zazwyczaj tańszy niż aplikacji natywnych.
- Łatwiejsze wdrażanie zmian: Aktualizacje PWA są łatwiejsze do wdrożenia niż w aplikacjach natywnych.
- Łatwość wyszukiwania: PWA, jako strony internetowe, są dobrze indeksowane przez wyszukiwarki.
- Bezpieczeństwo: PWA działają tylko na połączeniach HTTPS.
Wady PWA w porównaniu z aplikacjami natywnymi
- Ograniczona funkcjonalność: PWA oferują mniej funkcji niż aplikacje natywne.
- Niepełna kompatybilność: Nie wszystkie funkcje PWA muszą być obsługiwane na wszystkich urządzeniach.
- Słabszy branding: PWA nie są dostępne w sklepach z aplikacjami, co może osłabiać ich rozpoznawalność.
PWA można dodać do Sklepu Play, korzystając z mechanizmu Trusted Web Activity (TWA), co poprawia ich widoczność.
Elementy potrzebne do konwersji aplikacji internetowej na PWA
Aby przekształcić aplikację internetową w PWA, potrzebne są następujące elementy:
- Service Worker: Kluczowy element PWA, odpowiedzialny za buforowanie, powiadomienia push i obsługę zapytań.
- Plik manifestu: Zawiera informacje o aplikacji internetowej, umożliwiając jej instalację na ekranie głównym.
- Logo aplikacji: Wysokiej jakości obraz o rozmiarze 512×512 pikseli, używany jako ikona aplikacji. Konieczne jest przygotowanie zestawu obrazów w proporcji 1:1 dla różnych zastosowań.
- Responsywny design: Aplikacja internetowa musi być responsywna, by działać poprawnie na różnych rozmiarach ekranów.
Co to jest Service Worker?
Service Worker (skrypt działający po stronie klienta) pełni rolę serwera proxy między aplikacją internetową a zewnętrznymi zasobami, obsługując powiadomienia push oraz buforowanie danych.
Service Worker działa niezależnie od głównego skryptu JavaScript i nie ma dostępu do API DOM. Ma dostęp do IndexedDB API, Fetch API oraz Cache API. Może komunikować się z głównym wątkiem za pomocą wiadomości.
Usługi oferowane przez Service Worker:
- Przechwytywanie zapytań HTTP z domeny.
- Odbieranie powiadomień push z serwera.
- Zapewnienie dostępności aplikacji w trybie offline.
Service Worker kontroluje aplikację i może modyfikować zapytania, ale działa niezależnie. Dlatego domena musi korzystać z protokołu HTTPS, aby zapobiec atakom typu „man-in-the-middle”.
Czym jest plik manifestu?
Plik manifestu (manifest.json) zawiera informacje o aplikacji PWA dla przeglądarki.
- name: Nazwa aplikacji.
- short_name: Skrócona nazwa aplikacji (opcjonalna). Jeśli podano obie nazwy, przeglądarka użyje skróconej.
- description: Opis aplikacji.
- start_url: Określa stronę startową aplikacji po uruchomieniu PWA.
- icons: Zestaw obrazów używanych na ekranie głównym itp.
- background_color: Kolor tła ekranu powitalnego aplikacji PWA.
- display: Określa, jak interfejs przeglądarki ma wyświetlać aplikację.
- theme_color: Kolor motywu aplikacji PWA.
- scope: Zakres adresów URL, które mają być obsługiwane przez PWA. Domyślnie jest to folder, w którym znajduje się plik manifestu.
- shortcuts: Szybkie linki do funkcji PWA.
Konwersja aplikacji internetowej na PWA
Dla celów demonstracyjnych utworzono strukturę folderów dla strony newsblog.pl, składającą się z plików statycznych:
- index.html – strona główna
- artykuły/
- index.html – strona artykułów
- autorski/
- index.html – strona autorów
- narzędzia/
- index.html – strona narzędzi
- oferty/
- index.html – strona z ofertami
Jeśli masz już aplikację lub stronę internetową, możesz ją przekształcić w PWA, wykonując następujące kroki.
Utwórz potrzebne obrazy dla PWA
Na początek przygotuj logo aplikacji w proporcjach 1:1 w 5 różnych rozmiarach. Możesz skorzystać z narzędzia https://tools.crawlink.com/tools/pwa-icon-generator/, aby szybko wygenerować obrazy.
Utwórz plik manifestu
Następnie utwórz plik manifest.json z informacjami o aplikacji. Poniżej znajduje się przykładowy plik manifestu dla newsblog.pl:
{ "name": "newsblog.pl", "short_name": "newsblog.pl", "description": "newsblog.pl produces high-quality technology & finance articles, makes tools, and APIs to help businesses and people grow.", "start_url": "/", "icons": [{ "src": "assets/icon/icon-128x128.png", "sizes": "128x128", "type": "image/png" }, { "src": "assets/icon/icon-152x152.png", "sizes": "152x152", "type": "image/png" }, { "src": "assets/icon/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "assets/icon/icon-384x384.png", "sizes": "384x384", "type": "image/png" }, { "src": "assets/icon/icon-512x512.png", "sizes": "512x512", "type": "image/png" }], "background_color": "#EDF2F4", "display": "standalone", "theme_color": "#B20422", "scope": "/", "shortcuts": [{ "name": "Articles", "short_name": "Articles", "description": "1595 articles on Security, Sysadmin, Digital Marketing, Cloud Computing, Development, and many other topics.", "url": "https://geekflare.com/articles", "icons": [{ "src": "/assets/icon/icon-152x152.png", "sizes": "152x152" }] }, { "name": "Authors", "short_name": "Authors", "description": "newsblog.pl - Authors", "url": "/authors", "icons": [{ "src": "/assets/icon/icon-152x152.png", "sizes": "152x152" }] }, { "name": "Tools", "short_name": "Tools", "description": "newsblog.pl - Tools", "url": "https://newsblog.pl.com/tools", "icons": [{ "src": "/assets/icon/icon-152x152.png", "sizes": "152x152" }] }, { "name": "Deals", "short_name": "Deals", "description": "newsblog.pl - Deals", "url": "/deals", "icons": [{ "src": "/assets/icon/icon-152x152.png", "sizes": "152x152" }] } ] }
Zarejestruj Service Worker
Utwórz pliki register-service-worker.js i service-worker.js w głównym folderze.
Plik register-service-worker.js to skrypt JavaScript działający w głównym wątku, który ma dostęp do API DOM. Plik service-worker.js jest skryptem Service Worker, działającym niezależnie od głównego wątku, z krótkim cyklem życia. Uruchamia się przy wystąpieniu zdarzenia, które go wywołuje i działa do zakończenia procesu.
W pliku JavaScript głównego wątku sprawdź, czy Service Worker jest zarejestrowany. Jeśli nie, zarejestruj skrypt Service Worker (service-worker.js).
Wklej poniższy kod w pliku register-service-worker.js:
if ('serviceWorker' in navigator) { window.addEventListener('load', function() { navigator.serviceWorker.register('/service-worker.js'); }); }
Wklej poniższy kod w pliku service-worker.js:
self.addEventListener('install', (event) => { // event when service worker install console.log( 'install', event); self.skipWaiting(); }); self.addEventListener('activate', (event) => { // event when service worker activated console.log('activate', event); return self.clients.claim(); }); self.addEventListener('fetch', function(event) { // HTTP request interceptor event.respondWith(fetch(event.request)); // send all http request without any cache logic /*event.respondWith( caches.match(event.request).then(function(response) { return response || fetch(event. request); }) );*/ // cache new request. if already in cache serves with the cache. });
W tym artykule skupiamy się na konwersji aplikacji internetowej na PWA, a nie na implementacji trybu offline za pomocą pamięci podręcznej.
Dodaj link do pliku manifestu i skrypt w tagu <head> na stronie HTML:
<link rel="manifest" href="https://newsblog.pl.com/manifest.json"> <script src="/register-service-worker.js"></script>
Po wprowadzeniu zmian, odśwież stronę. Teraz możesz zainstalować aplikację na telefonie za pomocą przeglądarki Chrome.
Aplikacja zostanie dodana do ekranu głównego.
Jeśli używasz WordPressa, możesz skorzystać z gotowych wtyczek PWA. W przypadku VueJS lub ReactJS możesz zastosować powyższą metodę lub skorzystać z modułów PWA npm, które przyspieszą proces rozwoju. Moduły PWA npm często zawierają obsługę buforowania offline.
Włącz powiadomienia push
Powiadomienia web push pozwalają na ponowne angażowanie użytkowników w interakcję z aplikacją. Możesz je włączyć za pomocą:
- Notification API: Konfiguruje sposób wyświetlania powiadomień push użytkownikom.
- Push API: Służy do odbierania powiadomień wysyłanych z serwera do przeglądarki.
Pierwszym krokiem do włączenia powiadomień jest sprawdzenie Notification API i uzyskanie zgody użytkownika. W tym celu wklej poniższy kod do pliku register-service-worker.js:
if ('Notification' in window && Notification.permission != 'granted') { console.log('Ask user permission') Notification.requestPermission(status => { console.log('Status:'+status) displayNotification('Notification Enabled'); }); } const displayNotification = notificationTitle => { console.log('display notification') if (Notification.permission == 'granted') { navigator.serviceWorker.getRegistration().then(reg => { console.log(reg) const options = { body: 'Thanks for allowing push notification !', icon: '/assets/icons/icon-512x512.png', vibrate: [100, 50, 100], data: { dateOfArrival: Date.now(), primaryKey: 0 } }; reg.showNotification(notificationTitle, options); }); } };
Jeśli wszystko przebiegnie pomyślnie, otrzymasz powiadomienie z aplikacji.
Właściwość „Notification” w obiekcie window informuje, że API powiadomień jest wspierane w danej przeglądarce. Właściwość Notification.permission informuje, czy użytkownik wyraził zgodę na wyświetlanie powiadomień. Wartość 'granted’ oznacza, że użytkownik zezwolił aplikacji na wysyłanie powiadomień, a wartość 'denied’ oznacza, że użytkownik odmówił.
Włącz Firebase Cloud Messaging i utwórz subskrypcję
Teraz przechodzimy do właściwej części. Aby wysyłać powiadomienia z serwera do użytkownika, potrzebujemy unikalnego punktu końcowego (subskrypcji) dla każdego użytkownika. W tym celu użyjemy Firebase Cloud Messaging.
Zacznij od założenia konta w Firebase, przechodząc na stronę https://firebase.google.com/ i kliknij „Rozpocznij”.
- Utwórz nowy projekt, nadając mu nazwę (np. newsblog.pl) i kliknij „Kontynuuj”.
- W następnym kroku Google Analytics jest domyślnie włączone. Możesz wyłączyć tę opcję, jeśli nie jest potrzebna, i kliknąć „Kontynuuj”. W razie potrzeby można włączyć ją później w konsoli Firebase.
- Po utworzeniu projektu, panel powinien wyglądać podobnie do tego:
Przejdź do ustawień projektu, kliknij „Wiadomości w chmurze” i wygeneruj klucze.
Po wykonaniu tych kroków otrzymasz 3 klucze:
- Klucz serwera projektu
- Certyfikaty web push z kluczem prywatnym
- Certyfikaty web push z kluczem publicznym
Wklej poniższy kod w pliku register-service-worker.js:
const updateSubscriptionOnYourServer = subscription => { console.log('Write your ajax code here to save the user subscription in your DB', subscription); // write your own ajax request method using fetch, jquery, axios to save the subscription in your server for later use. }; const subscribeUser = async () => { const swRegistration = await navigator.serviceWorker.getRegistration(); const applicationServerPublicKey = 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY'; // paste your webpush certificate public key const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey); swRegistration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey }) .then((subscription) => { console.log('User is subscribed newly:', subscription); updateSubscriptionOnServer(subscription); }) .catch((err) => { if (Notification.permission === 'denied') { console.warn('Permission for notifications was denied') } else { console.error('Failed to subscribe the user: ', err) } }); }; const urlB64ToUint8Array = (base64String) => { const padding = '='.repeat((4 - base64String.length % 4) % 4) const base64 = (base64String + padding) .replace(/-/g, '+') .replace(/_/g, '/') const rawData = window.atob(base64); const outputArray = new Uint8Array(rawData.length); for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } return outputArray; }; const checkSubscription = async () => { const swRegistration = await navigator.serviceWorker.getRegistration(); swRegistration.pushManager.getSubscription() .then(subscription => { if (!!subscription) { console.log('User IS Already subscribed.'); updateSubscriptionOnYourServer(subscription); } else { console.log('User is NOT subscribed. Subscribe user newly'); subscribeUser(); } }); }; checkSubscription();
Wklej poniższy kod w pliku service-worker.js:
self.addEventListener('push', (event) => { const json = JSON.parse(event.data.text()) console.log('Push Data', event.data.text()) self.registration.showNotification(json.header, json.options) });
Po tych krokach wszystko jest skonfigurowane po stronie front-endu. Teraz możesz wysyłać powiadomienia push do użytkownika, korzystając z subskrypcji, dopóki nie cofnie zgody.
Wysyłanie powiadomień z backendu Node.js
Możesz skorzystać z modułu npm web-push dla ułatwienia.
Poniżej przykładowy kod do wysłania powiadomienia push z serwera Node.js:
const webPush = require('web-push'); // pushSubscription is nothing but subscription that you sent from your front-end to save it in DB const pushSubscription = {"endpoint":"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABh2…E0mTFsHtUqaye8UCoLBq8sHCgo2IC7UaafhjGmVCG_SCdhZ9Z88uGj-uwMcg","keys":{"auth":"qX6AMD5JWbu41cFWE3Lk8w","p256dh":"BLxHw0IMtBMzOHnXgPxxMgSYXxwzJPxpgR8KmAbMMe1-eOudcIcUTVw0QvrC5gWOhZs-yzDa4yKooqSnM3rnx7Y"}}; //your web certificates public-key const vapidPublicKey = 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY'; //your web certificates private-key const vapidPrivateKey = 'web-certificate private key'; var payload = JSON.stringify({ "options": { "body": "PWA push notification testing fom backend", "badge": "/assets/icon/icon-152x152.png", "icon": "/assets/icon/icon-152x152.png", "vibrate": [100, 50, 100], "data": { "id": "458", }, "actions": [{ "action": "view", "title": "View" }, { "action": "close", "title": "Close" }] }, "header": "Notification from newsblog.pl-PWA Demo" }); var options = { vapidDetails: { subject: 'mailto:[email protected]', publicKey: vapidPublicKey, privateKey: vapidPrivateKey }, TTL: 60 }; webPush.sendNotification( pushSubscription, payload, options ).then(data => { return res.json({status : true, message : 'Notification sent'}); }).catch(err => { return res.json({status : false, message : err }); });
Powyższy kod wyśle powiadomienie push do subskrypcji, co wywoła zdarzenie push w Service Worker.
Wysyłanie powiadomień z backendu PHP
W przypadku backendu PHP możesz skorzystać z pakietu kompozytora web-push-php. Poniżej znajduje się przykładowy kod do wysyłania powiadomień push:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); require __DIR__.'/../vendor/autoload.php'; use MinishlinkWebPushWebPush; use MinishlinkWebPushSubscription; // subscription stored in DB $subsrciptionJson = '{"endpoint":"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABh2…E0mTFsHtUqaye8UCoLBq8sHCgo2IC7UaafhjGmVCG_SCdhZ9Z88uGj-uwMcg","keys":{"auth":"qX6AMD5JWbu41cFWE3Lk8w","p256dh":"BLxHw0IMtBMzOHnXgPxxMgSYXxwzJPxpgR8KmAbMMe1-eOudcIcUTVw0QvrC5gWOhZs-yzDa4yKooqSnM3rnx7Y"}}'; $payloadData = array ( 'options' => array ( 'body' => 'PWA push notification testing fom backend', 'badge' => '/assets/icon/icon-152x1
newsblog.pl
Maciej – redaktor, pasjonat technologii i samozwańczy pogromca błędów w systemie Windows. Zna Linuxa lepiej niż własną lodówkę, a kawa to jego główne źródło zasilania. Pisze, testuje, naprawia – i czasem nawet wyłącza i włącza ponownie. W wolnych chwilach udaje, że odpoczywa, ale i tak kończy z laptopem na kolanach.