Progressive Web Applications

Przemek Suchodolski / @przemuh / przemuh.pl

About me

is hiring
is hiring

First task

One app - three platforms
  • Web
  • Android
  • iOS
  • Hybrid / WebView / PhoneGap 💀
  • Compile JS to native (React Native) 🚀
  • PWA 🎉

Stats

Share of Digital Media Time Spent

comScore Media Metrix Multi-Platform & Mobile Metrix, U.S., Total Audience, June 2017

Share of Time Spent on Mobile: App vs. Web

Source: comScore Mobile Metrix, U.S., Age 18+, June 2017

Average Monthly Minutes per Visitor

Source: comScore Mobile Metrix, U.S., Age 18+, June 2017

Average Monthly Unique Visitors (MM)

Source: comScore Mobile Metrix, U.S., Age 18+, June 2017

Every step = 20%

2015

  • Frances Berriman (designer)
  • Alex Russell (Google Chrome engineer)

Progressive Web Apps: Escaping Tabs Without Losing Our Soul

PWA characteristic

  • Responsive
  • Connectivity independent
  • App-like-interactions
  • Fresh
  • Safe
  • Discoverable
  • Re-engageable
  • Installable
  • Linkable

PWA characteristic TL;DR

  • Reliable
  • Fast
  • Engaging

PWA checklist

  • Site is served over HTTPS
  • Pages are responsive on tablets & mobile devices
  • The start URL (at least) loads while offline
  • Metadata provided for Add to Home screen
  • First load fast even on 3G
    (WebPageTest (aim for <4000 first view on Mobile 3G Nexus 5 Chrome)
  • Site works cross-browser
  • Page transitions don't feel like they block on the network

Reliable / Connectivity independent

Service Worker

Register


                    if('serviceWorker' in navigator) {
                        navigator.serviceWorker.register('/service-worker.js');
                    }
                

Install event


self.addEventListener('install', event => {
   event.waitUntil(
       caches.open(CACHE_NAME)
           .then(cache => {
               const urlsToCache = [
                    "/",
                    "main.js",
                    "images/david.jpg"
               ];
               cache.addAll(urlsToCache);
           })
   );
});
                

Fetch event


self.addEventListener('fetch', function(event) {
   event.respondWith(
       caches.match(event.request).then(function(response) {
           return response || fetch(event.request);
       })
   );
});
                    

SW Precache Webpack Plugin


                { ...

                    plugins: [
                        new SWPrecacheWebpackPlugin(
                          {
                            cacheId: 'my-project-name',
                            dontCacheBustUrlsMatching: /\.\w{8}\./,
                            filename: 'service-worker.js',
                            minify: true,
                            navigateFallback: PUBLIC_PATH + 'index.html',
                            staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
                          }
                        ),
                      ]

                ...}
                

Fresh / Background sync

Sync registration


                    navigator.serviceWorker.ready.then(function(registration) {
                      registration.sync.register('outbox').then(function() {
                        // registration succeeded
                      }, function() {
                        // registration failed
                      });
                    });
                

Respond to sync


                    self.addEventListener('sync', function(event) {
                      if (event.tag == 'outbox') {
                        event.waitUntil(sendEverythingInTheOutbox());
                      }
                    });
                

Periodical sync


                    navigator.serviceWorker.ready.then(function(registration) {
                      registration.periodicSync.register({
                        tag: 'get-latest-news',         // default: ''
                        minPeriod: 12 * 60 * 60 * 1000, // default: 0
                        powerState: 'avoid-draining',   // default: 'auto'
                        networkState: 'avoid-cellular'  // default: 'online'
                      }).then(function(periodicSyncReg) {
                        // success
                      }, function() {
                        // failure
                      })
                    });
                

Debugging

Engaging / Native experience

Push notification


                    self.addEventListener('push', function(event) {
                       console.log('Received a push message', event);

                       const title = 'Yay a message.';
                       const body = 'We have received a push message.';
                       const icon = '/images/icon-192x192.png';
                       const tag = 'simple-push-demo-notification-tag';

                       event.waitUntil(
                           self.registration.showNotification(title, {
                               body: body,
                               icon: icon,
                               tag: tag
                           })
                       );
                    });
                

Adding to home screen

Manifest.json


                    {
                       "name": "Meet Js",
                       "short_name": "mjs",
                       "icons": [
                           {
                               "src": "/android-chrome-192x192.png",
                               "sizes": "192x192",
                               "type": "image/png"
                           },
                           {
                               "src": "/android-chrome-512x512.png",
                               "sizes": "512x512",
                               "type": "image/png"
                           }
                       ],
                       "theme_color": "#f9a20c",
                       "background_color": "#ffffff",
                       "display": "standalone"
                    }
                

Fast / Performance

Case studies

Limitations ?

Take away

  • Each step - 20% vs PWA distribution
  • Reliable - Fast - Engaging
  • Progressive

Thank you

Questions ?