Four key PWA technologies you can start using right now

For an introduction to PWAs and a business case for why we should start using them, please take a look at my previous article: An Introduction to Progressive Web Apps.

Progressive Web Apps are a new set of technologies and guidelines which allow web developers to create engaging and performant web applications that can compete with native mobile apps. In this article I’m going to talk through some of the technologies which are available to us, outline browser support for each of the features and show a few code snippets which make use of the APIs a little.

Barely in its infancy, the technology is already reaping benefits for some large businesses. Companies like Alibaba and Flipkart have seen a significant increase in retention and conversion rates thanks to PWA. It is likely to have even greater benefits for people in developing countries using 2G and 3G networks on devices with little storage by providing them with faster and more reliable access to the web. It would make sense for many businesses tapping to these markets to take advantage of PWAs as well.

With this in mind, learning how to use Progressive Web Apps now, while the technology is still in its early stages, will help you get ahead of the curve and acquire valuable skills that will be increasingly in demand as PWAs take off.

Service Workers

Service workers are an integral part to making your PWA and arguably the most important technology as some of the APIs listed below are reliant on having an installed Service Worker.

It is essentially a script which is created by web developers that can be installed on the user’s browser and grants access to do actions in the background that developers wouldn’t usually be able to do. For example, it can act as a middle tier and intercept requests to the server, or run background tasks to sync data from a server to update the cache, or listen to push notifications. All of this can be done when the browser isn’t open on the device, so it’s a very powerful item in your toolbox.

The most common use of a service worker is to enable offline support and to improve speed of your site. Your service worker can be setup to intercept requests from the client to the server, check if the resource is stored in your app cache and deliver the cached resource instead of making a request to the server. This is exactly how you enable offline support on your app. If you couple Service Workers with IndexDB, you can make an app which caches data as well as the main site files to make a truly offline app.

This is a topic that can go into a lot of detail, so we will follow it up in another article with code samples and instructions on writing one from scratch. In the meantime, check out sw precache which is a node script that will scrape your site and generate a service worker to automatically cache the static resources and enable offline.

This is a quick win for any website, as it provides a massive speed boost for revisiting users and makes navigating between pages very quick. For us at Toaster, we try to implement service workers for caching on all of our sites, as we follow the PRPL pattern. Caching content before it’s needed is a great way keeping the time to first paint fast, and makes future requests quick too.

Current support for service workers is not great across Microsoft and Apple browsers, however they are gaining traction and they are currently in development in Edge, and it is mentioned in Apple’s 5 year plan. Check Jake Archibald's Service Worker Ready? page.

Source: http://caniuse.com/#feat=serviceworkers

Using the manifest.json file and meta tags to configure your app name and icon.

The manifest.json file is a fairly basic json file which contains configuration options for what your app would look like on the home screen. Here’s the example from the Toaster site:

{
  "name": "Toaster",
  "short_name": "Toaster",
  "icons": [{
      "src": "static/favicons/android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    }, {
      "src": "static/favicons/android-chrome-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    }, {
      "src": "static/favicons/android-chrome-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    }, {
      "src": "static/favicons/android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    }, {
      "src": "static/favicons/icon-256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    }],
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "#141414",
  "theme_color": "#141414"
}

Name and short_name: the name is used when opening the app, and the shortname is used underneath the icon when sitting amongst the icons.
Icons: A list of different sized app icons, which would be displayed on the home screen.
Start_url: This is the page that will open up if the user clicks on your home page icon. This is useful if you want to add some analytics, for example ?utm_source query strings would work here, or if you wanted to deliver a different landing page for your app mode.
Display: This is an option to decide if you want the app to open without the address bar, or to open with the standard browser chrome.
Background_color: This can be used to define a colour when the user firsts opens up the app before the stylesheet is loaded. In most cases, it would be the background colour of the splash screen.
Theme_color: The colour of the bar when the users views the browser tabs.

You can also check the full list of options.

The manifest.json is only used for the Chrome browser at the moment, however other browsers may look into using it in the future too. In the meantime, you can achieve the same effect in other browsers using meta tags. For example Apple’s method of setting the app icon is as follows:

<link rel="apple-touch-icon" href="touch-icon-iphone.png">
<link rel="apple-touch-icon" sizes="152x152" href="touch-icon-ipad.png">
<link rel="apple-touch-icon" sizes="180x180" href="touch-icon-iphone-retina.png">
<link rel="apple-touch-icon" sizes="167x167" href="touch-icon-ipad-retina.png">

Note that at the time of writing iOS Safari does not support Service Workers, so these users will not benefit from offline support or notifications.

Notifications API

The notifications API is used for creating customised notifications. The API allows you to configure settings such as the image, title, description, a prompt / CTA and much more. For a notification to work, one of the requirements is you have a Service Worker installed. A basic example would look something like this:

if (Notification.permission = 'granted') {
  navigator.serviceWorker.getRegistration().then(function(reg) {
    var options = {
      body: 'Notification description!',
      icon: 'images/notification-icon.png',  
    };

    reg.showNotification('Hello world!', options);
  });
}

You can prompt the request permission dialog, by running the requestPermission method:

Notification.requestPermission(function(status) {      
    // status is "granted", if accepted by user
});

There are loads of options, spanning from defining a vibration pattern to setting a sound and even creating some actions.

You’re then able to listen to notification events in the service worker and be notified when the user interacts with a notification.

self.addEventListener('notificationclose', function(e) {
  var notification = e.notification;

  // Add some behaviours here, eg: some analytics
});


self.addEventListener('notificationclick', function(e) {

  var notification = e.notification;
  var id = notification.data.id;

  var action = e.action;

  if (action = 'trackOrder') {
    clients.openWindow('orders/' + id);
  }

  notification.close();
});

Web notifications are currently not well supported on mobile, however desktop browsers are a different story. Note that web notifications are different to the notifications shown on a user’s lock screen. Those notifications are handled by the Push API (which is up next).

Source: http://caniuse.com/#feat=notifications

Push API

The push API allows a service worker to listen to incoming push messages. Setting up a push notification server is an article in itself, so I won’t go over it here. But essentially, in your service worker, it’s possible to add an event listener for push events, and provide functionality to display a notification using the Notification API. For example:

self.addEventListener('push', function(e) {
  var options = {
    body: 'This notification was generated from a push',
    icon: 'images/notification.png'
  };
  e.waitUntil(
    self.registration.showNotification('Push notification', options)
  );
});

Find more information here. Stay tuned for a following article about setting up a notification server and an end to end example of setting up Push Notifications.

The Push API has better support across modern browsers, however Apple and Microsoft are lagging behind on this one.

Source: http://caniuse.com/#feat=push-api

Wrap up

There you have it! These are the technologies which are making it possible for Web Developers to compete with the native applications market. By far, the most important is the service worker, as the other APIs are reliant on having a service worker installed.

You don’t need to integrate all of the above to create a PWA; you can pick and choose what is important to your website. Not all sites are going to need Web Notifications for example. However here at Toaster we build a fair number of sites which include a countdown to an event or a product launch so we would use Push Notifications to remind users that an event is starting.

What we do recommend on every site is utilising Service Workers to cache your application, as this can give a huge speed increase for returning visitors or for users navigating between pages on your site.

Progressive Web Apps are progressive (the clue is in the title). Progressive enhancement is a great technique for us developers to use new technology while maintaining support for older browsers. While you can’t rely on these technologies working everywhere, they will give users on newer browsers a much faster and more enjoyable experience.

These technologies are gaining a lot of traction in the web world, and it won’t be long before all the major browsers support the technologies to create a true progressive web app. There’s no reason why you can’t start now though. These features are progressive after all and can be used today.

Stay tuned for future posts from us at Toaster, as we plan to cover all of these technologies in more detail. Articles on Service Workers and caching strategies, Web Notifications and testing your PWA with Lighthouse are coming soon!