Sådan konverteres WebApp som PWA med Push Notification

I denne artikel ser vi, hvordan man konverterer en webapplikation eller et websted til en PWA med en push-meddelelse ved hjælp af Firebase Cloud Messaging.

I den moderne verden bliver de fleste webapplikationer konverteret til en PWA (Progressive Web App), fordi den giver funktioner som offline support, push-meddelelser, baggrundssynkronisering. PWA-funktioner gør vores webapplikation mere som en indbygget app og giver en rig brugeroplevelse.

For eksempel har store virksomheder som Twitter og Amazon konverteret deres webapp til PWA for mere brugerengagement.

Hvad er en PWA?

PWA = (webapp) + (nogle indbyggede appfunktioner)

PWA er din samme webapp (HTML+CSS+JS). Den fungerer på samme måde som din webapp i alle browsere, som den tidligere gjorde. Men det kan have indbyggede funktioner, når dit websted indlæses på en moderne browser. Det gør din webapp mere kraftfuld end før, og den gør den også mere skalerbar, fordi vi kan forhåndshente og cache aktiver i frontend, det reducerer anmodninger til din backend-server.

Hvordan PWA er forskellig fra Web App

  • Installerbar: Din webapp kan installeres som en indbygget app
  • Progressiv: Fungerer på samme måde som din webapp, men med nogle indbyggede funktioner
  • Native App Experience: Brugeren kan bruge og navigere Web App som en indfødt, når den er installeret.
  • Let tilgængelig: I modsætning til vores webapp er der ikke behov for, at vores brugere skal indtaste webadresser, hver gang de besøger. Når den er installeret, kan den åbnes med et enkelt tryk.
  • Applikationscaching: Før PWA var den eneste cachingmekanisme, som vores webapp blev implementeret med, ved at bruge HTTP-cache, som kun er tilgængelig for browseren. Men med PWA kan vi cache ting ved at bruge koden på klientsiden, som ikke er tilgængelig i en webapp.
  • (App/Play) butiksudgivelse: PWA kan udgives i Google Play Store og IOS App Store.

Konvertering af din applikation til PWA vil kun gøre den mere kraftfuld.

Hvorfor virksomheder bør overveje PWA

Mens de fleste af vores kunder når frem til os og beder om at udvikle webapp-løsningen først, og derefter beder de om Android- og iOS-apps. Alt, hvad vi skal gøre, er at bygge den samme funktionalitet i web-app til Android/IOS-app af et separat team, som tager flere udviklingsomkostninger og mere tid til at markedsføre.

Men nogle kunder har et begrænset budget, eller nogle kunder tror måske, at time to market er vigtigere for deres produkt.

De fleste af kundens krav kan opfyldes af PWA-funktioner selv. For dem foreslår vi kun PWA og giver dem en idé om at konvertere deres PWA som en Android-app ved hjælp af TWA, hvis de ønsker at implementere i Playstore.

Hvis dit krav virkelig har brug for native applikationsfunktioner, som ikke kan opfyldes af PWA. Kunder kan gå hen og udvikle begge applikationer, som de ønsker. Men selv i det scenarie. De kan implementere PWA’en i play-butikken, indtil Android-udviklingen er fuldført.

Eksempel: Titan Eyeplus

Til at begynde med udviklede de en PWA-app og implementerede den i play-butikken ved hjælp af TWA (Trusted Web Activity). Når de har afsluttet deres Android-applikationsudvikling. De implementerede deres rigtige Android-applikation i play-butikken. De opnåede både time-to-market ved hjælp af PWA og omkostningerne ved udviklingen.

PWA funktioner

PWA giver vores webapplikationer native app-lignende funktioner.

De vigtigste funktioner er:

  • Installerbar: En webapplikation installeret som en indbygget app.
  • Caching: Applikationscaching er muligt, hvilket giver vores applikation offline support.
  • Push-meddelelse: Push-meddelelse kan sendes fra vores server for at engagere vores brugere til vores hjemmeside.
  • Geofencing: Applikationen kan blive underrettet af en begivenhed, hver gang enhedens placering ændres.
  • Betalingsanmodning: Aktiver betaling i din applikation med en fantastisk brugeroplevelse som en indbygget app.
  Sådan opdeles tekst i Google Sheets

Og mange flere funktioner kommer i fremtiden.

Andre funktioner er:

  • Genveje: Hurtigt tilgængelige URL’er tilføjet i manifestfilen.
  • Web Share API: Lad din applikation modtage delte data fra andre applikationer.
  • Badge API: For at vise antallet af meddelelser i din installerede PWA.
  • Periodic Background Sync API: gemmer din brugers data, indtil den er forbundet til netværket.
  • Kontaktvælger: Bruges til at vælge kontakter fra brugerens mobil.
  • Filvælger: Bruges til at få adgang til filen på lokalt system/mobil

Fordel ved PWA frem for Native Application

Den oprindelige app klarer sig bedre end PWA og har flere funktioner end PWA. Men alligevel har det nogle fordele i forhold til den oprindelige app.

  • PWA kører på tværs af platforme som Android, IOS, Desktop.
  • Det reducerer dine udviklingsomkostninger.
  • Nem funktionsimplementering sammenlignet med en indbygget app.
  • Let at finde, fordi PWA (websted) er SEO-venligt
  • Sikkert, fordi det kun virker på HTTPS

Ulemper ved PWA i forhold til native app

  • Begrænsede funktionaliteter er tilgængelige sammenlignet med en indbygget app.
  • Det er ikke garanteret, at PWA-funktioner understøtter alle enheder.
  • Brandingen af ​​PWA er lav, fordi den ikke er tilgængelig i App Store eller Play Store.

Du kan implementere din PWA som en Android-app i Play Store ved hjælp af Android Trusted Web Activity (TWA). Det vil hjælpe din branding.

Ting, der er nødvendige for at konvertere Web App til PWA

Til konvertering, enhver webapp eller hjemmeside til PWA.

  • Service-Worker: kernen i enhver PWA-app til cachelagring, push-meddelelser, en proxy for vores anmodninger.
  • Manifestfil: Den har detaljer om din webapplikation. Det plejede at downloade vores applikation som en indbygget app på startskærmen.
  • App-logo: Højkvalitetsbillede 512 x 512 px til dit app-ikon. App-logo er nødvendig for PWA på startskærmen, splash-skærmen osv. Så vi er nødt til at oprette et sæt billeder i forholdet 1:1 til vores APP ved hjælp af alle værktøjer.
  • Responsivt design: Webappen skal være responsiv til at arbejde på forskellige skærmstørrelser.

Hvad er servicemedarbejder:

En serviceworker (script på klientsiden) er en proxy mellem din web-APP og den ydre side, der leverer push-meddelelser til vores web-app og understøtter caching.

Service Worker kører uafhængigt af det primære javascript. Så den har ikke adgang til DOM API. Den kan kun få adgang IndexedDB API, Hent API, Cache Storage API. Men det kan kommunikere med hovedtråden med et budskab.

Service leveret af servicemedarbejder:

  • Opsnapper HTTP-anmodninger fra dit oprindelsesdomæne.
  • Modtag push-besked fra din server.
  • Offline tilgængelighed af vores applikation

Servicemedarbejderen styrer din applikation og kan manipulere dine anmodninger, men den kører uafhængigt. Så af den grund skal oprindelsesdomænet være aktiveret med HTTPS for at undgå et man-in-the-middle-angreb.

Hvad er Manifest-filen

En manifestfil (manifest.json) har detaljer om vores PWA-app for at fortælle browseren.

  • navn: Navnet på ansøgningen
  • short_name: Kort navn til vores ansøgning. Hvis det leveres
  • med både ejendomsnavn og kort_navn vil browseren tage kort_navn.
  • beskrivelse: Beskrivelse for at beskrive vores applikation.
  • start_url: For at angive applikationens hjemmeside, da vores PWA blev lanceret.
  • ikoner: Sæt af billeder til PWA til startskærm osv.
  • background_color: For at indstille baggrundsfarven på splash-skærmen i vores PWA-applikation.
  • display: For at tilpasse vores browser-UI til at blive vist i vores PWA-app.
  • theme_color: Temafarve for PWA-appen.
  • scope: URL-omfang for vores ansøgning, der skal overvejes for PWA. Angiver som standard placeringen af ​​den lokaliserede manifestfil.
  • genveje: Hurtige links til vores PWA-applikation.

Konverter Web App til PWA

Til demoformålet har jeg lavet en toadmin.dk-webstedsmappestruktur med statiske filer.

  • index.html – startside
  • artikler/
    • index.html – artikelside
  • forfattere/
    • index.html – forfatterside
  • værktøj/
    • index.html – værktøjsside
  • tilbud/
    • index.html – tilbudsside

Hvis du allerede har et websted eller en webapp, så prøv at konvertere det til PWA ved at følge nedenstående trin.

  Sådan bruges Editor Chat i Google Docs

Opret påkrævede billeder til PWA

Tag først dit applogo og beskær det i en 1:1-forholdsstørrelse i 5 forskellige størrelser. jeg har brugt https://tools.crawlink.com/tools/pwa-icon-generator/ for hurtigt at få forskellige billedstørrelser. Så du kan også bruge det.

Opret en manifestfil

For det andet skal du oprette en manifest.json-fil til din webapplikation med dine appoplysninger. Til demoen har jeg oprettet en manifestfil til toadmin.dk Website.

{
	"name": "toadmin.dk",
	"short_name": "toadmin.dk",
	"description": "toadmin.dk 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": "toadmin.dk - Authors",
			"url": "/authors",
			"icons": [{
				"src": "/assets/icon/icon-152x152.png",
				"sizes": "152x152"
			}]
		},
		{
			"name": "Tools",
			"short_name": "Tools",
			"description": "toadmin.dk - Tools",
			"url": "https://toadmin.dk.com/tools",
			"icons": [{
				"src": "/assets/icon/icon-152x152.png",
				"sizes": "152x152"
			}]
		},
		{
			"name": "Deals",
			"short_name": "Deals",
			"description": "toadmin.dk - Deals",
			"url": "/deals",
			"icons": [{
				"src": "/assets/icon/icon-152x152.png",
				"sizes": "152x152"
			}]
		}
	]
}

Tilmeld Service-medarbejder

oprette en script-fil register-service-worker.js og service-worker.js i rodmappen.

Den første, register-service-worker.js er javascript-filen, der kører på hovedtråden, som kan få adgang til DOM API. Men service-worker.js er et service worker-script, der kører uafhængigt af hovedtråden, og dets levetid er også kort. Det kører, når hændelser kalder servicemedarbejdere og kører, indtil det afslutter processen.

Ved at tjekke hovedtrådens javascript-fil kan du kontrollere, om servicearbejderen er registreret i den. hvis ikke kan du registrere service worker scriptet (service-worker.js).

indsæt nedenstående uddrag i register-service-worker.js:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('/service-worker.js');
    });
}

Indsæt nedenstående kodestykke i 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.
});

Vi koncentrerede os ikke om, hvordan man aktiverer cache for offline support. Vi taler kun om, hvordan man konverterer webapps til PWA.

Tilføj manifestfil og script i all head-tagget på din HTML-side.

<link rel="manifest" href="https://toadmin.dk.com/manifest.json">
<script src="/register-service-worker.js"></script>

Opdater siden, efter du har tilføjet. Nu kan du installere din applikation som nedenfor på mobil chrome.

På startskærmen bliver appen tilføjet.

Hvis du bruger WordPress. Prøv at bruge det eksisterende PWA-konverter-plugin. For vueJS eller reactJS kan du følge ovenstående metode eller bruge de eksisterende PWA npm-moduler for at hurtigere din udvikling. Fordi PWA npm-moduler allerede er aktiveret med offline support-caching osv.

Aktiver push-besked

Web-push-meddelelser sendes til browseren for at få vores brugere til at engagere sig/interagere med vores applikation oftere. Vi kan aktivere det ved at bruge

  • Notification API: Den bruges til at konfigurere, hvordan vores push-meddelelse skal vises til brugeren.
  • Push API: Den bruges til at modtage meddelelser sendt fra vores server til browseren.

Det første trin for at aktivere push-meddelelse i vores applikation er at tjekke Notification API og få tilladelse fra brugeren til at vise en notifikation. For at kopiere og indsætte uddraget nedenfor i din 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);
        });
    }
};

Hvis alt gik korrekt. Du vil modtage en meddelelse fra applikationen.

‘Notifikation’ i vinduet vil fortælle os, at Notification API understøttes i den browser. Notification.permission vil fortælle, at brugeren har fået tilladelse til at vise meddelelsen. Hvis brugeren tillod vores ansøgning, vil værdien blive “tildelt”. hvis brugeren har afvist, vil værdien blive ‘blokeret’.

Aktiver Firebase Cloud Messaging og Opret abonnement

Nu begynder den rigtige del. For at sende notifikationer fra din server til brugeren har vi brug for et unikt slutpunkt/abonnement for hver bruger. Til det skal vi bruge firebase cloud-meddelelser.

  Sådan opretter du udgifts- og indtægtsregneark i Microsoft Excel

Som et første trin skal du oprette en firebase-konto ved at besøge dette link https://firebase.google.com/ og tryk på kom i gang.

  • Opret et nyt projekt med et navn og tryk fortsæt. Jeg vil oprette den med navnet toadmin.dk.
  • I næste trin er Google Analytics aktiveret som standard. Du kan skifte til, at vi ikke har brug for det nu og trykke på Fortsæt. Du kan aktivere det senere i din firebase-konsol, hvis du har brug for det.
  • Når projektet er oprettet, vil det se ud som nedenfor.
  • Gå derefter til projektindstillingerne og klik på cloud messaging og generer nøgler.

    Fra ovenstående trin har du 3 nøgler.

    • projekt server-nøgle
    • Web-push-certifikater privat-nøgle
    • Web-push-certifikater offentlig nøgle

    Indsæt nu nedenstående uddrag i 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();

    Indsæt nedenstående kodestykke i 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)
    });

    Nu er alt sat i front-end. Ved at bruge abonnementet kan du sende push-beskeder til din bruger, når du vil, indtil de ikke blev nægtet push-tjenesterne.

    Push fra node.js Backend

    Du kan bruge web-push npm-modul for at gøre det nemmere.

    Eksempel uddrag til at sende push-meddelelse fra nodeJS-server.

    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 toadmin.dk-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 });
        });

    Ovenstående kode sender en push-meddelelse til abonnementet. Push-hændelsen i service-workeren vil blive udløst.

    Push fra PHP-backend

    Til PHP-backend kan du bruge web-push-php komponistpakke. Tjek eksempelkoden for at sende push-meddelelser nedenfor.

    <?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-152x152.png',
                    'icon' => '/assets/icon/icon-152x152.png',
                    'vibrate' => 
                    array (
                      0 => 100,
                      1 => 50,
                      2 => 100,
                    ),
                    'data' => 
                    array (
                      'id' => '458',
                    ),
                    'actions' => 
                    array (
                      0 => 
                      array (
                        'action' => 'view',
                        'title' => 'View',
                      ),
                      1 => 
                      array (
                        'action' => 'close',
                        'title' => 'Close',
                      ),
                    ),
    ),
    'header' => 'Notification from toadmin.dk-PWA Demo',
    );
    
    // auth
    $auth = [
        'GCM' => 'your project private-key', // deprecated and optional, it's here only for compatibility reasons
        'VAPID' => [
            'subject' => 'mailto:[email protected]', // can be a mailto: or your website address
            'publicKey' => 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY', // (recommended) uncompressed public key P-256 encoded in Base64-URL
            'privateKey' => 'your web-certificate private-key', // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
        ],
    ];
    
    $webPush = new WebPush($auth);
    
    $subsrciptionData = json_decode($subsrciptionJson,true);
    
    
    // webpush 6.0
    $webPush->sendOneNotification(
      Subscription::create($subsrciptionData),
      json_encode($payloadData) // optional (defaults null)
    );

    Konklusion

    Jeg håber, at dette giver dig en idé om at konvertere webapplikationer til PWA. Du kan tjekke kildekoden til denne artikel her og demo det her. Jeg har testet push-meddelelsen ved også at sende den fra backend ved hjælp af eksempelkode.