PWA
Ionic apps are web apps wrapped in Capacitor for native targets, which means the same codebase ships as a Progressive Web App with almost no extra work. PWA gives you: an installable home-screen icon, offline service-worker caching, push notifications (Android/desktop), and a Lighthouse-friendly score that helps SEO.
PWA manifest, service worker, and install prompt
EXAMPLE
// 1) manifest.webmanifest — describes the installable app
{
"name": "Shop",
"short_name": "Shop",
"description": "Lightweight Shop client",
"start_url": "/",
"display": "standalone",
"orientation": "portrait",
"background_color": "#ffffff",
"theme_color": "#2563eb",
"icons": [
{ "src": "/icons/192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/512.png", "sizes": "512x512", "type": "image/png" },
{ "src": "/icons/maskable-512.png", "sizes": "512x512", "type": "image/png",
"purpose": "maskable" }
]
}
<!-- index.html: link the manifest and theme colour -->
<link rel='manifest' href='/manifest.webmanifest'>
<meta name='theme-color' content='#2563eb'>
// 2) service-worker.ts (Workbox-style) — cache shell + runtime cache
import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { CacheFirst, StaleWhileRevalidate, NetworkFirst } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';
precacheAndRoute(self.__WB_MANIFEST);
registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({
cacheName: 'images',
plugins: [new ExpirationPlugin({ maxEntries: 100, maxAgeSeconds: 30 * 24 * 60 * 60 })],
}),
);
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({ cacheName: 'api', networkTimeoutSeconds: 3 }),
);
registerRoute(
({ request }) => ['style', 'script', 'worker'].includes(request.destination),
new StaleWhileRevalidate({ cacheName: 'assets' }),
);
self.addEventListener('install', () => self.skipWaiting());
self.addEventListener('activate', () => self.clients.claim());
// 3) Register the service worker once the page is ready
// src/main.ts
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js');
});
}
// 4) Custom install prompt — beforeinstallprompt is Chrome/Edge only
let deferred: any = null;
window.addEventListener('beforeinstallprompt', (e: Event) => {
e.preventDefault();
deferred = e;
showInstallButton();
});
document.getElementById('install-btn')?.addEventListener('click', async () => {
if (!deferred) return;
deferred.prompt();
const choice = await deferred.userChoice;
console.log(choice.outcome); // 'accepted' or 'dismissed'
deferred = null;
});
// 5) iOS install — Safari does not implement beforeinstallprompt.
// Show your own instructions: 'Tap Share -> Add to Home Screen'.
Why it matters
Aim for a perfect 100 PWA Lighthouse score before shipping — Chrome will only offer the install prompt to users when the page passes its installability checks. A missing maskable icon, a non-HTTPS asset, or a missing start_url all silently disqualify you.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
// In index.html <link rel="manifest" href="/manifest.json"> // Register a service worker. Ionic ships PWA-ready by default.Try it Yourself »
Discussion
Loading…