Implementing a Progressive Web App (PWA) for Sharee Mobile: Features, Architecture, and Lessons Learned
This article explains the concept of Progressive Web Apps, compares them with native and traditional web apps, details the implementation of core PWA features such as App Manifest, Service Worker, caching strategies, push notifications, and Workbox best practices, and shares metrics, challenges, and solutions encountered during the Sharee mobile project.
Background
Progressive Web Apps (PWA) were introduced by Google at I/O 2016 and landed in 2017 as a set of web technologies aimed at narrowing the gap between web and native apps, providing app‑like experiences. Major browsers (Chrome, Safari, Firefox, Edge) support PWA, and many sites (Twitter, Starbucks, Ele.me, Sina) have reported measurable benefits such as increased user time and revenue.
West Elm saw a 15% increase in usage time and 9% revenue growth after adopting PWA.
Flipkart’s user time tripled and interaction rate rose by 40%.
In theory, any web app can become a PWA by following the standards, offering high ROI due to relatively low implementation effort. However, compatibility issues and scattered documentation have limited large‑scale adoption.
Selection
Web apps suffer from slower load times on weak networks, lack of offline access, and UI constraints, while native apps have high development costs, multiple version maintenance, and limited SEO. PWA aims to bring native‑like features to web apps.
App Types
Four app categories are compared, showing that PWA remains a web app but performs closer to native apps. The goal is not to replace native apps but to enhance web apps for better user experience.
PWA (Progressive Web App)
The official definition is quoted:
Progressive Web Apps use modern web capabilities to deliver an app‑like user experience. They evolve from pages in browser tabs to immersive, top‑level apps, maintaining the web's low friction at every moment.
PWA is not a single technology but a combination of several web technologies that together provide native‑like advantages.
Characteristics
PWA is fast, reliable, and engaging. Fast through resource caching, reliable via offline support, and engaging via immersive UI, home‑screen icons, and push notifications.
Standard Support
According to "Can I use", key technologies such as App Manifest (57.43% support) and Service Worker (72.82% support) have good coverage across browsers and OSes.
App Manifest support: 57.43%
Service Worker support: 72.82%
Notifications API support: 43.3%
Push API support: 72.39%
Background Sync: supported in Chrome 49+
Objectives
The Sharee mobile PWA aims to improve user experience, increase retention, and boost traffic.
Provide a fallback page for offline failures.
Pre‑cache static assets to speed up cold starts.
Add a persistent home‑screen entry to reduce navigation depth.
Push notifications (not yet implemented).
Metrics
Key quantitative indicators include install prompt conversion rates, desktop‑icon traffic share, and static resource load time.
PWA install click / install / cancel rates.
Desktop‑icon (home‑screen) visit proportion.
Static resource load time.
Implementation Details
The following sections describe the technical details of the PWA implementation, covering App Manifest, Service Worker, Push & Notification APIs, and Workbox best practices.
App Manifest
App Manifest is a JSON file that configures icons, name, start URL, display mode, theme color, etc. It enables adding the site to the home screen and shows install prompts.
Screen‑Persistent Icon
Configuring icons and names in the manifest reduces entry depth and provides a native‑like full‑screen experience.
Implementation
Include the manifest in the <head> :
<link rel="manifest" href="/manifest.json">Example manifest.json (truncated):
// manifest.json
{
"name": "Sharee PWA",
"short_name": "Sharee PWA",
"icons": [
{"src": "../logo/180.png", "sizes": "180x180", "type": "image/png"},
{"src": "../logo/192.png", "sizes": "192x192", "type": "image/png"},
{"src": "../logo/512.png", "sizes": "512x512", "type": "image/png"}
],
"start_url": "/?from=homescreen",
"scope": "/",
"display": "standalone",
"theme_color": "#FFF",
"background_color": "#FFF"
}
// iOS fallback meta tags
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="#fff">
<meta name="apple-mobile-web-app-title" content="Sharee PWA">
<link rel="apple-touch-icon" sizes="180x180" href="../logo/180.jpg">
<meta name="msapplication-TileColor" content="#fff">
<meta name="theme-color" content="#fff">Install Prompt
When the manifest meets certain criteria, browsers may show an install prompt. The prompt can be intercepted via the beforeinstallprompt event.
Implementation
let appPromptEvent = null;
const installBtn = document.getElementById('install-btn');
self.addEventListener('beforeinstallprompt', function(e) {
e.preventDefault();
appPromptEvent = e;
installBtn.classList.add('visible');
});
window.addEventListener('appinstalled', function() {
console.log('App installed');
installBtn.classList.remove('visible');
});
installBtn.addEventListener('click', function() {
if (appPromptEvent) {
appPromptEvent.prompt();
appPromptEvent.userChoice.then(function(result) {
if (result.outcome === 'accepted') {
console.log('User accepted install');
} else {
console.log('User declined install');
}
appPromptEvent = null;
});
}
});The beforeinstallprompt event has limited browser support; many browsers do not allow programmatic triggering.
Launch Animation
When launched from a home‑screen icon, the browser displays a splash screen based on manifest settings, smoothing the transition from white screen to content.
Service Worker
Service Worker runs in a separate thread, enabling offline capabilities, caching, and background sync.
Offline Page
Cache a fallback page during installation and serve it when network requests fail.
Implementation
const CACHE_NAME = 'sharee-v1';
const FILES_TO_CACHE = ['offline.html'];
self.addEventListener('install', e => {
console.log('[Service Worker] Install');
e.waitUntil(
caches.open(CACHE_NAME).then(cache => {
self.skipWaiting();
return cache.addAll(FILES_TO_CACHE);
})
);
});
self.addEventListener('fetch', e => {
e.respondWith(
caches.match(e.request).then(r => {
return r || fetch(e.request).then(response => {
return caches.open(CACHE_NAME).then(cache => {
cache.put(e.request, response.clone());
return response;
});
});
})
);
});
self.addEventListener('activate', function(e) {
e.waitUntil(
caches.keys().then(keyList => {
return Promise.all(
keyList.map(key => {
if (CACHE_NAME.indexOf(key) === -1) {
return caches.delete(key);
}
})
);
})
);
});Resource Caching
Static assets (CSS/JS) are cached using regex matching and a CacheFirst strategy with expiration plugins.
const cacheList = ['/static/css/', '/static/js'];
self.addEventListener('fetch', e => {
const cached = cacheList.find(c => e.request.url.indexOf(c) !== -1);
if (cached) {
e.respondWith(
caches.match(e.request).then(r => {
return r || fetch(e.request).then(response => {
return caches.open(CACHE_NAME).then(cache => {
if (cached) cache.put(e.request.url, response.clone());
return response;
});
});
})
);
}
});Push API & Notification API
PWA can send push notifications using the Push API and display them via the Notification API, both built on Service Worker.
Notification Example
self.registration.showNotification('PWA-Book-Demo test actions', {
body: 'Like button clickable',
actions: [{action: 'like', title: 'Like', icon: '/assets/images/like-icon.png'}]
});
self.addEventListener('notificationclick', function(e) {
e.notification.close();
if (e.action === 'like') {
console.log('Like button clicked');
} else {
console.log('Notification clicked');
}
});Push Example
self.addEventListener('push', function(e) {
if (!e.data) return;
let payload = e.data.text();
let promise = self.registration.showNotification(payload.title, {
body: payload.body,
icon: payload.icon,
data: {url: payload.url}
});
e.waitUntil(promise);
});
self.addEventListener('notificationclick', function(e) {
e.notification.close();
e.waitUntil(self.clients.openWindow(e.data.url));
});Workbox Best Practices
Workbox simplifies Service Worker development by providing libraries for precaching, routing, and caching strategies.
Import Workbox
importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.2.0/workbox-sw.js');Precaching
workbox.core.setCacheNameDetails({prefix: 'sharee', suffix: 'v1', precache: 'precache', runtime: 'runtime'});
workbox.routing.precacheAndRoute([
{url: '/index.html', revision: 'asdf'},
'/index.abc.js',
'/index.bcd.css'
]);Routing & Strategies
Register routes with matching rules (string, RegExp, or custom function) and apply strategies such as CacheFirst, NetworkFirst, StaleWhileRevalidate, etc.
workbox.routing.registerRoute(/\.(jpe?g|png)/, new workbox.strategies.CacheFirst({
cacheName: 'image-runtime-cache',
plugins: [new workbox.expiration.Plugin({maxAgeSeconds: 7*24*60*60, maxEntries: 10})],
fetchOptions: {mode: 'cors'}
}));Testing PWA
Use Chrome Lighthouse (Audits → Progressive Web App) to generate a report covering installability, offline support, performance, and best‑practice compliance.
Production Issues
Common problems include cache failures due to cross‑origin requests and SecurityError when drawing tainted images onto a canvas. Solutions involve ensuring CORS headers, using crossOrigin="anonymous" on images, and updating cached assets with new version identifiers.
Join Us
The ByteDance Internationalization team works on a wide range of front‑end technologies, including PWA, SSR, micro‑frontends, serverless, and edge computing. They invite engineers to apply via [email protected] with the email subject "Name - Experience Years - Frontend Internationalization".
References
Can I use – https://caniuse.com/
Add Manifest – https://web.dev/add-manifest/
Install criteria – https://web.dev/install-criteria/
Notifications API – https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API
Push API – https://developer.mozilla.org/en-US/docs/Web/API/Push_API
Service Worker API – https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
Workbox Expiration Plugin – https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-expiration.ExpirationPlugin
Google PWA demo – https://airhorner.com/
iOS compatibility – https://github.com/GoogleChromeLabs/pwacompat/
Workbox repository – https://github.com/GoogleChrome/workbox/
Welcome to follow ByteFront ByteFE!
Contact: [email protected]
ByteFE
Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.