Progressive Web Apps in the Real World

Progressive Web Apps in the Real World

This workshop was first presented at Devoxx UK Conference on the 8th June 2016.

http://cfp.devoxx.co.uk/2016/speaker/dean_hume

Presentation Details
----------------------------------

As web developers, we are constantly striving to provide our users with the best possible browsing experience. Regardless of their device, our aim is to provide them with resilient, performant websites that just work. Imagine if you could take this to the next level and provide your users with a super fast website with a similar experience to native applications. This is where Service Workers come in.

They are a promising game changer that provides developers with powerful features such as offline browsing, periodic background syncs, and push notifications to name just a few!

This talk will dive into Progressive apps and showcase some of the features that are available for developers to start using today.

Topics include:
- The basics of Service Workers
- Eliminating third-party single points of failure
- Supercharging your caching
- Implement offline browsing
- Push notifications on the web
- Background Sync
- How to debug your Service Worker and much more!

In this talk, we will run through working a few working examples and explore the ins and outs of Progressive. This talk is aimed at all web developers regardless of skill level - there is something for everyone!

For more information visit http://deanhume.com

C620790ae5bf5b50c245b2e0ef95f338?s=128

Dean Hume

June 08, 2016
Tweet

Transcript

  1. PROGRESSIVE WEB APPS in the real world

  2. Dean Hume @deanohume

  3. A Progressive Web App uses modern web capabilities to deliver

    an app-like user experience “
  4. CORE DRIVERS

  5. CORE DRIVERS URLS & Links

  6. CORE DRIVERS URLS & Links System Capabilities

  7. CORE DRIVERS URLS & Links Accessible System Capabilities

  8. CORE DRIVERS URLS & Links Accessible System Capabilities Free!

  9. These apps aren’t packaged and deployed through stores, they’re just

    websites that took all the right vitamins. Alex Russell “
  10. Awesome

  11. NO INSTALL NEEDED Awesome

  12. NO INSTALL NEEDED NO DOWNLOAD Awesome

  13. NO INSTALL NEEDED NO DOWNLOAD BUILT ON THE FABRIC OF

    THE WEB Awesome
  14. You are already using them

  15. What does this actually mean for our users?

  16. What does this actually mean for our users? ★ More

    engaging
  17. What does this actually mean for our users? ★ More

    engaging ★ Faster
  18. What does this actually mean for our users? ★ More

    engaging ★ Faster ★ Reliable
  19. None
  20. This Talk

  21. This Talk 1. Understanding Progressive Web Apps

  22. This Talk 1. Understanding Progressive Web Apps 2. Engage your

    users
  23. This Talk 1. Understanding Progressive Web Apps 2. Engage your

    users 3. Speed up your site
  24. This Talk 1. Understanding Progressive Web Apps 2. Engage your

    users 3. Speed up your site 4. Improve reliability
  25. Understanding progressive web apps 1

  26. Service workers

  27. Think of your web apps requests as planes taking off.

    ServiceWorker is the air traffic controller that routes the requests. Jeff Posnick “
  28. “The perfect progressive enhancement.”

  29. Behind the scenes

  30. With Service Workers

  31. With Service Workers

  32. With Service Workers

  33. With Service Workers

  34. HTTPS Only

  35. Free SSL

  36. None
  37. Service Workers are the key to unlocking the power

  38. Support

  39. The Approach

  40. The Approach App. Shell Architecture

  41. The Approach Pick & Choose App. Shell Architecture

  42. Application Shell Architecture

  43. None
  44. bit.ly/app-shell

  45. Or pick & choose the features you like!

  46. operasoftware.github.io/pwa-list

  47. Summary ❖ Service Workers ❖ SSL only ❖ Architecture

  48. 2.Engage your users

  49. 2.1 Look and feel

  50. 2.1 Look and feel 2.2 Push notifications

  51. 2.1 Look and feel 2.3 Add to home screen 2.2

    Push notifications
  52. Look and feel

  53. Look and feel <!-- Chrome, Firefox OS and Opera -->

    <meta name="theme-color" content="#09adec"> <!-- Windows Phone --> <meta name="msapplication-navbutton-color" content=" #09adec"> <!-- iOS Safari --> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
  54. Look and feel bit.ly/color-custom

  55. Manifest A simple JSON file that allows you to control

    how your app appears to the user
  56. { lang: "en", background_color: "#09adec", name: "Building Great Startup Teams",

    short_name: "Building Great Startup Teams", display: "standalone", icons: [ { src: "./images/logo-144.png", sizes: "144x144", type: "image/png" } ], start_url: "./index.html", orientation: "portrait" }
  57. { lang: "en", background_color: "#09adec", name: "Building Great Startup Teams",

    short_name: "Building Great Startup Teams", display: "standalone", icons: [ { src: "./images/logo-144.png", sizes: "144x144", type: "image/png" } ], start_url: "./index.html", orientation: "portrait" }
  58. Customize

  59. { lang: "en", background_color: "#09adec", name: "Building Great Startup Teams",

    short_name: "Building Great Startup Teams", display: "standalone", icons: [ { src: "./images/logo-144.png", sizes: "144x144", type: "image/png" } ], start_url: "./index.html", orientation: "portrait" }
  60. <!doctype html> <html lang="en"> <head> <link rel="manifest" href="manifest.json"> </head> <body>

    </body> </html>
  61. Manifest bit.ly/manifest-json

  62. Manifest Generator tomitm.github.io/appmanifest

  63. Push Notifications

  64. None
  65. Three Steps 1. Subscribe User

  66. Three Steps 1. Subscribe User 2. Save Subscription

  67. Three Steps 1. Subscribe User 2. Save Subscription 3. Send

    from Google Cloud
  68. Subscribe User

  69. if ('serviceWorker' in navigator) { }

  70. if ('serviceWorker' in navigator) { navigator.serviceWorker.register('service-worker.js').then(function (registration) { // Registration

    was successful }).catch(function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }
  71. if ('serviceWorker' in navigator) { navigator.serviceWorker.register('service-worker.js').then(function (registration) { // Registration

    was successful registration.pushManager.subscribe({userVisibleOnly: true}) .then(function(subscription){ }); }).catch(function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }
  72. Save Subscription

  73. if ('serviceWorker' in navigator) { navigator.serviceWorker.register('service-worker.js').then(function (registration) { // Registration

    was successful registration.pushManager.subscribe({userVisibleOnly: true}) .then(function(subscription){ // Send to Server return sendSubscriptionToServer(subscription); }); }).catch(function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }
  74. Send from Google Cloud

  75. Manifest

  76. { "name": "Push Demo", "short_name": "Push Demo", "icons": [{ "src":

    "icon.png", "sizes": "192x192", "type": "image/png" }], "start_url": "/index.html", "display": "standalone", "gcm_sender_id": "57874135625436178", "gcm_user_visible_only": true, "permissions": [ "gcm" ]} Manifest
  77. bit.ly/push-notifications-google bit.ly/push-notifications-dean Further reading

  78. https://deanhume.github.io/typography

  79. Add to home screen

  80. Add to home screen

  81. Add to home screen 1. You need a manifest.json file

  82. Add to home screen 1. You need a manifest.json file

    2. Your manifest file needs a start URL
  83. Add to home screen 1. You need a manifest.json file

    2. Your manifest file needs a start URL 3. You need a 144x144 PNG icon
  84. Add to home screen 1. You need a manifest.json file

    2. Your manifest file needs a start URL 3. You need a 144x144 PNG icon 4. Your site is using a Service Worker running over HTTPS
  85. Add to home screen 1. You need a manifest.json file

    2. Your manifest file needs a start URL 3. You need a 144x144 PNG icon 4. Your site is using a Service Worker running over HTTPS 5. The user has visited your site at least twice, with at least five minutes between visits.
  86. { lang: "en", background_color: "#09adec", name: "Building Great Startup Teams",

    short_name: "Building Great Startup Teams", display: "standalone", icons: [ { src: "./images/logo-144.png", sizes: "144x144", type: "image/png" } ], start_url: "./index.html", orientation: "portrait" }
  87. None
  88. Look and feel Add to home screen Push notifications Sum

    m ary
  89. 3.Speed up your site

  90. 3.1 Caching

  91. 3.1 Caching 3.2 Save-Data Header

  92. 3.1 Caching 3.3 Background Sync 3.2 Save-Data Header

  93. Caching

  94. With Service Workers

  95. With Service Workers

  96. var cacheVersion = 1; var currentCache = { assetCache: 'cache'

    + cacheVersion }; Caching
  97. var cacheVersion = 1; var currentCache = { assetCache: 'cache'

    + cacheVersion }; this.addEventListener('install', event => { event.waitUntil(caches.open(currentCache.assetCache) .then(function(cache) { }) ); }); Caching
  98. var cacheVersion = 1; var currentCache = { assetCache: 'cache'

    + cacheVersion }; this.addEventListener('install', event => { event.waitUntil(caches.open(currentCache.assetCache) .then(function(cache) { return cache.addAll(['result.min.css', './js/material.min.js']); }) ); }); Caching
  99. var cacheVersion = 1; var currentCache = { assetCache: 'cache'

    + cacheVersion }; this.addEventListener('install', event => { event.waitUntil(caches.open(currentCache.assetCache) .then(function(cache) { return cache.addAll(['result.min.css', './js/material.min.js']); }) ); }); this.addEventListener('fetch', event => { event.respondWith(caches.match(event.request) .then(function (response) { return response || fetch(event.request); }) ); }); Caching
  100. github.com/GoogleChrome/sw-toolbox bit.ly/sw-toolbox

  101. Save-Data Header

  102. Using Service Workers

  103. Using Service Workers

  104. this.addEventListener('fetch', event => { if(event.request.headers.get('save-data')){ if (/\.jpg$|.gif$|.png$/.test(event.request.url)) { // We

    can do something event.respondWith( fetch(‘low-quality-’ + event.request.url, { mode: 'no-cors' }) } } });
  105. this.addEventListener('fetch', event => { if(event.request.headers.get('save-data')){ if (/\.jpg$|.gif$|.png$/.test(event.request.url)) { // We

    can do something event.respondWith( fetch(‘low-quality-’ + event.request.url, { mode: 'no-cors' }) } } });
  106. this.addEventListener('fetch', event => { if(event.request.headers.get('save-data')){ if (/\.jpg$|.gif$|.png$/.test(event.request.url)) { // We

    can do something event.respondWith( fetch(‘low-quality-’ + event.request.url, { mode: 'no-cors' }) } } });
  107. this.addEventListener('fetch', event => { if(event.request.headers.get('save-data')){ if (/\.jpg$|.gif$|.png$/.test(event.request.url)) { // We

    can do something event.respondWith( fetch(‘low-quality-’ + event.request.url, { mode: 'no-cors' }) } } });
  108. buildingstartupteams.com

  109. buildingstartupteams.com

  110. None
  111. Saved 900 KB!

  112. Background sync

  113. Using Service Workers

  114. Using Service Workers

  115. With Service Workers

  116. Try later….

  117. // Request a one-off sync: navigator.serviceWorker.ready.then( function(swRegistration) { return swRegistration.sync.register('myFirstSync');

    });
  118. // Request a one-off sync: navigator.serviceWorker.ready.then( function(swRegistration) { return swRegistration.sync.register('myFirstSync');

    }); self.addEventListener('sync', function(event) { if (event.tag == 'myFirstSync') { event.waitUntil(expensiveOperation()); } });
  119. // Request a one-off sync: navigator.serviceWorker.ready.then( function(swRegistration) { return swRegistration.sync.register('myFirstSync');

    }); self.addEventListener('sync', function(event) { if (event.tag == 'myFirstSync') { event.waitUntil(expensiveOperation()); } });
  120. Background sync bit.ly/background-sync

  121. Caching Background Sync Save-Data Header Sum m ary

  122. 4.Reliable

  123. 4.1 Offline Browsing 4.2 3rd Party Scripts

  124. None
  125. Offline

  126. With Service Workers

  127. this.addEventListener('fetch', event => { };

  128. this.addEventListener('fetch', event => { // Check if the user navigated

    if (event.request.method === 'GET' && event.request.headers. get('accept').includes('text/html')) { // Respond appropriately } };
  129. this.addEventListener('fetch', event => { // Check if the user navigated

    if (event.request.method === 'GET' && event.request.headers. get('accept').includes('text/html')) { // Respond appropriately event.respondWith( fetch(event.request.url).catch(error => { // Return the offline page return caches.match('the-offline-page'); })); } };
  130. Offline Applications bit.ly/offline-apps bit.ly/offline-page

  131. 3rd Party Scripts

  132. Server Fails

  133. None
  134. Using Service Workers

  135. Using Service Workers

  136. With Service Workers

  137. function timeout(delay) { return new Promise(function(resolve, reject) { setTimeout(function(){ resolve(new

    Response('', { status: 408, statusText: 'Request timed out.' })); }, delay); }); }
  138. function timeout(delay) { return new Promise(function(resolve, reject) { setTimeout(function(){ resolve(new

    Response('', { status: 408, statusText: 'Request timed out.' })); }, delay); }); } self.addEventListener('fetch', event => { });
  139. function timeout(delay) { return new Promise(function(resolve, reject) { setTimeout(function(){ resolve(new

    Response('', { status: 408, statusText: 'Request timed out.' })); }, delay); }); } self.addEventListener('fetch', event => { event.respondWith(Promise.race([timeout(6000), fetch (event.request.url)])); });
  140. bit.ly/sw-timeout

  141. Summary

  142. Summary 1. Understanding Progressive Web Apps 2. Engage your users

    3. Speed up your site 4. Improve reliability
  143. Performance is a feature

  144. Further reading ❖ Shell Architecture - bit.ly/instant-shell ❖ Getting Started

    - bit.ly/starting-pwas ❖ Service Worker - bit.ly/pwa-swers ❖ Code Labs -bit.ly/code-labs-pwa ❖ Recipes ➢ bit.ly/mozilla-service-workers ➢ bit.ly/chrome-service-workers
  145. What’s still to come?

  146. What’s still to come? Web Bluetooth webbluetoothcg.github.io/web-bluetooth Streams API jakearchibald.com/2016/streams-ftw

    Web NFC w3c.github.io/web-nfc Geofencing w3c.github.io/geofencing-api
  147. Thank you! @ deanohum e