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

Always On! ... or not?

Always On! ... or not?

My Slides for my Talk at Code.Talks Hamburg 2016.

Carsten Sandtner

September 30, 2016
Tweet

More Decks by Carsten Sandtner

Other Decks in Technology

Transcript

  1. Always ON!
    …or not?
    Carsten Sandtner (@casarock)
    mediaman// Gesellschaft für Kommunikation mbH

    View Slide

  2. about:me
    Carsten Sandtner
    @casarock
    Head of Software Development
    //mediaman GmbH

    View Slide

  3. View Slide

  4. View Slide

  5. The Beginning
    Nils Peters - https://flic.kr/p/9k2Wdp

    View Slide

  6. Browser Cache

    View Slide

  7. Cookies
    Brett Jordan - https://flic.kr/p/7ZRSzA

    View Slide

  8. Ancient Times
    Thomas Conté - https://flic.kr/p/9dzzpc

    View Slide

  9. Application
    Cache

    View Slide

  10. „HTML5 provides an application caching mechanism
    that lets web-based applications run offline.
    Developers can use the Application Cache (AppCache)
    interface to specify resources that the browser should
    cache and make available to offline users.“
    -MDN
    https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache

    View Slide

  11. AppCache: Definition


    View Slide

  12. AppCache: Manifest
    CACHE MANIFEST
    # v2 2016-09-30
    index.html
    cache.html
    style.css
    app.js
    hero.png
    # Use from network if available
    NETWORK:
    network.html
    # Fallback content
    FALLBACK:
    / fallback.html

    View Slide

  13. AppCache: Javascript
    window.applicationCache.onchecking = function(e) {}
    window.applicationCache.onnoupdate = function(e) {}
    window.applicationCache.onupdateready = function(e) {}
    window.applicationCache.onobsolete = function(e) {}
    window.applicationCache.ondownloading = function(e) {}
    window.applicationCache.oncached = function(e) {}
    window.applicationCache.onerror = function(e) {}
    window.applicationCache.onprogress = function(e) {}

    View Slide

  14. The
    TRUTH

    View Slide

  15. • FILES ALWAYS COME FROM THE APPLICATIONCACHE, EVEN IF YOU’RE
    ONLINE
    • THE APPLICATIONCACHE ONLY UPDATES IF THE CONTENT OF THE
    MANIFEST ITSELF HAS CHANGED
    • THE APPLICATIONCACHE IS AN ADDITIONAL CACHE, NOT AT ALTERNATIVE
    ONE
    • NEVER EVER EVER FAR-FUTURE CACHE THE MANIFEST
    • NON-CACHED RESOURCES WILL NOT LOAD ON A CACHED PAGE
    • WE DON’T KNOW HOW WE GOT TO THE FALLBACK PAGE
    • …

    View Slide

  16. – Jake Archibald
    http://alistapart.com/article/application-cache-is-a-douchebag
    „Application Cache is a Douchebag“

    View Slide

  17. 2016
    W3C decides to remove application cache
    from standard

    View Slide

  18. Alexander Boden - https://flic.kr/p/pMrQ1N
    Things are getting better

    View Slide

  19. Web
    Storages

    View Slide

  20. Web Storages
    • key/value store
    • localStorage
    • sessionStorage

    View Slide

  21. localStorage
    localStorage.myCar = 'Volkswagen Beetle';
    localStorage['myCar'] = 'Volkswagen Beetle';
    localStorage.setItem('myCar', 'Volkswagen Beetle');
    let myCar = localStorage.getItem('myCar');
    window.addEventListener('storage', function(e) { ... }
    localStorage.removeItem('myCar');
    localStorage.clear()
    let complexType = {type: 'Beetle', manufacturer: 'Volkswagen'}
    localStorage.setItem('myCar', JSON.stringify(complexType));

    View Slide

  22. sessionStorage
    sessionStorage.myCar = 'Volkswagen Beetle';
    sessionStorage['myCar'] = 'Volkswagen Beetle';
    sessionStorage.setItem('myCar', 'Volkswagen Beetle');
    let myCar = sessionStorage.getItem('myCar');
    window.addEventListener('storage', function(e) { ... }
    sessionStorage.removeItem('myCar');
    sessionStorage.clear()
    let complexType = {type: 'Beetle', manufacturer: 'Volkswagen'}
    sessionStorage.setItem('myCar', JSON.stringify(complexType));

    View Slide

  23. WebStorages
    • easy to use!
    • good browser support!
    • But:
    • http/https define different stores!
    • asynchronous
    • Quota?

    View Slide

  24. IndexedDB

    View Slide

  25. –Wikipedia
    https://en.wikipedia.org/wiki/Indexed_Database_API
    „The Indexed Database API, or IndexedDB (formerly
    WebSimpleDB), is a W3C recommended web
    browser standard interface for a transactional local
    database of JSON objects collections with indices.“

    View Slide

  26. IndexedDB: Open/Create
    var indexedDB = window.indexedDB || window.mozIndexedDB ||
    window.webkitIndexedDB || window.msIndexedDB;
    var open = indexedDB.open("MyDatabase", 1);
    // Create the schema
    open.onupgradeneeded = function() {
    var db = open.result;
    var store = db.createObjectStore("FancyNamedStore", {keyPath: "id"});
    var index = store.createIndex("NameIndex", ["name.last", "name.first"]);
    };
    open.onsuccess = function() {};
    open.onfailure = function() {};

    View Slide

  27. IndexedDB: Write/Read
    open.onsuccess = function() {
    var db = open.result;
    var tx = db.transaction("FancyNamedStore", "readwrite");
    var store = tx.objectStore("FancyNamedStore");
    var index = store.index("NameIndex");
    store.put({id: 12345, name: {first: "John", last: "Bar"}, age: 42});
    store.put({id: 67890, name: {first: "Bob", last: "Foo"}, age: 35});
    var getJohn = store.get(12345);
    var getBob = index.get(["Foo", "Bob"]);
    getJohn.onsuccess = function() {
    console.log(getJohn.result.name.first); // => "John"
    };
    getBob.onsuccess = function() {
    console.log(getBob.result.name.first); // => "Bob"
    };
    tx.oncomplete = function() {
    db.close();
    };
    }

    View Slide

  28. View Slide

  29. localForage* FTW!
    * or any other library…

    View Slide

  30. „localForage is a JavaScript library that improves the
    offline experience of your web app by using an
    asynchronous data store with a simple, localStorage-
    like API. It allows developers to store many types of
    data instead of just strings.“
    –https://localforage.github.io

    View Slide

  31. „localForage includes a localStorage-backed fallback
    store for browsers with no IndexedDB or WebSQL
    support. Asynchronous storage is available in the
    current versions of all major browsers: Chrome,
    Firefox, IE, and Safari (including Safari Mobile).“
    –https://localforage.github.io

    View Slide

  32. „localForage offers a callback API as well as support
    for the ES6 Promises API, so you can use
    whichever you prefer.“
    –https://localforage.github.io

    View Slide

  33. Modern Times
    Image © by Apple Computer Inc.

    View Slide

  34. Service
    Workers

    View Slide

  35. — https://github.com/w3c/ServiceWorker
    „Service workers are a new browser feature that
    provide event-driven scripts that run independently of
    web pages. Unlike other workers, service workers
    can be shut down at the end of events, note the lack
    of retained references from documents, and they
    have access to domain-wide events such as
    network fetches.“

    View Slide

  36. — https://github.com/w3c/ServiceWorker
    „Service workers also have scriptable caches. Along
    with the ability to respond to network requests from
    certain web pages via script, this provides a way for
    applications to “go offline”.“

    View Slide

  37. Introduction

    View Slide



  38. Internet
    1
    2

    View Slide



  39. Internet

    Service Worker
    1 2
    3

    View Slide



  40. Internet

    Service Worker

    Cache
    1
    2
    3
    3

    View Slide



  41. Internet

    Service Worker

    Cache
    5
    3
    2
    4
    1

    View Slide



  42. Internet

    Service Worker

    Cache

    1
    2
    3
    4

    View Slide

  43. Code

    View Slide

  44. Register Service Worker
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw-test/sw.js', {scope: '/sw-test/'})
    .then(function(reg) {
    // registration worked
    console.log('Registration succeeded. Scope is ' + reg.scope);
    }).catch(function(error) {
    // registration failed
    console.log('Registration failed with ' + error);
    });
    }

    View Slide

  45. Service Worker Overview
    self.addEventListener('install', function(event) {
    console.log("installed");
    });
    self.addEventListener('activate', function(event) {
    console.log("activated");
    });
    self.addEventListener('fetch', function(event) {
    console.log("fetch");
    event.respondWith(new Response("My response!!"));
    });

    View Slide

  46. Install
    self.addEventListener('install', function(event) {
    event.waitUntil(
    caches.open('v1').then(function(cache) {
    return cache.addAll([
    '/images/myImage.png',
    '/index.html'
    ]);
    })
    );
    });

    View Slide

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

    View Slide

  48. Fetch & Update Cache
    this.addEventListener('fetch', function(event) {
    event.respondWith(
    caches.match(event.request).then(function(resp) {
    return resp || fetch(event.request).then(function(response) {
    caches.open('v1').then(function(cache) {
    cache.put(event.request, response.clone());
    });
    return response;
    });
    }).catch(function() {
    return caches.match('/sw-test/gallery/myLittleVader.jpg');
    })
    );
    });

    View Slide

  49. Clean Up Cache
    this.addEventListener('activate', function(event) {
    var cacheWhitelist = ['v2'];
    event.waitUntil(
    caches.keys().then(function(keyList) {
    return Promise.all(keyList.map(function(key) {
    if (cacheWhitelist.indexOf(key) === -1) {
    return caches.delete(key);
    }
    }));
    })
    );
    });

    View Slide

  50. Update Cache
    var CACHE_NAME = 'static-v9';
    self.addEventListener('install', function(event) {
    event.waitUntil(
    caches.open(CACHE_NAME_STATIC).then(function(cache) {
    return cache.addAll(['...']);
    })
    )
    });
    self.addEventListener('activate', function(event) {
    var cacheWhitelist = [CACHE_NAME_STATIC];
    event.waitUntil(
    caches.keys().then(function(keyList) {
    return Promise.all(keyList.map(function(key) {
    if (cacheWhitelist.indexOf(key) === -1) {
    return caches.delete(key);
    }
    }));
    })
    );
    });

    View Slide

  51. We have the tools!

    View Slide

  52. Gonzalo Baeza - https://flic.kr/p/dCPzuE
    Now & The Future

    View Slide

  53. Progressive
    Web Apps

    View Slide

  54. –Ada Rose Edwards
    https://www.smashingmagazine.com/2016/09/the-building-blocks-of-progressive-web-apps/
    „An ideal web app is a web page that has the best
    aspects of both the web and native apps. It should
    be fast and quick to interact with, fit the device’s
    viewport, remain usable offline and be able to have
    an icon on the home screen.“

    View Slide

  55. OMG! PWA? WTF?
    • Progressive
    • Responsive
    • Connectivity independent
    • App-like
    • Safe
    • Discoverable
    • Installable
    • Linkable

    View Slide

  56. PWA Architecture
    „Thorsten“ - https://flic.kr/p/y3ib6k

    View Slide

  57. App Shell

    View Slide

  58. Service Workers
    www.audio-luci-store.it - https://flic.kr/p/hQannE

    View Slide

  59. Installability

    View Slide

  60. Push Notification
    • Allow SW to wake up
    • Works in Background, only SW is woken up
    • Needs permission from user!

    View Slide

  61. –W3C
    https://w3c.github.io/push-api/
    „The Push API enables sending of a push message
    to a webapp via a push service.“

    View Slide

  62. And Webpages?

    View Slide

  63. –Slightly modified by me…
    „An ideal web page is a web page that has the best
    aspects of both the web and native apps. It should
    be fast and quick to interact with, fit the device’s
    viewport and remain usable offline and be able to
    have an icon on the home screen.“

    View Slide

  64. Cache Data from APIs
    • localStorage
    • sessionStorage
    • IndexedDB

    View Slide

  65. Are you online?
    var online = navigator.onLine;
    if (!online) {
    // Fallback -> Get Data from Storage!
    }
    else {
    // Use network....
    }

    View Slide

  66. That’s easy!

    View Slide

  67. View Slide

  68. Wait?
    • Slow network? (Edge, GPRS etc.)
    • mobile networks are not reliable…
    • „Lie“-Fi

    View Slide

  69. Use Service Workers
    • Provide offline fallback
    • Cache static files
    • Controll the network ;)

    View Slide

  70. Demo

    View Slide

  71. GPRS

    View Slide

  72. GPRS + SW

    View Slide

  73. Considerations
    • Don't abuse offline caches.
    • How to deal with sensitive information?
    • Are my assets permanently stored?
    • Think about your use case!

    View Slide

  74. Always on
    is a lie.
    Carsten Sandtner
    @casarock
    [email protected]
    https://github.com/casarock
    ¯\_(ツ)_/¯

    View Slide