Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Progressive Web Apps & Offline Development 2019

Progressive Web Apps & Offline Development 2019

Mike Oram

May 29, 2019
Tweet

More Decks by Mike Oram

Other Decks in Technology

Transcript

  1. Obligatory about me Full-stack developer LAMP and Node I run

    Mayden Academy (@MaydenAcademy) Learn new stuff and teach it to people @MPOram
  2. “Progressive Web Apps are experiences that combine the best of

    the web and the best of the apps” @MPOram
  3. What is a PWA? • Term coined by Alex Russell

    in 2015[1] • Appear to the user like a native app • They can work offline, but don’t have to • Operating system agnostic (Windows, Android, iOS or OSX) [1] https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/ @MPOram
  4. No more App Store Use to Install Not Install to

    Use Install prompt event triggered when a user interacts with an application for more than 30 seconds*. *In Chrome v68 @MPOram
  5. Why PWA? Tinder Cut average load times from 11.91s to

    4.69s. 90% smaller than native Android app. https://www.pwastats.com/ @MPOram
  6. Why PWA? Uber Only 50k gzipped. Takes less than 3s

    to load on 2G. https://www.pwastats.com/ @MPOram
  7. Why PWA? Trivago 150% user engagement increase compared to web.

    97% increase in hotel offer clicks. 67% of users keep browsing when they go offline. https://www.pwastats.com/ @MPOram
  8. Why PWA? Pinterest User engagements increased by 60%. 44% increase

    in user-generated ad revenue. Time spent on the site has increased by 40%. https://www.pwastats.com/ @MPOram
  9. Make your application a PWA HTTPS It already is though,

    right? A Service Worker* A bit like a client side proxy Web App Manifest Your Apps settings *not in Firefox User permission To install your app and use the APIs @MPOram
  10. Get the users permission Add to Home screen prompt •

    Listen for the beforeinstallprompt Event • Event fires if install criteria are met • Display install prompt after event has fired • Acceptance of the prompt results in automatic install of your application (Adds it to their home screen) @MPOram
  11. window.addEventListener('beforeinstallprompt', (promptEvent) => { promptEvent.preventDefault(); addBtn.style.display = 'block'; addBtn.addEventListener( 'click',

    (e) => { addBtn.style.display = 'none'; promptEvent.prompt(); // Show the prompt promptEvent.userChoice. then((result) => { console.log(result); deferredPrompt = null; }); }); }); @MPOram
  12. What is a Web App Manifest? { "lang": "en", "background_color":

    "#ffffff", "name": "Mayden Academy", "start_url": ".", "description": "Example", "display": "standalone", "icons": [ { "src": "logo.png", "sizes": "144x144", "type": "image/png" } ], "orientation": "portrait" } <link rel="manifest" href="manifest.json"> @MPOram
  13. What is a service worker? A client side proxy •

    Runs in a separate execution thread • No DOM access (use the postMessage API to communicate with client) • Can interact with all network requests • Most commonly used for Cache management @MPOram
  14. if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js', {scope: './'}) .then(function(registration) {

    console.log('SW Success') }).catch(function(error) { console.log('SW failed:', error) }); } else { console.log('SW not supported') } @MPOram
  15. self.addEventListener("fetch", function(event){ var reqDate = reqDate || Date.now() event.respondWith( if

    (reqDate < reqDate-300000) { // 5 minutes ago return fetch(event.request); } else { // return previous request from cache } ) }) Only call the API every 5 minutes @MPOram
  16. HTTP Request Initial request to your API, stores data and

    displays User interaction User refreshes or performs an action that requires the same data Service Worker Service Worker picks up fetch and decides how to respond Response Data comes back from service worker Update UI Update DOM with response data @MPOram
  17. Client side data storage Service Worker Cache Mostly used for

    caching static files, works with data such as JSON localStorage Similar to the service worker cache but is synchronous so does not work inside a service worker IndexedDB Works asynchronously so can be used inside a service worker for data storage @MPOram
  18. What is IndexedDB A client side Database Client-side storage of

    large amounts of data, usually JSON. Uses indexes for high-performance searches Asynchronous promise based API Permanent data storage @MPOram
  19. Using IndexedDB // connect to DB var IDB = db.transaction([

    'toDoList'],"readwrite") .objectStore('toDoList') IDB.add({name: "Mike"}, 1) // store JSON with key of 1 // retrieve data stored in key 1 var data = IDB.get(1) data.name = 'Charlie' IDB.put(data, 1) // update JSON at key of 1 @MPOram
  20. self.addEventListener( "fetch", function(event) { event.respondWith( if (reqDate < reqDate-300000) {

    // 5 minutes ago let response = await fetch(event.request) await IDB.add(response, event.request.body.id) return response } else { return await IDB.get(event.request.body.id) } ) }) Only call the API every 5 minutes @MPOram
  21. self.addEventListener( "fetch", function(event) { event.respondWith( if (reqDate < reqDate-300000) {

    // 5 minutes ago let response = await fetch(event.request) await IDB.add(response, event.request.body.id) return response } else { return await IDB.get(event.request.body.id) } ) }) Offline Support @MPOram
  22. let response = await fetch(event.request) .catch(function(error) { // if we

    are offline // retrieve and return data from IndexedDB // if present }) Offline Support @MPOram
  23. function isOnline() { let conStatus = document.getElementById(‘conStat’) conStatus.style.display = ‘none’

    if (!navigator.onLine){ conStatus.style.display = ‘block’ } } window.addEventListener('online', isOnline) window.addEventListener('offline', isOnline) Offline Support @MPOram
  24. HTTP Request Initial request to your API API Response Data

    stored in IndexedDB and displayed User action User performs a page action Service Worker Performs fetch request or falls back to IndexedDB if network down Update UI Update DOM with response data @MPOram
  25. // app.js button.addEventListener( 'click', function() { registration.sync.register( 'update-trains') }) //

    service-worker.js self.addEventListener('sync', function (event) { if (event.tag === 'update-trains') { // fetch new train data when online event.waitUntil(updateTrains()) } }) Offline Support - background sync @MPOram
  26. PWA Limitations Limited Storage Offline data and files only up

    to: Andriod: < 2GB Chrome <6% of free space Firefox <10% of free space Safari <50MB IE10 <250MB Edge ¯\_(ツ)_/¯ @MPOram
  27. PWA Limitations iOS auto delete iOS will free up the

    app’s files if the app is unused for a few weeks. The icon will still be there on the home screen, when accessed the app will be downloaded again. https://medium.com/@firt/progressive-web-apps-on-ios-are-here-d00430dee3a7 @MPOram
  28. PWA Limitations Limited native access No access to some features,

    such as Bluetooth, Touch ID, Face ID, altimeter sensor, app payments or contact info. No Push Notifications or Siri integration on iOS. https://medium.com/@firt/progressive-web-apps-on-ios-are-here-d00430dee3a7 @MPOram