Progressive Web Application (PWA) A Beginner’s guide

Abhishek Ankush
7 min readSep 23, 2020

Progressive Web Apps(PWA) could be next big thing for Mobile web development. Introduced by Google in 2015, PWA have shown great potential using best of capabilities from Native apps and Mobile web applications providing a massive win for the application’s user experience.

What is PWA ?

A PWA is a mobile web application build with common web technologies including HTML, CSS and JavaScript with capabilities like working offline, Push notification, Device Hardware access, easy access from Native apps.

In other words PWA is a web application but better:

  1. Progressive and Responsive: Every User, Every Browser, Every Device
  2. Connectivity Independent: Offline and low quality network mode
  3. App like experience: App style navigation and easy home screen launch
  4. Fast & Fresh Data: Always up-to-date
  5. Device Hardware access: Camera and geolocation api access
  6. Linkable and Discoverable: Sharing possible with URL & indexed by SEO
  7. Engaging: Push-notification support for user engagement
Feature Comparison between PWA, Native App & Responsive web application

Core Building Blocks for PWA

  1. Service Workers: For Offline Support
  2. Web App Manifest file: For Home screen access
  3. Application Shell Architecture: For different screen/device support
  4. Push Notification: For keeping user engaged

Service Workers: The Brain of PWA

A service worker is an event-driven worker registered against an origin and a path. It takes the form of a JavaScript file that can control the web-page/site that it is associated with, intercepting and modifying navigation and resource requests, and caching resources in a very granular fashion to give you complete control over how your app behaves in certain situations helping the application to work offline or in low network.

Web page make a request service worker intercepts the same and check if the response is already avaiable in cache and respond
Service worker Placement

Service worker behaviors:

  1. Runs in different threads from the main JavaScript that empowers your app
  2. Runs in its own global context
  3. Designed to be fully asynchronous; therefore, it doesn’t have access to things such as synchronous XHR and Local Storage
  4. Runs in worker context — thus, it doesn’t have access to DOM
  5. Runs HTTPS-Only in production, in addition to Localhost for development
  6. Runs in 1:1 scope, meaning there can be only one Service Worker per scope
  7. Can be terminated any time

Service Workers Lifecycle:

  1. Register — when the user navigates to the website, by calling the register() function , the browser detects the Service Worker JavaScript file; therefore, it downloads, parses, and the execution phase begins
  2. Install — This is the best place to precache all of the static assets. Keep in mind that an install event happens only the first time after registration.
  3. Activate — This event activates the newly registered Service worker and start using the same for the application. This is also the good time to clean up old caches and other things associated with the previous version of your service worker
  4. Idle — once install and activate events are completed with no errors, Service Worker will be effective. However, if it fails during installation, activation, or is replaced by a new one, it remains redundant and does not affect the app
Service worker Lifecycle

Service workers can be configured to work in a certain way. When a certain request in not cached Service worker can be told to cache the request response after fetching the same from Server. This will help in reducing the duplicate calls for same request for next time.

const CACHE_NAME = ‘My PWA cache’;
const FILES_TO_CACHE = [
‘/index.html’,
‘/main.js’,
‘/main.css’,
‘/delete.svg’,
‘/404.html’,
‘/offline.html’
];

self.addEventListener(‘install’, event => {
console.log(‘attempting to install service worker and cache static assets’);
event.waitUntil(
caches.open(CACHE_NAME).then(cache => {
console.log(‘Opened cache’);
return cache.addAll(FILES_TO_CACHE)
})
)
});

self.addEventListener(‘activate’, event => {
console.log(`activating a new service worker`);
const cacheWhiteList = [FILES_TO_CACHE];

event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhiteList.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
)
})
)
})

self.addEventListener(‘fetch’, event => {
console.log(`fetch event for ${event.request.url}`);
event.respondWith(
caches.match(event.request.url).then(
response => {
if (response) {
console.log(`found ${event.request.url} in cache`);
return response;
}
console.log(‘network request for ‘, event.request.url);
return fetch(event.request).then(response => {
if (response.status === 404) {
return caches.match(‘404.html’);
}
return caches.open(CACHE_NAME).then(cache => {
cache.put(event.request.url, response.clone());
return response;
})
}).catch( error => {
console.error(‘error in fetching’, error);
return caches.match(‘offline.html’);
}
);
}
).catch(error => {
console.error(error);
})
)
})

Web App Manifest file

Web App Manifest file helps the web application to enable the functionality of add to Home screen. This is a JSON text file following Web App Manifest specification that provides information about an application such as its name, author, icons, and description. This file enables an application to be installed by a user on their device and allows us to modify the theme, URL that should be opened, splash screen, icons on home page etc. Below are few important attributes from the same:

name: a readable name for the app displayed to user or as a label for an icon

short_name: short name that replaces name if that doesn’t fit due to insufficient space

theme_color: defines the default theme color

background_color: defines the expected background color for the app even before user agent loads website style sheets

display: preferred display mode for the website

scope: Defines the scope for PWA

start_url: the URL that loads when a user launches the application

Icons: an array of image files that specifics the app icons depending on the context

{

“name”: “Basic PWA”,

“short_name”: “PWA”,

“lang”: “en”,

“start_url”: “/”,

“display”: “fullscreen”,

“theme_color”: “#c2f442”,

“background_color”: “#c2f442”,

“icons”: [{

“src”: “delete.svg”,

“sizes”:”150x150"

}]

}

Application Shell Architecture

An Application Shell(or app shell) Architecture is one way to build a Progressive Web App that reliably and instantly loads on your users’ screens, similar to what you see in native applications.

The app “shell” is the minimal HTML, CSS and JavaScript required to power the user interface and when cached offline can ensure instant, reliably good performance to users on repeat visits. This means the application shell is not loaded from the network every time the user visits. Only the necessary content is needed from the network

Benefits:

  • Reliable performance that is consistently fast
  • Native-like interactions
  • Economical use of data

So Put another way, the app shell is similar to the bundle of code that you’d publish to an app store when building a native app. It is the skeleton of your UI and the core components necessary to get your app off the ground, but likely does not contain the data.

Push Notification Architecture

A notification is a message that pops up on the user’s device. Notifications can be triggered locally by an open application, or they can be “pushed” from the server to the user even when the app is not running. They allow your users to opt-in to timely updates and allow you to effectively re-engage users with customized content.

Push notification examples

Push Notifications are assembled using two APIs:

Notifications API: Lets the app display system notifications to the user.

Push API: This allows a service worker to handle Push Messages from a server, even while the app is not active.

The Notification and Push API’s are built on top of the Service Worker API, which responds to push message events in the background and relays them to the application.

Subscription workflow steps:

Grant: User Grants permission

Application ask for subscription: The app asks a web push service for a PushSubscription object

Web push service returns subscription object: The web push service returns the PushSubscription object

App sends push notification: We define actions triggering push notification and app server pushes notification based on subscription

Service worker receives notification: Service worker on client receives notifications and show it to user.

Push Notification Subscription

Offline mode support:

Service worker uses different offline storage on user’s device to serve request in offline mode:

sessionStorage: maintains a separate storage area for each given origin for the duration of Session

localStorage: maintains a separate storage area for each given origin even when browser is closed and reopened

Cache: for the network resources necessary

IndexedDB: to store application state and data set

Offline mode support

Criteria’s for Adding to Home screen (A2HS):

  1. Serve over HTTPS (this was one of the PWA core concepts and required for Service Worker).

2. Web Manifest file has “name” or “short_name”, “Icon” of 192px and a 512px sizes icons, “start_url”, “display” must be fullscreen, standalone, or minimal-ui

3. The web app is not already installed

4. App has a registered Service Worker with a fetch event handler

Debugging and Measurement tools

Debugging of PWA application can be done with below two good tools:

Chrome Dev tools:

Google Lighthouse:

Google Lighthouse

Thankyou !! Happy Learning

--

--