Progressive Web Apps

More than just killing the mighty T-REX

What this is not about?

  • A workshop
  • A deep dive about how to implement a PWA
  • A deep dive about service workers and its component
  • A live coding session

Why PWA ??

Not everyone will run your app on Google Fiber!

Why PWA ??

Not everyone owns the fastest hardware!

Why PWA ??

Lesser dropping of users!

Users are lazy and there time is too precious!

App like feel!

Why PWA ??

Push notification API to keep the user engaging!

Why PWA?

Why PWA ??

App deployment becomes

  • Simpler
  • Faster 
  • Uniform!

Dayyyyuuuummm !!!!

Why PWA ??

Offline support!!

What is PWA?

A web app which

  • Supports offline loading
  • Progressively renders a view
  • Looks like a native app
  • ​Built with an app shell model
  • ​Constantly engages with users through push notifications
  • Fully responsive
  • Is installable, so that it stays in home screen

Components of PWA

App Shell

Manifest File​

Service Workers​

Notifications

HTTPS

Promises

Fetch API

App Shell

Slides for app shell

Benefits of App Shell

The benefits of an app shell architecture with a service worker include:

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

Requirements App Shell

The app shell should ideally:

  • Load fast.
  • Use as little data as possible.
  • Use static assets from a local cache.
  • Separate content from navigation
  • Retrieve and display page-specific content (HTML, JSON, etc.)
  • Optionally, cache dynamic content

App Shell example

Web App Manifest

Web App Manifest

This is what a web app manifest  can do!

Web App Manifest

Add to home screen

Web App Manifest

Add a splash screen

Web App Manifest

Customize the Icon

Web App Manifest

What exactly is it?

The web app manifest is a simple JSON file that gives us the ability to control how our app appears to the user in areas where they would expect to see apps (for example, a mobile device's home screen), direct what the user can launch, and define its appearance at launch.

Web App Manifest

  • Creating a manifest file and linking it to your page is a straightforward process.

  • Control what the user sees when launching from the home screen.

  • This includes things like a splash screen, theme colors, and even the URL that's opened.

Web App Manifest

Lets take a look at several cool features

Web App Manifest

Web App Manifest

"display":"standalone"
"display":"browser"
"display":"fullscreen"

Web App Manifest

"theme_color":"#2196F3"

Web App Manifest

"start_url": "/?utm_source=homescreen"

Web App Manifest

So, How its look like?

So, How its look like?

Web App Manifest

{
  "name": "HackerWeb",
  "short_name": "HW",
  "start_url": ".",
  "display": "standalone",
  "background_color": "#fff",
  "description": "A simply readable Hacker News app.",
  "icons": [{
    "src": "images/touch/homescreen48.png",
    "sizes": "48x48",
    "type": "image/png"
  }, {
    "src": "images/touch/homescreen72.png",
    "sizes": "72x72",
    "type": "image/png"
  }, {
    "src": "images/touch/homescreen192.png",
    "sizes": "192x192",
    "type": "image/png"
  }],
  "related_applications": [{
    "platform": "web"
  }, {
    "platform": "play",
    "url": "https://play.google.com/store/apps/details?id=cheeaun.hackerweb"
  }]
}

Web App Manifest

Deploying a Manifest

<link rel="manifest" href="/manifest.json">

Web App Manifest

And finally, It opens the door to compete with Native apps.

Service Workers

What is a service worker?

  • Event driven web worker.
  • Runs on a completely different thread, which means no access to DOM.
  • Works like a proxy server between your client application and the network.
  • It is completely non blocking in nature, because of which no access to XHR and Local Storage.
  • Only through HTTPS.

The lifecycle of a service worker

Registering a service worker

// It is better to do which the feature detection so that
// our code doesn't start to throw error
if ('serviceWorker' in navigator)
    {
        // Path to your service worker file and also
        // the default scope of your service worker
        navigator.serviceWorker.register('./serviceWorker.js')
            .then(function(ServiceWorkerRegistration)
            {
                // Returns the ServiceWorkerRegistration object
                // Which holds the service workers which can either be
                // installing phase, waiting phase or Active phase
                console.log('Successfully registered service worker');
            })
            .catch(function(err)
            {
                console.warn('Error whilst registering service worker', err);
            });
    }
// The Service worker can lie in root directory
// but the scope can be all the files under the 'dogs'
navigator.serviceWorker.register('./serviceWorker.js', {'scope':'/dogs/'})
    .then(function(reg)
    {
        console.log('Successfully registered service worker');
    })
    .catch(function(err)
    {
        console.warn('Error whilst registering service worker', err);
    });

On re-registering the browser will detect a service worker already installed and it won't go through the process of registering/installing the same service worker again.

Installing a service worker

//sw.js

// This is the place where we will cache 
// the files required for offline
addEventListener('install',function(event)
{
    console.log('Installing service worker');
});
//sw.js

var cacheName = 'v1';

addEventListener('install',function(event)
{
    console.log('Installing service worker '+cacheName);

    // This says that the 'install' event needs to 
    // be extended until the process of caching
    // our file or any other activity we desire to do
    // is done or fails.
    event.waitUntil(
        caches
            .open(cacheName)
            .then(function(cache)
            {
                return cache.addAll(arrayOfFileToCache);
            })
        );
});

Activating a service worker

//sw.js

// Installing SW code


// This event is fired the moment installation phase 
// of the service worker is over and the service worker 
// becomes active ready to handle and intercept request
// 
// This is also the place where we would clear our cached
// file from previous service worker
addEventListener('activate',function(event)
{
    
});
//sw.js

// We would again wrap the process of deleting old cache
// within 'waitUntil' so that we can montior
// if the process of deleting old cache
// was successful or not
addEventListener('activate',function(event)
{
    var cacheWhitelist = [cacheName];
    event.waitUntil
    (
        caches.keys()
            .then(function(cacheNames)
            {
                return Promise.all
                (
                    cacheNames
                        .map(function(cacheName)
                        {
                            if(cacheWhitelist.indexOf(cacheName) === -1)
                            {
                                return caches.delete(cacheName);
                            }
                        })
                );
            })
    );
});

Service worker updation?

Considered updated if the service worker file is a byte-different

I have changed my service worker but it is still showing previous!

This is because by default only one service worker can be activated, and the new service worker is in waiting phase.

//sw.js

var cacheName = 'v1';

addEventListener('install',function(event)
{
    console.log('Installing service worker '+cacheName);

    // This says that the 'install' event needs to 
    // be extended until the process of caching
    // our file or any other activity we desire to do
    // is done or fails.
    event.waitUntil(
        caches
            .open(cacheName)
            .then(function(cache)
            {
                return cache.addAll(arrayOfFileToCache)
                    .then(function()
                    {
                        // This signifys that the new worker will instantly 
                        // replace the old service worker, once the new files
                        // are cached
                        self.skipWaiting();
                    });
            })
        );
});

Note: If using then our files are mismatch and it becomes mandatory to either forcefully refresh the browser or convey this message to the user

Serving and intercepting request

// All the request lying within the scope of the service 
// worker will be handled within the fetch event
addEventListener('fetch',function(event)
{
    event.respondWith
    (
        // Find within the cache if the url being requested is present or not
        caches.match(event.request)
            .then(function(response)
                {
                    // If the resource being requested was found in cache we respond 
                    // with the cache result
                    if (response)
                    {
                        // retrieve from cache
                        return response;
                    }
    
                    // Else we use the fetch API using the request 
                    // to contact to the network
                    // for the desired file
                    return fetch(event.request);
                })
    );    
});
  • Cache only
  • Network only
  • Cache falling back to network
  • Network falling back to cache
  • Cache then network

Benefits of service worker

  • Offline by intercepting the network request and giving us the control over the request!
  • Performance benefits
  • Background Sync
  • Listen and send Push messages
  • Notification API

Lighthouse to rescue

Lighthouse tests if your app:

  • Can load in offline or flaky network conditions
  • Is relatively fast
  • Is served from a secure origin
  • Uses certain accessibility best practices

 

Lighthouse is available as a Chrome extension for Chrome 52 (and later), and in Chrome dev tools for Chrome 60 (and later).

Demo Time

Useful links

  • https://gist.github.com/Rich-Harris/fd6c3c73e6e707e312d7c5d7d0f3b2f

  • https://www.youtube.com/watch?v=RWLzUnESylc

  • http://blog.gaborcselle.com/2012/10/every-step-costs-you-20-of-users.html

  • https://developers.google.com/web/fundamentals/instant-and-offline/service-worker/lifecycle

  • https://jakearchibald.com/2014/offline-cookbook/

  • https://developers.google.com/web/fundamentals/getting-started/primers/service-workers

  • https://addyosmani.com/blog/getting-started-with-progressive-web-apps/

  • https://developers.google.com/web/ilt/pwa/

  • https://www.youtube.com/watch?v=cmGr0RszHc8&feature=youtu.be

  • https://www.youtube.com/watch?v=3Tr-scf7trE&list=WL&index=91

  • https://www.youtube.com/watch?v=J2dOTKBoTL4

Thank you!

Progressive Web Apps

By Anirudh Modi

Progressive Web Apps

  • 424