PWA (Progressive Web App) — is een webapplicatie die moderne browsermogelijkheden gebruikt om als een native app te werken: snel laden, offline werken, pushmeldingen verzenden en installeren op het startscherm. Aan de basis van PWA liggen drie technologieën: Service Worker, manifest en HTTPS. Service Worker — is een script dat de browser op de achtergrond uitvoert, los van de webpagina, en mogelijkheden opent die niet beschikbaar zijn voor gewone sites: netwerkverzoeken onderscheppen, bronnen cachen, achtergrondsynchronisatie en pushmeldingen. Het manifest — is een JSON-bestand dat de browser vertelt hoe de applicatie eruit moet zien wanneer deze op het apparaat wordt geïnstalleerd: naam, pictogrammen, themakleur, schermoriëntatie. Zonder HTTPS werkt Service Worker niet — dit is een verplichte veiligheidseis. PWA is compatibel met elke moderne browser en vereist geen publicatie in de app store. De gebruiker opent de site, ziet het voorstel om de app te installeren, klikt op «Toevoegen aan startscherm» — en de app is klaar. Voor bedrijven betekent PWA het bereiken van elk publiek zonder kosten voor afzonderlijke ontwikkeling voor iOS en Android, hoge laadsnelheid zelfs op langzame netwerken en betrokkenheid via pushmeldingen. In het artikel bespreken we hoe Service Worker werkt, hoe je een manifest maakt, welke cachingstrategieën je moet gebruiken en hoe je offline toegang realiseert.
Belangrijkste
Belangrijkste
Progressive Web App (PWA) — is een benadering van webapplicatieontwikkeling die de beste kwaliteiten van het web en native apps combineert. De term werd in 2015 geïntroduceerd door Francesco Berriman en Google promoot PWA actief als vervanging voor eenvoudige mobiele apps. Het basisidee: een website wordt geleidelijk verbeterd afhankelijk van de mogelijkheden van de browser en het apparaat. Als de browser Service Worker ondersteunt — wordt de offlinemodus ingeschakeld. Als het manifest wordt ondersteund — verschijnt de knop «Installeren». Als er een meldingen-API is — kan de app pushmeldingen sturen. Een gebruiker op een zwak apparaat met langzaam internet krijgt de basisversie van de site, en op een moderne smartphone — een volwaardige app met een pictogram op het bureaublad.
PWA hoeft niet te worden geïnstalleerd via een app store. Een link is voldoende. Dit lost het grootste probleem van mobiele apps op — de hoge drempel. De gebruiker gaat niet naar Google Play of App Store, wacht niet op het downloaden van 100 MB, geeft niet tientallen machtigingen. Hij opent gewoon de site en de browser stelt voor om de app te installeren. Als de gebruiker weigert — gebruikt hij nog steeds de site. En als hij akkoord gaat — verschijnt het pictogram op het startscherm en opent de app als native: zonder adresbalk van de browser, in volledige-schermmodus en met snelle start.
Technisch moet PWA aan drie criteria voldoen: werken via HTTPS (veilige verbinding), een Service Worker (achtergrondverwerkingsscript) hebben en een manifest (Web App Manifest) bevatten. Deze drie componenten veranderen een gewone site in een installeerbare app.
Service Worker — is een JavaScript-script dat de browser in een aparte thread uitvoert, onafhankelijk van de webpagina. Het heeft geen toegang tot de DOM, kan niet rechtstreeks met de interface communiceren, maar kan netwerkverzoeken onderscheppen en wijzigen, de cache beheren, pushmeldingen verwerken en achtergrondsynchronisatie uitvoeren. Service Worker werkt als een proxyserver tussen de browser en het netwerk: elk verzoek van de pagina gaat door Service Worker, die beslist — gegevens uit de cache retourneren, van de server opvragen of beide doen.
Service Worker leeft volgens zijn eigen levenscyclus, niet gebonden aan de geopende pagina. Het wordt geïnstalleerd, geactiveerd en werkt op de achtergrond, zelfs nadat alle tabbladen van de site zijn gesloten. Dit stelt PWA in staat om pushmeldingen te ontvangen en de cache op de achtergrond bij te werken, zonder tussenkomst van de gebruiker.
Service Worker doorloopt vier fasen: registratie, installatie, activering en inactiviteit/beëindiging.
Registratie. De browser ontvangt een link naar het JS-bestand van Service Worker en begint met downloaden. Registratie wordt uitgevoerd vanuit gewone JavaScript op de pagina:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('SW geregistreerd:', registration.scope);
})
.catch(error => {
console.log('SW-registratie mislukt:', error);
});
}Installatie. Na succesvol downloaden activeert de browser de gebeurtenis install. In deze fase is het gebruikelijk om belangrijke bronnen te cachen (HTML-skelet, CSS, belangrijke afbeeldingen) zodat de app offline kan werken. Als de installatie slaagt, gaat Service Worker naar de volgende fase. Als het script een fout genereert — wordt de installatie geannuleerd en blijft de oude Service Worker werken.
self.addEventListener('install', event => {
event.waitUntil(
caches.open('pwa-cache-v1').then(cache => {
return cache.addAll([
'/',
'/index.html',
'/styles/main.css',
'/scripts/app.js',
'/images/logo.png'
]);
})
);
});Activering. Wanneer alle tabbladen van de site zijn gesloten, wordt de oude Service Worker beëindigd en wordt de nieuwe geactiveerd. De gebeurtenis activate wordt gebruikt voor het opschonen van oude caches en gegevensmigratie:
self.addEventListener('activate', event => {
const cacheWhitelist = ['pwa-cache-v2'];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (!cacheWhitelist.includes(cacheName)) {
return caches.delete(cacheName);
}
})
);
})
);
});Inactiviteit. De geactiveerde Service Worker onderschept verzoeken en verwerkt gebeurtenissen. Het kan door de browser worden gestopt om bronnen te sparen en opnieuw worden gestart bij het volgende verzoek. Service Worker is gebeurtenisgestuurd: het leeft alleen zolang het gebeurtenissen verwerkt.
Service Worker ondersteunt verschillende cachingstrategieën. De keuze hangt af van het brontype en de vereisten voor gegevensactualiteit.
Cache First (eerst cache). Eerst wordt de cache gecontroleerd. Als de bron wordt gevonden — wordt deze uit de cache geretourneerd. Zo niet — gaat het verzoek naar de server, wordt het antwoord in de cache opgeslagen. De strategie is geschikt voor statische bronnen: afbeeldingen, lettertypen, CSS, JS. Zorgt voor maximale snelheid en volledige offline werking.
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request).then(fetchResponse => {
return caches.open('pwa-cache-v1').then(cache => {
cache.put(event.request, fetchResponse.clone());
return fetchResponse;
});
});
})
);
});Network First (eerst netwerk). Het verzoek gaat eerst naar de server. Als de server antwoordt — worden de gegevens aan de gebruiker geretourneerd en in de cache opgeslagen. Als de server niet beschikbaar is — wordt de gecachte kopie geretourneerd. De strategie is geschikt voor API-verzoeken, nieuws, inhoud die actueel moet zijn maar ook offline kan werken.
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).then(response => {
return caches.open('pwa-dynamic-v1').then(cache => {
cache.put(event.request, response.clone());
return response;
});
}).catch(() => {
return caches.match(event.request);
})
);
});Stale While Revalidate (verouderd met vernieuwing). Het antwoord wordt onmiddellijk uit de cache geretourneerd, terwijl op de achtergrond een verzoek naar de server wordt gestuurd om de cache bij te werken. De gebruiker ziet de inhoud onmiddellijk en het volgende verzoek ontvangt al verse gegevens. Ideaal voor inhoud die verandert, maar waarbij het niet kritisch is als de gebruiker een versie ziet die een paar minuten oud is.
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(cached => {
const fetchPromise = fetch(event.request).then(response => {
return caches.open('pwa-dynamic-v1').then(cache => {
cache.put(event.request, response.clone());
return response;
});
});
return cached || fetchPromise;
})
);
});Het manifest — is een JSON-bestand, meestal manifest.json, dat wordt verbonden via de <link>-tag in de head van de HTML-pagina. Het vertelt de browser hoe de app moet worden weergegeven bij installatie op het apparaat: naam, pictogrammen van verschillende groottes, achtergrondkleur, themakleur, oriëntatie en weergavemodus (browser, minimale UI, volledig scherm).
{
"name": "PWA Demo App",
"short_name": "PWA Demo",
"description": "Demo PWA-applicatie",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#3f51b5",
"orientation": "portrait",
"icons": [
{
"src": "/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
]
}De parameter display bepaalt hoe de app eruit ziet na installatie. standalone verbergt de adresbalk van de browser en het navigatiepaneel — de app ziet eruit als native. fullscreen gebruikt het volledige scherm zonder browserelementen. minimal-ui laat minimale browserelementen (knoppen terug en vernieuwen) achter.
Pictogrammen moeten in ten minste twee formaten worden voorbereid: 192x192 en 512x512 pixels. PNG-formaat met ondersteuning voor de parameter purpose (bijvoorbeeld maskable) stelt de browser in staat het pictogram aan te passen aan de vorm van de behuizing van het apparaat — op Android kan het pictogram worden bijgesneden tot een afgerond vierkant. Na het aansluiten van het manifest begint Chrome op Android de banner «Toevoegen aan startscherm» te tonen bij vervulling van de voorwaarden: HTTPS, geregistreerde Service Worker, correct manifest en ten minste twee bezoeken met een interval van 5 minuten.
PWA kan pushmeldingen verzenden zoals een native app. Hiervoor worden twee API's gebruikt: Push API (serververzending) en Notification API (weergave op het apparaat). Service Worker ontvangt de push-gebeurtenis, zelfs als de app niet is geopend, en kan een melding tonen met titel, tekst en pictogram.
Om pushmeldingen te ontvangen, moet de gebruiker toestemming geven:
Notification.requestPermission().then(permission => {
if (permission === 'granted') {
console.log('Push toegestaan');
}
});Service Worker abonneert zich op de push-gebeurtenis en toont de melding:
self.addEventListener('push', event => {
const data = event.data.json();
self.registration.showNotification(data.title, {
body: data.body,
icon: '/icons/icon-192x192.png',
badge: '/icons/badge-72x72.png',
actions: [
{ action: 'open', title: 'Openen' },
{ action: 'close', title: 'Sluiten' }
]
});
});
self.addEventListener('notificationclick', event => {
event.notification.close();
if (event.action === 'open') {
clients.openWindow('/');
}
});Voor het verzenden van push vanaf de server wordt het Web Push (VAPID)-protocol gebruikt. De server versleutelt het bericht en verzendt het via de pushdienst van de browser (Firebase Cloud Messaging voor Chrome, Mozilla Autopush voor Firefox). Het abonnement van de gebruiker (PushSubscription-object) moet bij registratie op de server worden opgeslagen.
PWA moet snel zijn. Google Lighthouse — is een auditingtool die PWA controleert aan de hand van een checklist: Service Worker-registratie, antwoord 200 bij offline toegang, correct manifest, HTTPS, correcte pictogramgrootte, snel laden op langzame netwerken. Minimale slaagscore voor PWA — 80 op 100 op de Lighthouse-schaal. Apps met een score onder 80 krijgen geen installatiebanner in Chrome.
Belangrijkste prestatiemetrieken voor PWA — First Contentful Paint (FCP) tot 1,8 seconden, Largest Contentful Paint (LCP) tot 2,5 seconden, Time to Interactive (TTI) tot 3,5 seconden. Service Worker kan FCP en LCP aanzienlijk verbeteren als het kritieke HTML en CSS cached bij installatie. De strategie Cache First voor statische inhoud en Stale While Revalidate voor API geeft de beste gebruikerservaring.
Een van de belangrijkste mogelijkheden van PWA — werken zonder internet. Service Worker onderschept verzoeken en retourneert gecachte versies van pagina's. Als de gebruiker probeert een pagina te openen die niet in de cache staat, kan een aangepaste reservepagina worden getoond:
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request);
}).catch(() => {
return caches.match('/offline.html');
})
);
});Achtergrondsynchronisatie (Background Sync) stelt je in staat het verzenden van gegevens naar de server uit te stellen als het apparaat offline is. Service Worker slaat het verzoek op en verzendt het automatisch wanneer de verbinding wordt hersteld:
self.addEventListener('sync', event => {
if (event.tag === 'sync-messages') {
event.waitUntil(sendMessages());
}
});
function sendMessages() {
return caches.open('pwa-pending-v1').then(cache => {
return cache.keys().then(requests => {
return Promise.all(requests.map(request => {
return fetch(request).then(() => cache.delete(request));
}));
});
});
}Chrome DevTools biedt het paneel Application, waar je Service Worker kunt debuggen (registratie, status, cache, push), het manifest kunt controleren, de cache kunt wissen en eigen pushmeldingen voor testen kunt maken. Het tabblad Network met emulatie van de offlinemodus helpt bij het controleren van de cachewerking. Lighthouse in het paneel Audits geeft een volledige PWA-audit met aanbevelingen.
Workbox — een bibliotheek van Google die het maken van Service Worker vereenvoudigt. In plaats van handmatig cachingstrategieën te schrijven, biedt Workbox kant-en-klare modules:
import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';
precacheAndRoute(self.__WB_MANIFEST);
registerRoute(
/\.(?:png|jpg|jpeg|svg|gif)$/,
new StaleWhileRevalidate()
);Workbox integreert met bundlers (Webpack, Vite) en genereert automatisch het precache-manifest. PWA Builder (pwabuilder.com) van Microsoft genereert alle PWA-bestanden online: Service Worker, manifest, pictogrammen, HTML-sjabloon.
FAQ
PWA — is een site die na installatie op de telefoon werkt als een gewone app: pictogram op het bureaublad, offline toegang, pushmeldingen, volledige-schermmodus zonder adresbalk van de browser. Bovendien hoef je niet naar de App Store of Google Play te gaan — installatie gebeurt met één klik vanuit de browser.
Een native app wordt geschreven voor een specifiek platform (Swift voor iOS, Kotlin voor Android), vereist publicatie in een store en handmatige installatie. PWA — is een website geschreven in HTML, CSS en JavaScript, die via de browser op een apparaat kan worden geïnstalleerd. PWA neemt weinig ruimte in (alleen cache), werkt automatisch bij en wordt ondersteund door alle moderne browsers.
Chrome, Firefox, Safari (vanaf iOS 11.3), Edge, Samsung Internet, Opera. Service Worker wordt ondersteund door alle moderne browsers, behalve Internet Explorer. Safari heeft beperkte ondersteuning voor pushmeldingen, maar de basismogelijkheden van PWA (installatie op startscherm, offline toegang) werken.
Ja. Hiervoor moet je een manifest (manifest.json) toevoegen, een Service Worker (sw.js) maken en registreren, de site overzetten naar HTTPS, metatags en pictogrammen toevoegen. De site zelf hoeft niet te worden herschreven als deze op JavaScript werkt en HTML retourneert. Als de site volledig server-side is (MPA), kan Service Worker worden toegevoegd als een cachelaag zonder de architectuur te wijzigen.
Wanneer de gebruiker PWA opent, controleert de browser of het Service Worker-bestand op de server is gewijzigd. Als het bestand ten minste één byte verschilt, downloadt de browser de nieuwe Service Worker en start de installatie ervan. De oude Service Worker blijft werken totdat alle tabbladen van de app zijn gesloten. Na het sluiten van de tabbladen wordt de nieuwe Service Worker geactiveerd en vervangt de oude. De gebruiker kan de app geforceerd bijwerken door de pagina opnieuw te laden.
PWA is gerechtvaardigd als het doel is om een maximaal publiek te bereiken zonder kosten voor ontwikkeling op twee platformen, als de app geen diepe toegang tot hardware vereist (Bluetooth, NFC, camera op de achtergrond), als de inhoud vaak verandert. Voor complexe apps (games, videobewerkers) blijft een native app de voorkeur hebben. PWA wordt vaak gebruikt als aanvullend kanaal of als MVP vóór een volwaardige app.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook