Service workers are your best friend!

Service workers are your best friend!

The main API for PWA creation is Service Workers, they are the heart of this “new web”. With Service workers, we can send push notifications to the user or do background sync and show data even when the user is offline. They are not some science fiction, but a script that is quite easy to use.

In this talk, we will see overview what are service workers and when and how to use them.

29db221e8a59b06c9180725ec8ac1e75?s=128

Antonio Peric-Mazar

December 04, 2018
Tweet

Transcript

  1. Service workers are your best friend! Antonio Perić-Mažar, Locastic 02.12.2018.,

    #growITconf
  2. Antonio Perić-Mažar CEO @ Locastic Co-Founder @ Blockada antonio@locastic.com @antonioperic

  3. Locastic • We help clients create amazing web and mobile

    apps (since 2011) • mobile development • web development • UX/UI • Training and Consulting • Shift Conference, Symfony Croatia • www.locastic.com t: @locastic
  4. None
  5. [Mobile] User Experience on Web

  6. MOBILE

  7. UX

  8. MOBILE.UX.

  9. None
  10. None
  11. None
  12. None
  13. None
  14. And trust me… you will never had enough cheese

  15. “I don't care how many kick-ass Visio architecture diagrams you

    have; as far as the user is concerned, the UI is the application. I know UI US HARD, but you have to build an impressive UI if you want to be taken seriously. Give your UI the high priority it deserves.” Jeff Atwood, Coding Horror blog
  16. None
  17. Capebility Reach

  18. “A Progressive Web App uses modern web capabilities to deliver

    an app-like user experience.”
  19. “A Progressive Web App uses modern web capabilities to deliver

    an app-like user experience.”
  20. PWA is: • Progressive - Works for every user, regardless

    of browser choice because it's built with progressive enhancement as a core tenet. • Responsive - Fits any form factor: desktop, mobile, tablet, or whatever is next. • Connectivity independent - Enhanced with service workers to work offline or on low-quality networks. • App-like - Feels like an app, because the app shell model separates the application functionality from application content . • Fresh - Always up-to-date thanks to the service worker update process.
  21. PWA is: • Safe - Served via HTTPS to prevent

    snooping and to ensure content hasn't been tampered with. • Discoverable - Is identifiable as an "application" thanks to W3C manifest and service worker registration scope, allowing search engines to find it. • Re-engageable - Makes re-engagement easy through features like push notifications. • Installable - Allows users to add apps they find most useful to their home screen without the hassle of an app store. • Linkable - Easily share the application via URL, does not require complex installation.
  22. None
  23. Fast Integrated Reliable Engaging 4 things to focus on

  24. Fast Integrated Reliable Engaging

  25. Fast • No junky scrolling • No slow load performance

    • Measure and improve all the time • Bad connection (or no connection) is not excuse
  26. 53% of users abandon sites that take longer than 3

    seconds to load
  27. https://cloudfour.com/thinks/ios-doesnt-support-progressive-web-apps-so-what/

  28. None
  29. App shell model • Reliable performance that is consistently fast

    • Native-like interactions • Economical use of data
  30. Fast Integrated Reliable Engaging

  31. Integrated • User should not reach browser to reach your

    app • They should be able to interact same as with any other app on their device • They expect to have all possibilities as other apps • Users should be able to start app from their home screen
  32. https://www.mobigyaan.com/android-8-0-oreo-vs-ios-11-which-is-better

  33. https://techcrunch.com/2017/08/25/majority-of-u-s-consumers-still-download-zero-apps-per-month-says-comscore/

  34. https://techcrunch.com/2017/08/25/majority-of-u-s-consumers-still-download-zero-apps-per-month-says-comscore/

  35. https://www.technology.org/2017/07/28/progressive-web-apps-vs-native-which-is-better-for-your-business/

  36. 80% users intentionally moved apps to their home screen

  37. Broken experience • Required user interaction • Where it will

    start? • Would it work offline? https://medium.com/@saigeleslie/how-to-create-a-progressive-web-app-with-react-in-5-mins-or-less-3aae3fe98902
  38. Web manifest • Simple JSON file • Tell browsers about

    your app and how it should behave once app is ‘installed’ • Having manifest is required to show add to home screen pop-up • Works for desktop and mobile apps (chrome) • https://manifest-validator.appspot.com/ • https://app-manifest.firebaseapp.com/
  39. { "background_color":"#ffffff", "display":"standalone", "icons":[ … ], "name":"Twitter", "short_name":"Twitter", "start_url":"/", "theme_color":"#ffffff",

    “scope":"/" } <link rel="manifest" href="/manifest.json"> You can add it now to 
 your app
  40. None
  41. https://ponyfoo.com/articles/progressive-app-serviceworker

  42. 40% higher interaction rate from Home screen

  43. Web Payment API!

  44. 66% of purchases on mobile are on the web

  45. 1/3 of purchases on Web are via mobile That means

    the UX 
 is BROKEN!
  46. Checkout forms today: • Manual • Tedious • Slow •

    N-taps http://www.alyssatucker.com/improving-hollars-ios-checkout-process/
  47. Autofill - step forward • Autocomplete attributes • 30% faster

    • Automatic • Simple • Slow • n-taps http://www.alyssatucker.com/improving-hollars-ios-checkout-process/
  48. Web Payment API!

  49. None
  50. None
  51. None
  52. Web Payment API! • Automatic • Simple • Fast •

    1-tap • Supportes payment gatway,
 or some applications payment 
 (Google Pay) https://paymentrequest.show/images/pr-woocommerce.gif
  53. More APIs • Media Session • Media Capture API •

    Casting support • Web bluetooth • Web Share
  54. More APIs • Media Session • Media Capture API •

    Casting support • Web bluetooth • Web Share
  55. Remember users expect to be able to interact with your

    app in the same way that they do all of the other apps on their device
  56. Fast Integrated Reliable Engaging

  57. Reliable Reliability means, never showing the Downsaur

  58. None
  59. Reliable • The quality of a network connection can be

    affected by a number of factors such as: • Poor coverage of a provider. • Extreme weather conditions. • Power outages. • Users travelling into “dead zones” such as buildings that block their network connections. • Travelling on a train and going through a tunnel. • Internet connection is managed by a third party and time boxed when it will be active or inactive like in an airport or hotel. • Cultural practises that require limited or no internet access at specific times or days.
  60. Reliable • We need instant loading offline • 60% of

    mobile connection is 2G • Fast Application is UX • 14 sec to load average website on 4g • 19 sec to load average website on 3G
  61. Service Workers

  62. Service Workers

  63. Service Workers Service Workers

  64. Service Workers • Rich offline experiences • Background syncs •

    Push notifications • …
  65. Service Workers • Script that browser runs in background, separated

    from web page • It is Javascript worker, so it cannot access to DOM directly • Service worker is a programmable network proxy, allowing you to control how network requests from your page are handled.
  66. Service Workers • It's terminated when not in use, and

    restarted when it's next needed, so you cannot rely on global state within a service worker's onfetch and onmessage handlers. • Service workers make extensive use of promises • Service worker is for second load
  67. Service Workers lifecycle

  68. Register a Service Worker if ('serviceWorker' in navigator) { window.addEventListener('load',

    function() { navigator.serviceWorker.register('/sw.js').then(function(registration) { // Registration was successful console.log('ServiceWorker registration successful with scope: ', registration.scope); }, function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }); }
  69. None
  70. Service workers Events • On install - as a dependency

    • On install - not as a dependency • On activate • On user interaction • On network response • Stale-while-revalidate • On push message • On background-sync
  71. On install - as a dependency

  72. On install - as a dependency self.addEventListener('install', function(event) { event.waitUntil(

    caches.open('mysite-static-v3').then(function(cache) { return cache.addAll([ '/css/whatever-v3.css', '/css/imgs/sprites-v6.png', '/css/fonts/whatever-v8.woff', '/js/all-min-v4.js' // etc ]); }) ); });
  73. On install - not as a dependency

  74. On install - not as a dependency self.addEventListener('install', function(event) {

    event.waitUntil( caches.open('mygame-core-v1').then(function(cache) { cache.addAll( // levels 11-20 ); return cache.addAll( // core assets & levels 1-10 ); }) ); });
  75. Update Service Worker • Update your service worker JavaScript file.

    When the user navigates to your site, the browser tries to redownload the script file that defined the service worker in the background. If there is even a byte's difference in the service worker file compared to what it currently has, it considers it new. • Your new service worker will be started and the install event will be fired. • At this point the old service worker is still controlling the current pages so the new service worker will enter a waiting state. • When the currently open pages of your site are closed, the old service worker will be killed and the new service worker will take control. • Once your new service worker takes control, its activate event will be fired.
  76. None
  77. self.addEventListener('activate', function(event) { event.waitUntil( caches.keys().then(function(cacheNames) { return Promise.all( cacheNames.filter(function(cacheName) {

    // Return true if you want to remove this cache, // but remember that caches are shared across // the whole origin }).map(function(cacheName) { return caches.delete(cacheName); }) ); }) ); }); On Activate
  78. Update Service Worker • self.skipWaiting() • Skips waiting for refresh

    to start using new SW
  79. On User Interaction

  80. // on user interaction document.querySelector('.cache-article').addEventListener('click', function(event) { event.preventDefault(); var id

    = this.dataset.articleId; caches.open('mysite-article-' + id).then(function(cache) { fetch('/get-article-urls?id=' + id).then(function(response) { // /get-article-urls returns a JSON-encoded array of // resource URLs that a given article depends on return response.json(); }).then(function(urls) { cache.addAll(urls); }); }); });
  81. On Network response

  82. self.addEventListener('fetch', function(event) { event.respondWith( caches.open('mysite-dynamic').then(function(cache) { return cache.match(event.request).then(function (response) {

    return response || fetch(event.request).then(function(response) { cache.put(event.request, response.clone()); return response; }); }); }) ); });
  83. State-while-revalidate

  84. State-while-revalidate self.addEventListener('fetch', function(event) { event.respondWith( caches.open('mysite-dynamic').then(function(cache) { return cache.match(event.request).then(function(response) {

    var fetchPromise = fetch(event.request).then(function(networkResponse) { cache.put(event.request, networkResponse.clone()); return networkResponse; }) return response || fetchPromise; }) }) ); });
  85. On Background Sync

  86. self.addEventListener('sync', function(event) { if (event.id == 'update-leaderboard') { event.waitUntil( caches.open('mygame-dynamic').then(function(cache)

    { return cache.add('/leaderboard.json'); }) ); } });
  87. SW: Serving suggestions - responding to requests • Cache only

    • Network only • Cache, falling back to network • Cache & network race • Network falling back to cache • Cache then network • Generic fallback
  88. Cache only

  89. Cache only self.addEventListener('fetch', function(event) { // If a match isn't

    found in the cache, the response // will look like a connection error event.respondWith(caches.match(event.request)); });
  90. Network only

  91. Network only self.addEventListener('fetch', function(event) { event.respondWith(fetch(event.request)); // or simply don't

    call event.respondWith, which // will result in default browser behaviour });
  92. Cache, falling back to network

  93. Cache, falling back to network self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request).then(function(response)

    { return response || fetch(event.request); }) ); });
  94. Cache & network race

  95. Cache & network race // Promise.race is no good to

    us because it rejects if // a promise rejects before fulfilling. Let's make a proper // race function: function promiseAny(promises) { return new Promise((resolve, reject) => { // make sure promises are all promises promises = promises.map(p => Promise.resolve(p)); // resolve this promise as soon as one resolves promises.forEach(p => p.then(resolve)); // reject if all promises reject promises.reduce((a, b) => a.catch(() => b)) .catch(() => reject(Error("All failed"))); }); }; self.addEventListener('fetch', function(event) { event.respondWith( promiseAny([ caches.match(event.request), fetch(event.request) ])
  96. Network, falling back to Cache

  97. Network, falling back to Cache self.addEventListener('fetch', function(event) { event.respondWith( fetch(event.request).catch(function()

    { return caches.match(event.request); }) ); });
  98. Cache, than Network

  99. Cache, than Network var networkDataReceived = false; startSpinner(); // fetch

    fresh data var networkUpdate = fetch('/data.json').then(function(response) { return response.json(); }).then(function(data) { networkDataReceived = true; updatePage(data); }); // fetch cached data caches.match('/data.json').then(function(response) { if (!response) throw Error("No data"); return response.json(); }).then(function(data) { // don't overwrite newer network data if (!networkDataReceived) { updatePage(data); } }).catch(function() { // we didn't get cached data, the network is our last hope: return networkUpdate; }).catch(showErrorMessage).then(stopSpinner);
  100. Cache, than Network self.addEventListener('fetch', function(event) { event.respondWith( caches.open('mysite-dynamic').then(function(cache) { return

    fetch(event.request).then(function(response) { cache.put(event.request, response.clone()); return response; }); }) ); });
  101. Generic fallback

  102. Generic fallback self.addEventListener('fetch', function(event) { event.respondWith( // Try the cache

    caches.match(event.request).then(function(response) { // Fall back to network return response || fetch(event.request); }).catch(function() { // If both fail, show a generic fallback: return caches.match('/offline.html'); // However, in reality you'd have many different // fallbacks, depending on URL & headers. // Eg, a fallback silhouette image for avatars. }) ); });
  103. None
  104. None
  105. None
  106. Reliable conclusion • Think how you design for the success,

    failure and instability of a network connection • Data may be expensive, so be considerate to the user • Make sure performance is part of your design process and UX • Try to provide offline by default if your app doesn't require much data • Inform users of their current state and of changes in states • https://serviceworke.rs/ - different examples
  107. https://serviceworke.rs/ - different examples

  108. Your goal is to provide a good experience that lessens

    the impact of changes in connectivity
  109. Fast Integrated Reliable Engaging

  110. Engaging • Charming and Attractive • Shift way how we

    think in patterns and designs from web patterns to some native patterns • Push notifications (browser doesn’t need to be opened) • Push Notification API
  111. Engaging

  112. What makes good notification Push. Push. Back upon now. (Courtesy

    Enrique Iglesias)
  113. What makes good notification • Timely - I feel I

    need and it matters now • Precise - specific info, what happens • Personal - make it personal
  114. What makes good notification

  115. https://www.slideshare.net/SeulgiChoi4/pwa-push-notification

  116. https://www.slideshare.net/SeulgiChoi4/pwa-push-notification

  117. None
  118. self.addEventListener('push', function(event) { if (event.data.text() == 'new-email') { event.waitUntil( caches.open('mysite-dynamic').then(function(cache)

    { return fetch('/inbox.json').then(function(response) { cache.put('/inbox.json', response.clone()); return response.json(); }); }).then(function(emails) { registration.showNotification("New email", { body: "From " + emails[0].from.name tag: "new-email" }); }) ); } }); self.addEventListener('notificationclick', function(event) { if (event.notification.tag == 'new-email') { // Assume that all of the resources needed to render // /inbox/ have previously been cached, e.g. as part // of the install handler. new WindowClient('/inbox/'); } });
  119. Push Notifications { "body": "Did you make a $1,000,000 purchase

    at Dr. Evil...", "icon": "images/ccard.png", "vibrate": [200, 100, 200, 100, 200, 100, 400], "tag": "request", "actions": [ { "action": "yes", "title": "Yes", "icon": "images/yes.png" }, { "action": "no", "title": "No", "icon": "images/no.png" } ] }
  120. 43% agrees to an app’s request to allow push notifications

  121. None
  122. Tools!

  123. Lighthouse

  124. None
  125. Some show case!

  126. 65% increase in page per session 75% increase in Tweets

    sent
 20% decrease in bounce rate Twitter Lite
  127. 76% higher conversation across browsers 4x higher interaction rate from

    Add to screen Increased usage of native apps also Alibaba
  128. 80%+ conversation 54% smaller than Android app 120% smaller than

    iOS app BookMyShow
  129. Cut load times from 11.91 to 4.69 seconds 90% smaller

    than Native Android App https://medium.com/@addyosmani/a-tinder-progressive-web-app-performance- case-study-78919d98ece0 Tinder
  130. Myths about PWA!

  131. PWAs are only for offline apps

  132. PWAs are a mobile thing

  133. PWAs are a Google-only thing

  134. None
  135. PWAs are not ready yet

  136. None
  137. None
  138. None
  139. None
  140. https://pwa.rocks/

  141. None
  142. None
  143. Don’t be driven with hype, choose the best fit for

    your project
  144. It is not about PWA vs Native apps, it is

    about Users
  145. Thank you!

  146. QnA? 1st question will get free ticket for BločkConf (workshop

    + conference) Join us at BločkConf! 14-15.12.
 www.blockconf.io Use ‘growit’ code for 20% discount