Progressive Web Apps

What are Progressive Web Apps(PWA)?

Progressive Web Apps are user experiences that have the reach of the web, and are:

  • Reliable- Load instantly and never show the downasaur, even in uncertain network conditions.
  • Fast- Respond quickly to user interactions with silky smooth animations and no janky scrolling.
  • Engaging- Feel like a natural app on the device, with an immersive user experience
  • Linkable- Easily share the application via URL, does not require complex installation.
  • Installable- Allows users to add apps they find most useful to their home screen without the hassle of an app store.
  • Safe- Served via HTTPS to prevent snooping and to ensure content hasn’t been tampered with.
The main files for PWA.
  • Service Worker
  • Manifest
What are Service Workers?

A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don’t need a web page or user interaction. Today, they already include features like push notifications and background sync. In the future, service workers might support other things like periodic sync or geofencing. The core feature discussed in this tutorial is the ability to intercept and handle network requests, including programmatically managing a cache of responses.

Things to note about a Service Worker.
  • It’s a JavaScript Worker, so it can’t access the DOM directly. Instead, a service worker can communicate with the pages it controls by responding to messages sent via the postMessage interface, and those pages can manipulate the DOM if needed.
  • Service worker is a programmable network proxy, allowing you to control how network requests from your page are handled.
  • It’s terminated when not in use, and restarted when it’s next needed, so you cannot rely on global state within a service worker’s onfetch and onmessage handlers. If there is information that you need to persist and reuse across restarts, service workers do have access to the IndexedDB API.
Service Worker LifeCycle

A service worker has a lifecycle that is completely separate from your web page.

To install a service worker for your site, you need to register it, which you do in your page’s JavaScript. Registering a service worker will cause the browser to start the service worker install step in the background.

Typically during the install step, you’ll want to cache some static assets. If all the files are cached successfully, then the service worker becomes installed.

When installed, the activation step will follow and this is a great opportunity for handling any management of old caches, which we’ll cover during the service worker update section.

After the activation step, the service worker will control all pages that fall under its scope, though the page that registered the service worker for the first time won’t be controlled until it’s loaded again.

Below is a diagram of service worker lifecycle

Code for Service Worker

Service Worker Registeration:

You will paste this code in your main js file.

if ('serviceWorker' in navigator) {navigator.serviceWorker.register('./sw.js')
.then(() => {
console.log('Service Worker presents')
})
}

Sevice Worker Main file code:

You will make a file name ‘sw.js’ in the current directory and paste the code in it

const CACHE_NAME = 'blood-bank';
const urlsToCache = [
'./',
'./index.html',
'./style.css',
]
self.addEventListener('install', function (event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function (cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request)
.then(function (response) {
if (response) {
return response;
}
return fetch(event.request).then(
function (response) {
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
var responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(function (cache) {
cache.put(event.request, responseToCache);
});
return response;
}
);
})
);
});
self.addEventListener('activate', function (event) {
var cacheWhitelist = ['pages-cache-v1', 'blog-posts-cache-v1'];
event.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.map(function (cacheName) {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
async function cacheFirst(req) {
const cacheResponse = await caches.match(req);
return cacheResponse || fetch(req);
}
async function networkFirst(req) {
const cache = await caches.open(cacheName);
try {
const res = await fetch(req);
cache.put(req, res.clone())
return res
} catch (error) {
return await cache.match(req)
}
}
Manifest Code

You will make a file name manifest.json and will generate the code of it from