Creating app like experiences with Progressive Web Apps
What exactly are these progressive web apps?
A Progressive Web App uses 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.
Progressive Web Apps are:
- Progressive - Work for every user, regardless of browser choice because they’re built with progressive enhancement as a core tenet.
- Responsive - Fit any form factor, desktop, mobile, tablet, or whatever is next.
- Connectivity independent - Enhanced with service workers to work offline or on low quality networks.
- App-like - Use the app-shell model to provide app-style navigations and interactions.
- Discoverable - Are identifiable as “applications” thanks to W3C manifests and service worker registration scope allowing search engines to find them.
- Re-engageable - Make re-enngagement easy through features like push notifications.
- Installable - Allow users to “keep” apps they find most useful on their home screen without the hassle of an app store.
- Linkable - Easily share via URL and not require complex installation.
Easy reengagement
Motivation
Problems?
- Not easily discoverable
- Don't exactly live on the web
- Involve going to a store (sometimes multiple) to get the app
- Slow iteration pace
- Complex packaging
25
average apps used per month by a mobile user
100+
web sites navigated per month by the average mobile user
Fiksu CPI Index
Installs have a cost
In a consumer mobile app, every step you make a user perform before they get value out of your app will cost you 20% of users.
So how do we do it?
- WebApp manifests
- Service Workers
- Add to homescreen application banner
- Push notifications for re-engagement
WebApp Manifest
The Manifest for Web applications is a simple JSON file that gives you, the developer, the ability to control how your app appears to the user in the areas that they would expect to see apps (for example the device home screen), direct what the user can launch and more importantly how they can launch it
Sample
{
"name": "My Funky APP",
"short_name": "MFA",
"icons": [{
"src": "images/touch/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
}, {
"src": "images/touch/apple-touch-icon.png",
"sizes": "152x152",
"type": "image/png"
}, {
"src": "images/touch/ms-touch-icon-144x144-precomposed.png",
"sizes": "144x144",
"type": "image/png"
}, {
"src": "images/touch/chrome-touch-icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
}],
"start_url": "/index.html?homescreen=1",
"display": "standalone",
"background_color": "#3E4EB8",
"theme_color": "#2F3BA2"
}
App install banners
How do I get them?
- Have a WebApp Manifest
- Be served over HTTPS (see letsencrypt for a free certificate)
- Have a valid service worker registered
- Be visited twice, with at least 5 minutes between visits
Service Workers
A service worker is a script that runs in the background of your page and responds to events and network requests.
Basic architecture
- The service worker URL is fetched and registered via serviceWorkerContainer.register().
- If successful, the service worker is executed.
- When the user navigates to a page controlled by the service worker it is installed
- After instalation the service worker is activated (this is a good place for cleanup of previously cached resources).
- The service worker now has control of pages opened after the register() call
Registering a service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
};
Lets do some caching
this.addEventListener('install', function(event) {
event.waitUntil(
caches.open('v1').then(function(cache) {
return cache.addAll([
'/sw-test/',
'/sw-test/index.html',
'/sw-test/style.css',
'/sw-test/app.js',
'/sw-test/image-list.js',
'/sw-test/star-wars-logo.jpg',
'/sw-test/gallery/',
'/sw-test/gallery/bountyHunters.jpg',
'/sw-test/gallery/myLittleVader.jpg',
'/sw-test/gallery/snowTroopers.jpg'
]);
})
);
});
this.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request);
);
});
Other options for responding to requests
// respond with a custom reply
new Response('<p>Hello from your friendly neighbourhood service worker!</p>', {
headers: { 'Content-Type': 'text/html' }
});
// go out to the network to fetch the actual data in case we couldn't generate a reply
fetch(event.request);
// or maybe go to a fallback in case we can't access the network
caches.match('/fallback.html');
Going for a cache first approach
this.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).catch(function() {
return fetch(event.request).then(function(response) {
return caches.open('v1').then(function(cache) {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
Demo
References
Thank you
Questions?
Creating app like experiences with Progressive Web Apps
By Alex Bularcă
Creating app like experiences with Progressive Web Apps
- 971