Offline-First Apps for an Always-on UX DroidCON Berlin – June 2016
Glynn Bird, Developer Advocate, IBM @glynn_bird
@glynn_bird
…On the Move
@glynn_bird
3
@glynn_bird
4
@glynn_bird
5
@glynn_bird
Image Credit: Joan Touzet (@wohali), ASF Member, CouchDB PMC Member
@glynn_bird 6
Responsive Frameworks
@glynn_bird 7
Not just mobile first…
Image Credit: Device landscape by Jeremy Keith, on Flickr
@glynn_bird 8
Offline-First
Offline First
Image Credit: NASA New Horizons
@glynn_bird 9
Offline, online and somewhere in-between
@glynn_bird 10
Distributed systems are hard
@glynn_bird 11
Offline-first is the only way to achieve a true, 100% always-on user assuming the device is reliable experience.* *
@glynn_bird 12
Benefits of Offline First • Better, faster user experience, both offline and online • Allow your users to work offline or with limited connectivity • Potentially saves battery life and bandwidth usage
@glynn_bird 13
Offline Patterns & Anti-Patterns • Don't return an error for no reason • Do let users view cached/saved data • Do synchronize data when connected • Consider letting your users decide when to sync • Think about the UX of users seeing stale data
@glynn_bird 14
Difficulties of Offline First
Image credit http://www.sneakerheadvc.com/wp-content/uploads/2012/02/Apple_iSync1.png
@glynn_bird 15
Introducing CouchDB & IBM Cloudant
@glynn_bird
Apache CouchDB • JSON document store • HTTP API • Replication • Free, open-source
@glynn_bird 17
Apache CouchDB – built to replicate • MVCC for document versioning • Replication • One-way or Two-way • One-shot or continuous
@glynn_bird 18
Apache CouchDB – built to replicate 2 . 0
Cloudant Geo
Cloudant Search (Lucene)
Dashboard
Cloudant Query (Mango)
multi-node clustering
@glynn_bird 19
IBM Cloudant – built for scale
@glynn_bird 20
IBM Cloudant • Globally distributed data layer for web and mobile applications • Run as-a-service • MongoDB-style queries • Advanced geospatial capabilities • Full text search indexing
@glynn_bird 21
Cloudant Sync • Stores data using SQLite • TouchDB provides MVCC • Replication to Cloudant over HTTPS • Cloudant Query API
@glynn_bird
Mobile Web Apps vs Native PouchDB
@glynn_bird
Storage Web App - PouchDB
Native App - CloudantSync
• In-browser database
• In-app database
• Can synchronize with any database that implements the CouchDB Replication Protocol
• Can synchronize with any database that implements the CouchDB Replication Protocol
• Free, open-source
• Free, open-source
@glynn_bird 24
Installation Native App - CloudantSync compile 'com.cloudant:cloudant-sync-datastore-android:latest.release'
Web App - PouchDB <script src="pouchdb.js">
@glynn_bird 25
A document Native App - CloudantSync MutableDocumentRevision revision = new MutableDocumentRevision(); Map<String,String> body = new HashMap<String, String>(); body.put("event", "droidcon"; body.put("type", "conference"); body.put("date", "2016-06-17"); revision.body = DocumentBodyFactory.create(body); Web App - PouchDB var doc = { event: "droidcon", type: "conference", date: "2016-06-17" }; @glynn_bird 26
Write doc Native App - CloudantSync DocumentRevision rev = datastore.createDocumentFromRevision(revision);
Web App - PouchDB db.post(doc, function(err, data) { } );
@glynn_bird 27
Read doc Native App - CloudantSync datastore.getDocument("droidcon");
Web App - PouchDB db.get("droidcon", function(err, data) { } );
@glynn_bird 28
Querying a Database with Mango • MongoDB-style query language db.fi n d({ selector: { nam e: 'M ario' debut: { '$gt': 1990 } }, fi elds: ['_id', 'lastnam e'], sort: ['lastnam e'] })...
Image Credit: Mango with section on a white background by bangdoll, on Flickr
@glynn_bird 29
Query Native App - CloudantSync IndexManager indexManager = new IndexManager(datastore); Object[] fields = {"conference"}; indexManager.ensureIndexed(Arrays.toList(fields), "conference"); Map<String,Object> selector = new HashMap<String,Object>(); selector.put("conference","droidcon"); QueryResult result = indexManager.find(selector); Web App – PouchDB with PouchDB-find plugin var q = { fields: ["conference"], selector: { conference: "droidcon"} }; db.find(q, function(err, data) { } ); @glynn_bird 30
Replication Native App - CloudantSync URL remoteDB = new URL("http://example.com/db"); Replicator pull = ReplicatorBuilder.pull().from(remoteDB).to(datastore).build(); pull.start(); Replicator push = ReplicatorBuilder.push().from(datastore).to(remoteDB).build(); push.start();
Web App – PouchDB with PouchDB-find plugin var remote = new PouchDB("http://example.com/db"); db.sync(remote);
@glynn_bird 31
Web Apps Going Offline
@glynn_bird
HTML5 Offline Application Cache • Enables fully-functional offline web apps • Stores files and assets for offline browsing • Makes page loads very fast, even when online
@glynn_bird 33
Cache Manifest File … CACHE MANIFEST # v1 - 2015-01-08 index.html logo.png app.css app.js
@glynn_bird 34
Service Workers (Beta) Client-side scripting framework for •programmable cache •sync •push messaging •geo-fencing •background tasks
https://jakearchibald.github.io/isserviceworkerready/
@glynn_bird 35
Progressive Web Apps (PWAs) •Responsive •Offline-first •App-like •Auto-update •Installable •Linkable
pokedex.org @glynn_bird 36
Hybrid Mobile Web Apps • Native mobile web apps built with HTML5, CSS and JavaScript • Good for: • Fully-featured, cross-platform native apps • High-fidelity prototypes
@glynn_bird 37
Pro Forma • Define fields you want to collect • Renders form saving data to PouchDB • Replicates data to Cloudant • Demo https://glynnbird.github.io/proforma/
@glynn_bird 38
MD • Offline word processor • Saves Markdown documents to PouchDB • Replicates data to Cloudant • Demo http://mddoc.mybluemix.net/
@glynn_bird 39
Gutenberg • Offline e-book reader • Replicates book list from server • Each book is a Cloudant database • Demo http://glynnbird.github.io/gutenberg/
@glynn_bird 40
www.glynnbird.com • My home page • Cloudant database of articles • Replicated to PouchDB • Appcache for offline first • http://www.glynnbird.com/
@glynn_bird 41
Volt • Password vault in a Chrome extension • Data stored in encrypted in PouchDB • Optional back to CouchDB/Cloudant • https://github.com/glynnbird/volt
@glynn_bird 42
BadgeScanner • Offline-first QR badge scanner • Data stored n PouchDB • Optional backup to CouchDB/Cloudant • https://github.com/glynnbird/badgescanner • https://badgescanner.mybluemix.net/
@glynn_bird 43
Location Tracker • Stores data locally in PouchDB • Front end built with AngularJS • Authentication logic built with Node.js • User interface built with Leaflet • Replicates location data to Cloudant • More info: https://cloudant.com/location-tracker/ • https://developer.ibm.com/clouddataser vices/2016/06/14/location-tracker-part -1-offline-first/ @glynn_bird 44
Glynn Bird Developer Advocate, Cloud Data Services
[email protected] @glynn_bird github.com/glynnbird
@glynn_bird