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

Auch ohne Netz: Offline-First Architekturen für HTML5 Apps

Auch ohne Netz: Offline-First Architekturen für HTML5 Apps

Christian Weyer

September 30, 2015
Tweet

More Decks by Christian Weyer

Other Decks in Programming

Transcript

  1. Christian Weyer • Co-founder, co-owner and principal consultant at Thinktecture

    AG • Focus on – Mobile & web-based application architectures – Interoperability, cross-device – Pragmatic end-to-end solutions • Microsoft MVP for ASP.NET (Architecture) ASP.NET Web API / vNext Advisory Board Member ASPInsider, AzureInsider • Google GDE for AngularJS • http://blogs.thinktecture.com/cweyer [email protected] @christianweyer 2
  2. Talking Points • Offline-First as a Must • Users Matter

    • When is “Offline”? • Caching • Data Storage • Synchronization 3
  3. Offline-First • Mobile-First is hip – … but it is

    not enough • Few web sites are designed to work offline • Few web apps are designed to work offline • Few mobile apps are designed to work offline • Offline-First == User-First 4
  4. Given Facts – Offline is everwhere • Countryside • Flight

    • Train • Costs • Roaming • Decide what „offline“ means to you/your apps 6
  5. 7

  6. 8

  7. 9

  8. 10

  9. User Experience • Let people interact with their content •

    Aggressive caching is a better user experience • Make error messages informative and consistent • Don’t show contradictory information • Don’t let people start something they can’t finish 11
  10. User Experience • When caching, choose breadth over depth •

    Design your empty states well • Never show the raw error message • Remember what your users were doing last • Never purge the cache while offline 12
  11. Detect Status: Browser Events • Status properties & events •

    May be unreliable with different results on various platforms • Need to write algorithm to ping well-known endpoint 14 window.addEventListener('load', function() { var status = document.getElementById("status"); function updateOnlineStatus(event) { var condition = navigator.onLine ? "online" : "offline"; status.className = condition; status.innerHTML = condition.toUpperCase(); } window.addEventListener('online', updateOnlineStatus); window.addEventListener('offline', updateOnlineStatus); });
  12. HTML5 AppCache • Adding static data/files to dedicated browser cache

    area – Based on root web page • Manifest describes what to cache • API to detect updates and act accordingly • Can be tough to test and debug • Usage information in browsers – chrome://appcache-internals/ in Chrome – help appcache in Firefox Developer Toolbar 17
  13. AppCache Manifest & API 18 <html manifest="example.appcache"> ... </html> CACHE

    MANIFEST # v1 2015-09-14 # This is another comment index.html cache.html style.css image1.png # Use from network if available NETWORK: network.html /api # Fallback content FALLBACK: / fallback.html if (window.applicationCache) { window.applicationCache.addEventListener( 'updateready', function() { if (confirm('An update is available. Reload now?')) { window.location.reload(); } }); }
  14. Service Workers • Browser-based applications need to perform work “outside

    the browser” • Rich offline experiences • Periodic background sync • Push notifications • … and more native-like functionality 20
  15. Service Workers • JavaScript Workers • Implement Lifecycle with events

    • Browser support to question – Especially on mobile platforms 21
  16. Web Storage • Two types of storage: Session and Local

    • Stores key/value pairs – Simple types & JSON • Properties – Storage.length • Methods – Storage.key() – Storage.getItem() – Storage.setItem() – Storage.removeItem() – Storage.clear() 24
  17. 25

  18. Session & Local Storage • sessionStorage and localStorage properties on

    window object • Difference – data stored in localStorage has no expiration time – data stored in sessionStorage gets cleared when the browsing session ends 26
  19. IndexedDB • NoSql database in the browser • Store and

    retrieve objects that are indexed with a key – rich query abilities • Changes to the database happen within transactions • Useful for applications that store large amount of data – Also for blobs • API can be challenging to use 30
  20. Dexie.js – IndexedDB Wrapper 31 var db = new Dexie('MyDatabase');

    // Define a schema db.version(1) .stores({ friends: 'name, age' }); // Open the database db.open() .catch(function(error){ alert('Uh oh : ' + error); }); // Find some old friends db.friends .where('age') .above(75) .each(function(friend){ console.log(friend.name); }); // or make a new one db.friends .add({ name: 'Camilla', age: 25 });
  21. Storage Abstractions • Sometimes you need an abstraction over the

    different stores • Mozilla‘s localForage is one of them 33 // In localStorage, we would do: localStorage.setItem('key', JSON.stringify('value')); doSomethingElse(); // With localForage, we use callbacks: localforage.setItem('key', 'value', doSomethingElse); // Or we can use Promises localforage.setItem('key', 'value').then(doSomethingElse);<
  22. Synchronization • „Offline“ heavily depends on use cases • Sometimes

    data needs to be synchronized – From server to device – From device to server • Conflicts will happen, for sure – Conflict resolution is king, but tough – Solutions based on functional requirements & logic • Certain architecture types can help – Like CQRS 34
  23. Conflicts “Conflicts are not an error condition, they are the

    result of your infrastructure allowing the same dataset to be modified across disconnected systems. The introduction of such conflicts in such a topology is the expected behavior and their programmatic resolution is a core piece of application logic.” 35 https://cloudant.com/blog/introduction-to-document-conflicts-part-two
  24. CouchDB & PouchDB • Apache CouchDB – Database that uses

    JSON for documents – JavaScript for MapReduce indexes – Regular HTTP for its API • PouchDB – Open-source JavaScript database – Inspired by CouchDB – Designed to run well within the browser • PouchDB can sync with CouchDB – Consider checking the inner workings of the sync protocol 37
  25. Summary • Offline should not be an exception • Prepare

    your architecture and your applications for being offline • Think about your users first! • Browsers have simple storages and powerful databases available • Synchronization can be complex and tedious – It all depends on the use cases 38
  26. Resources • Offline: When Your Apps Can’t Connect to the

    Internet – https://medium.com/user-experience-design-1/offline-93c2f8396124 • Mobile Apps Offline Support – http://www.infoq.com/articles/mobile-apps-offline-support • Introduction to CQRS – http://www.codeproject.com/Articles/555855/Introduction-to-CQRS • Working with quota on mobile browsers – http://www.html5rocks.com/en/tutorials/offline/quota-research/ • AppCache Nanny – https://github.com/gr2m/appcache-nanny • Gulp-manifest – https://github.com/hillmanov/gulp-manifest 39
  27. Resources • WebStorage API – https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API • IndexedDb API –

    http://w3c.github.io/IndexedDB/ • Storing images and files in IndexedDB – https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/ • Dexie.js – https://github.com/dfahlander/Dexie.js/wiki/Samples • LocalForage – http://mozilla.github.io/localForage/ • Apache CouchDB – http://couchdb.apache.org/ • PouchDB – http://pouchdb.com/ 40
  28. Resources • [email protected] • http://www.thinktecture.com • Thinktecture’s GitHub Repositories –

    https://github.com/thinktecture • Christian Weyer’s GitHub Repositories – https://github.com/ChristianWeyer 41