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. „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
  2. 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
  3. 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) {}
  4. • 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 • …
  5. 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));
  6. 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));
  7. WebStorages • easy to use! • good browser support! •

    But: • http/https define different stores! • asynchronous • Quota?
  8. –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.“
  9. 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() {};
  10. 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(); }; }
  11. „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
  12. „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
  13. „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
  14. — 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.“
  15. — 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”.“
  16. 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); }); }
  17. 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!!")); });
  18. 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'); }) ); });
  19. 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); } })); }) ); });
  20. 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); } })); }) ); });
  21. –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.“
  22. OMG! PWA? WTF? • Progressive • Responsive • Connectivity independent

    • App-like • Safe • Discoverable • Installable • Linkable
  23. Push Notification • Allow SW to wake up • Works

    in Background, only SW is woken up • Needs permission from user!
  24. –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.“
  25. Are you online? var online = navigator.onLine; if (!online) {

    // Fallback -> Get Data from Storage! } else { // Use network.... }
  26. Considerations • Don't abuse offline caches. • How to deal

    with sensitive information? • Are my assets permanently stored? • Think about your use case!