Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

Antonio Perić-Mažar CEO @ Locastic Co-Founder @ Blockada [email protected] @antonioperic

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

[Mobile] User Experience on Web

Slide 6

Slide 6 text

MOBILE

Slide 7

Slide 7 text

UX

Slide 8

Slide 8 text

MOBILE.UX.

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

And trust me… you will never had enough cheese

Slide 15

Slide 15 text

“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

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

Capebility Reach

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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.

Slide 21

Slide 21 text

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.

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Fast Integrated Reliable Engaging 4 things to focus on

Slide 24

Slide 24 text

Fast Integrated Reliable Engaging

Slide 25

Slide 25 text

Fast • No junky scrolling • No slow load performance • Measure and improve all the time • Bad connection (or no connection) is not excuse

Slide 26

Slide 26 text

53% of users abandon sites that take longer than 3 seconds to load

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

App shell model • Reliable performance that is consistently fast • Native-like interactions • Economical use of data

Slide 30

Slide 30 text

Fast Integrated Reliable Engaging

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

https://www.mobigyaan.com/android-8-0-oreo-vs-ios-11-which-is-better

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

80% users intentionally moved apps to their home screen

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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/

Slide 39

Slide 39 text

{ "background_color":"#ffffff", "display":"standalone", "icons":[ … ], "name":"Twitter", "short_name":"Twitter", "start_url":"/", "theme_color":"#ffffff", “scope":"/" } You can add it now to 
 your app

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

https://ponyfoo.com/articles/progressive-app-serviceworker

Slide 42

Slide 42 text

40% higher interaction rate from Home screen

Slide 43

Slide 43 text

Web Payment API!

Slide 44

Slide 44 text

66% of purchases on mobile are on the web

Slide 45

Slide 45 text

1/3 of purchases on Web are via mobile That means the UX 
 is BROKEN!

Slide 46

Slide 46 text

Checkout forms today: • Manual • Tedious • Slow • N-taps http://www.alyssatucker.com/improving-hollars-ios-checkout-process/

Slide 47

Slide 47 text

Autofill - step forward • Autocomplete attributes • 30% faster • Automatic • Simple • Slow • n-taps http://www.alyssatucker.com/improving-hollars-ios-checkout-process/

Slide 48

Slide 48 text

Web Payment API!

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Web Payment API! • Automatic • Simple • Fast • 1-tap • Supportes payment gatway,
 or some applications payment 
 (Google Pay) https://paymentrequest.show/images/pr-woocommerce.gif

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

Fast Integrated Reliable Engaging

Slide 57

Slide 57 text

Reliable Reliability means, never showing the Downsaur

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

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.

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

Service Workers

Slide 62

Slide 62 text

Service Workers

Slide 63

Slide 63 text

Service Workers Service Workers

Slide 64

Slide 64 text

Service Workers • Rich offline experiences • Background syncs • Push notifications • …

Slide 65

Slide 65 text

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.

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

Service Workers lifecycle

Slide 68

Slide 68 text

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); }); }); }

Slide 69

Slide 69 text

No content

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

On install - as a dependency

Slide 72

Slide 72 text

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 ]); }) ); });

Slide 73

Slide 73 text

On install - not as a dependency

Slide 74

Slide 74 text

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 ); }) ); });

Slide 75

Slide 75 text

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.

Slide 76

Slide 76 text

No content

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

Update Service Worker • self.skipWaiting() • Skips waiting for refresh to start using new SW

Slide 79

Slide 79 text

On User Interaction

Slide 80

Slide 80 text

// 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); }); }); });

Slide 81

Slide 81 text

On Network response

Slide 82

Slide 82 text

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; }); }); }) ); });

Slide 83

Slide 83 text

State-while-revalidate

Slide 84

Slide 84 text

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; }) }) ); });

Slide 85

Slide 85 text

On Background Sync

Slide 86

Slide 86 text

self.addEventListener('sync', function(event) { if (event.id == 'update-leaderboard') { event.waitUntil( caches.open('mygame-dynamic').then(function(cache) { return cache.add('/leaderboard.json'); }) ); } });

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

Cache only

Slide 89

Slide 89 text

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)); });

Slide 90

Slide 90 text

Network only

Slide 91

Slide 91 text

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 });

Slide 92

Slide 92 text

Cache, falling back to network

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

Cache & network race

Slide 95

Slide 95 text

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) ])

Slide 96

Slide 96 text

Network, falling back to Cache

Slide 97

Slide 97 text

Network, falling back to Cache self.addEventListener('fetch', function(event) { event.respondWith( fetch(event.request).catch(function() { return caches.match(event.request); }) ); });

Slide 98

Slide 98 text

Cache, than Network

Slide 99

Slide 99 text

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);

Slide 100

Slide 100 text

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; }); }) ); });

Slide 101

Slide 101 text

Generic fallback

Slide 102

Slide 102 text

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. }) ); });

Slide 103

Slide 103 text

No content

Slide 104

Slide 104 text

No content

Slide 105

Slide 105 text

No content

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

https://serviceworke.rs/ - different examples

Slide 108

Slide 108 text

Your goal is to provide a good experience that lessens the impact of changes in connectivity

Slide 109

Slide 109 text

Fast Integrated Reliable Engaging

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

Engaging

Slide 112

Slide 112 text

What makes good notification Push. Push. Back upon now. (Courtesy Enrique Iglesias)

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

What makes good notification

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

No content

Slide 118

Slide 118 text

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/'); } });

Slide 119

Slide 119 text

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" } ] }

Slide 120

Slide 120 text

43% agrees to an app’s request to allow push notifications

Slide 121

Slide 121 text

No content

Slide 122

Slide 122 text

Tools!

Slide 123

Slide 123 text

Lighthouse

Slide 124

Slide 124 text

No content

Slide 125

Slide 125 text

Some show case!

Slide 126

Slide 126 text

65% increase in page per session 75% increase in Tweets sent
 20% decrease in bounce rate Twitter Lite

Slide 127

Slide 127 text

76% higher conversation across browsers 4x higher interaction rate from Add to screen Increased usage of native apps also Alibaba

Slide 128

Slide 128 text

80%+ conversation 54% smaller than Android app 120% smaller than iOS app BookMyShow

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

Myths about PWA!

Slide 131

Slide 131 text

PWAs are only for offline apps

Slide 132

Slide 132 text

PWAs are a mobile thing

Slide 133

Slide 133 text

PWAs are a Google-only thing

Slide 134

Slide 134 text

No content

Slide 135

Slide 135 text

PWAs are not ready yet

Slide 136

Slide 136 text

No content

Slide 137

Slide 137 text

No content

Slide 138

Slide 138 text

No content

Slide 139

Slide 139 text

No content

Slide 140

Slide 140 text

https://pwa.rocks/

Slide 141

Slide 141 text

No content

Slide 142

Slide 142 text

No content

Slide 143

Slide 143 text

Don’t be driven with hype, choose the best fit for your project

Slide 144

Slide 144 text

It is not about PWA vs Native apps, it is about Users

Slide 145

Slide 145 text

Thank you!

Slide 146

Slide 146 text

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