Een beginnersgids voor progressieve webapps
Over de auteur
Kevin Farrugia is medeoprichteroprichter bij Incredible Web, een web & bedrijf voor de ontwikkeling van mobiele toepassingen, gevestigd in Malta, EU; dat toonaangevende …Meer overKevin↬
- 18 min lezen
- Mobile,Apps,AMP,Service Workers
- Opgeslagen voor offline lezen
- Delen op Twitter, LinkedIn
Progressive web apps zouden wel eens de volgende big thing voor het mobiele web kunnen zijn. Oorspronkelijk voorgesteld door Google in 2015, hebben ze al veel aandacht getrokken vanwege het relatieve gemak van ontwikkeling en de bijna onmiddellijke winst voor de gebruikerservaring van de applicatie.
Verder lezen op SmashingMag:
- The Building Blocks Of Progressive Web Apps
- Conversational Design Essentials: Tips voor het bouwen van een chatbot
- Building A First-Class App That Leverages Your Website
- Creating A Complete Web App In Foundation For Apps
Een progressieve webapplicatie maakt gebruik van de nieuwste technologieën om het beste van web- en mobiele apps te combineren. Zie het als een website die is gebouwd met webtechnologieën, maar die werkt en aanvoelt als een app. Recente verbeteringen in de browser en in de beschikbaarheid van service workers en in de Cache en Push API’s hebben webontwikkelaars in staat gesteld gebruikers in staat te stellen webapps op hun startscherm te installeren, push-notificaties te ontvangen en zelfs offline te werken.
Progressieve webapps maken gebruik van het veel grotere webecosysteem, plugins en community en het relatieve gemak van het implementeren en onderhouden van een website in vergelijking met een native applicatie in de respectievelijke app stores. Degenen onder jullie die zowel op mobiel als op het web ontwikkelen, zullen het waarderen dat een website in minder tijd kan worden gebouwd, dat een API niet hoeft te worden onderhouden met backwards-compatibility (alle gebruikers zullen dezelfde versie van de code van je website draaien, in tegenstelling tot de versiefragmentatie van native apps) en dat de app over het algemeen eenvoudiger te implementeren en te onderhouden zal zijn.
Waarom Progressive Web Apps?
Een studie heeft aangetoond dat een app gemiddeld 20% van zijn gebruikers verliest voor elke stap tussen het eerste contact van de gebruiker met de app en het moment dat de gebruiker de app begint te gebruiken. Een gebruiker moet de app eerst vinden in een app store, downloaden, installeren en dan, ten slotte, openen. Wanneer een gebruiker uw progressive web app vindt, kan hij deze onmiddellijk gebruiken, waardoor de onnodige download- en installatiefasen wegvallen. En wanneer de gebruiker terugkeert naar de app, wordt hij gevraagd de app te installeren en te upgraden naar een full-screen ervaring.
Hoewel, een native app is zeker niet alleen maar slecht. Mobiele applicaties met push-notificaties hebben tot drie keer meer retentie dan hun tegenhangers zonder push, en een gebruiker heeft drie keer meer kans om een mobiele applicatie opnieuw te openen dan een website. Bovendien verbruikt een goed ontworpen mobiele applicatie minder data en is veel sneller omdat sommige resources op het apparaat staan.
Een progressive webapplicatie maakt gebruik van de kenmerken van een mobiele app, wat resulteert in een betere gebruikersretentie en betere prestaties, zonder de complicaties die het onderhoud van een mobiele applicatie met zich meebrengt.
Use Cases
Wanneer moet je een progressive web app bouwen? Native wordt meestal aanbevolen voor applicaties waarvan je verwacht dat gebruikers er vaak naar terugkeren, en een progressive web app is niet anders. Flipkart gebruikt een progressive web app voor zijn populaire e-commerce platform, Flipkart Lite, en SBB gebruikt een progressive web app voor zijn online check-in proces, waardoor gebruikers toegang hebben tot hun tickets zonder internetverbinding.
Bij de beoordeling of je volgende applicatie een progressive web app, een website of een native mobiele applicatie moet zijn, stel je eerst je gebruikers en de belangrijkste gebruikersacties vast. Omdat een progressive web app “progressive” is, werkt deze in alle browsers en wordt de ervaring verbeterd wanneer de browser van de gebruiker wordt bijgewerkt met nieuwe en verbeterde functies en API’s.
Dus, er is geen compromis in de gebruikerservaring met een progressive web app in vergelijking met een traditionele website; maar het kan zijn dat u moet beslissen welke functionaliteit offline wordt ondersteund, en u zult de navigatie moeten vergemakkelijken (vergeet niet dat de gebruiker in stand-alone modus geen toegang heeft tot de terug-knop). Als uw website al een applicatie-achtige interface heeft, zal het toepassen van de concepten van progressive web apps deze alleen maar beter maken.
Als bepaalde functies nodig zijn voor kritieke gebruikersacties, maar nog niet beschikbaar zijn door een gebrek aan cross-browser ondersteuning, dan is een native mobiele applicatie wellicht de betere optie, waarmee voor alle gebruikers dezelfde ervaring wordt gegarandeerd.
Karakteristieken van een Progressive Web App
Voordat we in de code springen, is het belangrijk om te begrijpen dat progressive web apps de volgende kenmerken hebben:
- Progressive. Per definitie moet een progressieve webapp op elk apparaat werken en progressief worden verbeterd, waarbij gebruik wordt gemaakt van alle functies die beschikbaar zijn op het apparaat en de browser van de gebruiker.
- Ontdekbaar. Omdat een progressive web app een website is, moet deze vindbaar zijn in zoekmachines. Dit is een groot voordeel ten opzichte van native applicaties, die nog steeds achterlopen op websites in doorzoekbaarheid.
- Linkable. Een andere eigenschap die is overgenomen van websites is dat een goed ontworpen website de URI moet gebruiken om de huidige status van de applicatie aan te geven. Dit stelt de web app in staat om zijn status te behouden of opnieuw te laden wanneer de gebruiker de URL van de app bookmarkt of deelt.
- Responsive. De UI van een progressieve web app moet passen bij de vormfactor en schermgrootte van het apparaat.
- App-achtig. Een progressive web app moet eruitzien als een native app en worden gebouwd op het shell-model van een applicatie, met minimale paginaverversingen.
- Connectiviteitsonafhankelijk. Het moet werken in gebieden met weinig connectiviteit of offline (onze favoriete eigenschap).
- Re-engageable. Gebruikers van mobiele apps zijn eerder geneigd hun apps opnieuw te gebruiken, en progressieve webapps zijn bedoeld om dezelfde doelen te bereiken door middel van functies zoals pushmeldingen.
- Installeerbaar. Een progressive web app kan worden geïnstalleerd op het startscherm van het apparaat, waardoor deze direct beschikbaar is.
- Vers. Wanneer nieuwe content wordt gepubliceerd en de gebruiker is verbonden met internet, moet die content beschikbaar worden gemaakt in de app.
- Veilig. Omdat een progressive web app een intiemere gebruikerservaring heeft en omdat alle netwerkverzoeken via service workers kunnen worden onderschept, is het noodzakelijk dat de app over HTTPS wordt gehost om man-in-the-middle-aanvallen te voorkomen.
Let’s Code!
Onze eerste progressive web app, Sky High, zal het aankomstschema van een luchthaven simuleren. De eerste keer dat de gebruiker onze web app opent, willen we hem een lijst van aankomende vluchten laten zien, opgehaald van een API. Als de gebruiker geen Internet verbinding heeft en de web app opnieuw laadt, willen we hem het vluchtschema laten zien zoals het was toen hij het de laatste keer downloadde met een verbinding.
De basis
Het eerste kenmerk van een progressieve webapp is dat deze op alle apparaten moet werken en moet verbeteren op apparaten en browsers die dit toestaan. Daarom hebben we onze website gebouwd met traditionele HTML5 en met JavaScript dat het ophalen van gegevens uit een mock API simuleert. Doorheen de applicatie gebruiken we kleine stukjes Knockout om onze Model-View-ViewModel (MVVM) bindingen af te handelen – een lichtgewicht JavaScript framework dat ons toelaat onze JavaScript modellen te binden aan onze HTML views. We hebben ervoor gekozen Knockout te gebruiken omdat het relatief eenvoudig te begrijpen is en de code niet onoverzichtelijk maakt; je kunt dit echter vervangen door een ander framework, zoals React of AngularJS.
Onze website volgt Google’s richtlijnen voor materiaalontwerp, een reeks principes die ontwerp en interactie sturen. Materiaalontwerp dient niet alleen als een uniforme standaard voor verschillende toepassingen en apparaten, maar geeft het ontwerp ook betekenis. We hebben material design gebruikt voor de aankomstweergave van Sky High om onze progressive web app die native-app look and feel te geven.
Ten slotte hebben we onze app getest om er zeker van te zijn dat deze jank-vrij is en dat het scrollen zijdezacht verloopt. Het is aangetoond dat rendering zonder jank de betrokkenheid van gebruikers verbetert. Streef naar een rendering van 60 frames per seconde.
Voor deze demo zullen we een statisch JSON bestand ophalen, in plaats van een echte API. Dit is alleen maar om het eenvoudig te houden. In de echte wereld zou je een API bevragen of WebSockets gebruiken.
index.html
<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Sky-High Airport Arrivals</title> <link async rel="stylesheet" href="./css/style.css"> <link href="https://fonts.googleapis.com/css?family=Roboto:300,600,300italic,600italic" rel="stylesheet" type="text/css"></head><body> <header> <div class="content"> <h3>Arrivals</h3> </div> </header> <div class="container"> <div class="content"> <ul class="arrivals-list" data-bind="foreach: arrivals"> <li class="item"> <span class="title" data-bind="html: title"></span> <span class="status" data-bind="html: status"></span> <span class="time" data-bind="html: time"></span> </li> </ul> </div> </div> <script src="./js/build/vendor.min.js"></script> <script src="./js/build/script.min.js"></script></body></html>
Het index.html
bestand is relatief standaard. We hebben een HTML-lijst gemaakt en onze View Model-eigenschap arrivals
eraan gekoppeld met Knockout, via het attribuut data-bind="foreach: arrivals”
. Het View Model arrivals
wordt gedeclareerd in het page.js
bestand hieronder en getoond in de Page
module. Op onze HTML-pagina hebben we voor elk item in de arrivals
array, de title
status
en time
eigenschappen aan de HTML-weergave gebonden.
page.js
(var Page = (function() { // declare the view model used within the page function ViewModel() { var self = this; self.arrivals = ko.observableArray(); } // expose the view model through the Page module return { vm: new ViewModel(), hideOfflineWarning: function() { // enable the live data document.querySelector(".arrivals-list").classList.remove('loading') // remove the offline message document.getElementById("offline").remove(); // load the live data }, showOfflineWarning: function() { // disable the live data document.querySelector(".arrivals-list").classList.add('loading') // load html template informing the user they are offline var request = new XMLHttpRequest(); request.open('GET', './offline.html', true); request.onload = function() { if (request.status === 200) { // success // create offline element with HTML loaded from offline.html template var offlineMessageElement = document.createElement("div"); offlineMessageElement.setAttribute("id", "offline"); offlineMessageElement.innerHTML = request.responseText; document.getElementById("main").appendChild(offlineMessageElement); } else { // error retrieving file console.warn('Error retrieving offline.html'); } }; request.onerror = function() { // network errors console.error('Connection error'); }; request.send(); } }})();
Dit page.js
bestand ontsluit de Page
module, die ons ViewModel vm
en twee functies bevat, hideOfflineWarning
en showOfflineWarning
. Het View Model ViewModel
is een eenvoudige JavaScript-literatuur die in de hele toepassing zal worden gebruikt. De eigenschap arrivals
op het ViewModel is Knockout’s observableArray
, die automatisch onze HTML aan een JavaScript-array bindt, zodat we items in onze array kunnen pushen en poppen in JavaScript en automatisch de HTML van de pagina kunnen bijwerken.
De functies hideOfflineWarning
en showOfflineWarning
stellen de rest van onze toepassing in staat deze functies aan te roepen om de UI van de pagina bij te werken die weergeeft of we online verbonden zijn. De showOfflineWarning
voegt een klasse van loading
toe aan ons arrivals-list
HTML element om de lijst te vervagen, en dan haalt het het HTML bestand offline.html
op via XHR. Ervan uitgaande dat het bestand succesvol is opgehaald (response.status === 200
), voegen we dit toe aan onze HTML. Natuurlijk, als we geen service workers gebruiken en de gebruiker is niet verbonden met het Internet, dan zou het niet mogelijk zijn om offline.html
op te halen, en dus zou de gebruiker de offline pagina van de browser te zien krijgen.
De business logica van waaruit we de gegevens van onze API ophalen en binden aan onze View Models en Views is te vinden in arrivals.js
en is standaard MVVM functionaliteit met behulp van Knockout. In het arrivals.js
bestand initialiseren we eenvoudig de services en View Models die we in de applicatie zullen gebruiken, en we stellen een functie beschikbaar – Arrivals.loadData()
– die de data ophaalt en aan het view model bindt.
Web App Manifest
Laten we onze web app meer app-achtig maken. Een web app manifest bestand is een eenvoudig JSON bestand dat de W3C specificatie volgt. Hiermee is het mogelijk om de web app in volledig scherm modus te draaien als een standalone applicatie, om een pictogram toe te wijzen dat wordt weergegeven wanneer de applicatie is geïnstalleerd op het apparaat, en om een thema en achtergrondkleur aan de app toe te wijzen. Bovendien stelt Chrome op Android proactief voor dat de gebruiker de webapp installeert via een installatiebanner voor webapps. Om de installatieprompt te kunnen weergeven, moet uw webapp:
- een geldig webapp-manifestbestand hebben,
- worden geserveerd via HTTPS,
- een geldige servicewerker hebben geregistreerd,
- tweemaal zijn bezocht, met ten minste vijf minuten tussen elk bezoek.
manifest.json
{ "short_name": "Arrivals", "name": "Arrivals at Sky High", "description": "Progressive web application demonstration", "icons": , "start_url": "./?utm_source=web_app_manifest", "display": "standalone", "orientation": "portrait", "theme_color": "#29BDBB", "background_color": "#29BDBB"}
Laten we dit manifest-bestand eens uitsplitsen:
-
short_name
is een menselijk leesbare naam voor de applicatie. In Chrome voor Android is dit ook de naam die bij het pictogram op het startscherm staat. -
name
is ook een leesbare naam voor de applicatie en definieert hoe de applicatie in de lijst komt te staan. -
description
geeft een algemene beschrijving van de webapplicatie. -
icons
definieert een array van afbeeldingen van verschillende grootte die zullen dienen als de pictogrammenset van de applicatie. In Chrome voor Android wordt het pictogram gebruikt op het splash-scherm, op het startscherm en in de taakswitcher. -
start_url
is de start-URL van de applicatie. -
display
definieert de standaard weergavemodus voor de webapplicatie:fullscreen
standalone
minimal-ui
ofbrowser
. -
orientation
definieert de standaard oriëntatie voor de webapplicatie:portrait
oflandscape
. -
theme_color
is de standaard themakleur voor de applicatie. Op Android wordt dit ook gebruikt om de statusbalk te kleuren. -
background_color
definieert de achtergrondkleur van de webapplicatie. In Chrome definieert het ook de achtergrondkleur van het splash-scherm. -
related_applications
is niet geïmplementeerd in ons voorbeeld, maar wordt gebruikt om native applicatie-alternatieven op te geven in de verschillende app stores.
Voeg de manifest.json
verwijzing toe aan de index.html
tag van het bestand head
:
<link rel="manifest" href="./manifest.json">
Als een gebruiker de webapp eenmaal aan zijn startscherm heeft toegevoegd, kan hij vanaf zijn apparaat direct weer met uw toepassing aan de slag, zonder dat hij direct de browser hoeft te openen. U ziet dat dit veel meer is dan een webbladwijzer.
Add to Homescreen on Chrome for Android from Smashing Magazine on Vimeo.
Service Workers
Een van de meer opwindende aspecten van progressieve webapps is dat ze offline kunnen werken. Met behulp van service workers is het mogelijk om gegevens te tonen die in eerdere sessies van de app zijn opgehaald (met behulp van IndexedDB) of, als alternatief, de shell van de applicatie te tonen en de gebruiker te informeren dat hij niet met internet is verbonden (de aanpak die we in deze demo hebben gekozen). Zodra de gebruiker weer verbinding heeft, kunnen we de laatste gegevens van de server ophalen.
Dit alles is mogelijk door service workers, dat zijn event-driven scripts (geschreven in JavaScript) die toegang hebben tot domein-brede events, inclusief netwerk fetches. Met hen kunnen we alle statische bronnen cachen, wat het aantal netwerkverzoeken drastisch kan verminderen en de prestaties ook aanzienlijk kan verbeteren.
Application Shell
De application shell is het minimum aan HTML, CSS en JavaScript dat nodig is om een gebruikersinterface aan te sturen. Een native mobiele applicatie bevat de applicatieshell als onderdeel van zijn distribueerbare, terwijl websites deze normaal gesproken via het netwerk opvragen. Progressieve webapplicaties overbruggen deze kloof door de resources en assets van de applicatieshell in de cache van de browser te plaatsen. In onze Sky High applicatie kunnen we zien dat onze applicatie shell bestaat uit de top header bar, de fonts en alle CSS die nodig zijn om deze elegant te renderen.
Om met service workers aan de slag te gaan, moeten we eerst het JavaScript-bestand van onze service worker maken, sw.js
, geplaatst in de root directory.
sw.js
// Use a cacheName for cache versioningvar cacheName = 'v1:static';// During the installation phase, you'll usually want to cache static assets.self.addEventListener('install', function(e) { // Once the service worker is installed, go ahead and fetch the resources to make this work offline. e.waitUntil( caches.open(cacheName).then(function(cache) { return cache.addAll().then(function() { self.skipWaiting(); }); }) );});// when the browser fetches a URL…self.addEventListener('fetch', function(event) { // … either respond with the cached object or go ahead and fetch the actual URL event.respondWith( caches.match(event.request).then(function(response) { if (response) { // retrieve from cache return response; } // fetch as normal return fetch(event.request); }) );});
Laten we onze service worker eens van dichterbij bekijken. Eerst stellen we een cacheName
variabele in. Deze wordt gebruikt om te bepalen of er wijzigingen zijn aangebracht in onze cached assets. In dit voorbeeld gebruiken we een statische naam, wat betekent dat onze activa niet zullen veranderen of moeten worden bijgewerkt.
self.addEventListener('install', function(e) { // declare which assets to cache}
Het install
-event vuurt tijdens de installatiefase van de service worker en vuurt slechts één keer als de service worker al is geïnstalleerd. Daarom zal het verversen van de pagina de installatiefase niet opnieuw triggeren. Tijdens de installatie fase, zijn we in staat om aan te geven welke assets zullen worden gecached. In ons voorbeeld hierboven cachen we een CSS bestand, twee JavaScript bestanden, ons fonts bestand, onze offline HTML template en, natuurlijk, de applicatie root. self.skipWaiting()
dwingt de wachtende service worker om actief te worden.
Tot zover hebben we onze service worker gedeclareerd, maar voordat we deze in werking kunnen zien treden, moeten we er in ons JavaScript naar verwijzen. In onze applicatie, registreren we deze in main.js
// Register the service worker if available.if ('serviceWorker' in navigator) { navigator.serviceWorker.register('./sw.js').then(function(reg) { console.log('Successfully registered service worker', reg); }).catch(function(err) { console.warn('Error whilst registering service worker', err); });}window.addEventListener('online', function(e) { // Resync data with server. console.log("You are online"); Page.hideOfflineWarning(); Arrivals.loadData();}, false);window.addEventListener('offline', function(e) { // Queue up events for server. console.log("You are offline"); Page.showOfflineWarning();}, false);// Check if the user is connected.if (navigator.onLine) { Arrivals.loadData();} else { // Show offline message Page.showOfflineWarning();}// Set Knockout view model bindings.ko.applyBindings(Page.vm);
We hebben ook twee event listeners opgenomen om te controleren of de status van de sessie is veranderd van online
in offline
of vice versa. De event handlers roepen dan de verschillende functies aan om de gegevens op te halen via Arrivals.loadData()
en om het offline bericht in of uit te schakelen via respectievelijk Page.showOfflineWarning
en Page.hideOfflineWarning
. Onze applicatie controleert ook of de gebruiker op dit moment online is, door gebruik te maken van navigator.onLine, en haalt de gegevens op of toont de offline waarschuwing dienovereenkomstig. En in de laatste regel van main.js
, passen we de Knockout bindings toe op ons View Model Page.vm
.
Als we onze applicatie voor de eerste keer laden (met Chrome Developer Tools), zullen we niets nieuws zien. Als we de applicatie echter opnieuw laden, zullen we zien dat een aantal netwerkbronnen zijn opgehaald van de service worker. Dit is de schil van onze applicatie.
Offline-test
Een gebruiker die de toepassing uitvoert zonder internetverbinding (ervan uitgaande dat hij of zij al op de pagina is geweest), krijgt gewoon de shell van de toepassing en de offline-waarschuwing te zien – een verbetering ten opzichte van Chrome’s sluipende t-rex. Zodra de gebruiker een netwerkverbinding tot stand heeft gebracht, schakelen we de waarschuwing uit en halen we de nieuwste gegevens op.
The Guardian hanteert een bijzonder interessante aanpak wanneer offline gebruikers zijn website openen, door een kruiswoordraadsel te bieden:
Push-notificaties
Push-notificaties stellen gebruikers in staat zich aan te melden voor tijdige updates van applicaties die ze vertrouwen, en hen helpen opnieuw contact te maken met de apps. Met pushmeldingen op het web kunt u ook contact houden met uw publiek als de browser gesloten is.
De Push-API wordt ondersteund in Chrome, Opera en de browser van Samsung en is in ontwikkeling in Firefox en Microsoft Edge. Helaas zijn er geen aanwijzingen dat de functie in Safari zal worden geïmplementeerd.
Prestaties
Een van de gemakkelijkste winstpunten met service workers is dat we de prestaties met weinig tot geen moeite kunnen verbeteren. Als we onze website vergelijken met die van voor de implementatie van service workers, dan zien we dat we voorheen meer dan 200 KB ophaalden bij het laden van de pagina; dat is nu teruggebracht tot 13 KB. Op een normaal 3G netwerk zou het laden van de pagina 3,5 seconden hebben geduurd; nu duurt het 500 milliseconden.
Deze prestatieverbeteringen zijn drastisch omdat de applicatie zelf erg klein is en beperkte functionaliteit heeft. Toch is het mogelijk om door het juiste gebruik van caching de prestaties en de waargenomen prestaties aanzienlijk te verbeteren, vooral voor gebruikers op plaatsen met een lage connectiviteit.
Lighthouse
Google’s Chrome team heeft een tool samengesteld voor het testen van progressive web apps. Lighthouse draait in Node.js of als een Chrome plugin en is ook te vinden op GitHub.
Om een Lighthouse test uit te voeren, moet uw website online beschikbaar zijn, wat betekent dat u niet kunt testen op localhost
.
Om te beginnen downloadt u het npm-pakket:
npm install -g GoogleChrome/lighthouse
Als dat eenmaal is geïnstalleerd, start u Chrome (vanaf versie 52):
npm explore -g lighthouse -- npm run chromelighthouse https://incredibleweb.github.io/pwa-tutorial/
De uitvoer van de Lighthouse-run is zichtbaar in de opdrachtregel en rangschikt uw website aan de hand van de functies en eigenschappen van de progressieve webapp die u hebt geïmplementeerd – bijvoorbeeld of u een manifest.json
-bestand gebruikt of dat uw pagina offline beschikbaar is.
Conclusie
Dit artikel is slechts een voorproefje voor progressive web apps. We kunnen nog veel meer doen om die app-achtige ervaring te creëren waar gebruikers naar op zoek zijn, of het nu is door push-notificaties te ondersteunen met de Push API, de app re-engageable te maken, of IndexedDB en background syncing te gebruiken om de offline ervaring te verbeteren.
Cross-Browser Support
Het is nog vroeg dag voor progressive web apps, en de cross-browser ondersteuning is nog beperkt, vooral in Safari en Edge. Microsoft ondersteunt progressive web apps echter openlijk en zou tegen het eind van het jaar meer functies moeten implementeren.
- Service workers en Cache API. Ondersteund in Chrome, Firefox, Opera en de browser van Samsung. In ontwikkeling in Microsoft Edge, naar verwachting beschikbaar tegen het einde van 2016. Wordt overwogen voor Safari.
- Toevoegen aan startscherm. Ondersteund in Chrome, Firefox, Opera, Android Browser en Samsung’s browser. Microsoft lijkt aan te geven dat progressive web apps beschikbaar zullen zijn als store listings. Vooralsnog geen plannen voor Safari.
- Push API. Voornamelijk ondersteund in Chrome, Firefox, Opera en Samsung’s browser. In ontwikkeling in Microsoft Edge. Nog geen plannen voor Safari.
Als meer ontwikkelaars hun voordeel doen met de mogelijkheden van progressive web apps – die relatief eenvoudig te implementeren zijn en direct resultaat opleveren – dan zullen gebruikers deze web apps het liefst in ondersteunde browsers gebruiken, en hopelijk de andere browserleveranciers overhalen zich aan te passen.