Share
Embed
Offline-First Apps with PouchDB at CodeMash
Web and mobile apps shouldn't stop working when there's limited or no network connectivity. Based on Apache CouchDB, PouchDB is an open source JavaScript database that can run within a web browser, Cordova mobile apps, or Node.js applications. An offline-first app built with PouchDB can store its data locally and then synchronize with a cloud database when it has a reliable network connection.
Bradley Holt
January 07, 2016
Transcript
62 slides
-
@BradleyHolt! Offline-First Apps with PouchDB CodeMash Thursday, January 7, 2016
Bradley Holt, Developer Advocate -
@BradleyHolt! Image Credit: A mockup of the golden Apple iPhone
5S by Zach Vega, on Wikimedia Commons -
@BradleyHolt! Image Credits: A mockup of the golden Apple iPhone
5S by Zach Vega, on Wikimedia Commons; Joan Touzet (@wohali), ASF Member, CouchDB PMC Member -
@BradleyHolt! Image Credit: Device landscape by Jeremy Keith, on Flickr
Not just mobile first…! -
@BradleyHolt! Image Credit: Cloud Formation Over the Adirondacks by Bradley
Holt Offline First! Because being offline shouldn't be an error condition.! -
@BradleyHolt! Doesn't ubiquitous connectivity make offline- enabled apps unnecessary?! Image
Credit: Cell phone tower by Gary Lerude, on Flickr -
@BradleyHolt! Quite the opposite, in fact.! Image Credit: Tangled Network
by Bruno Girin, on Flickr -
@BradleyHolt! Ubiquitous connectivity is driving the demand for offline
capabilities.! Image Credit: Wired by Alexandre Duret-Lutz, on Flickr -
@BradleyHolt! The Eight Fallacies of Distributed Computing 1. The network
is reliable 2. Latency is zero 3. Bandwidth is infinite 4. The network is secure 5. Topology doesn't change 6. There is one administrator 7. Transport cost is zero 8. The network is homogeneous Text Credit: The Eight Fallacies of Distributed Computing by Peter Deutsch | Image Credit: Pneumatic Central by Sleestak, on Flickr -
@BradleyHolt! Image Credit: Connected version 2 by Hans Kylberg, on
Flickr Offline-first is the only way to achieve a true, 100% always-on user experience.* ! *assuming the device is reliable! -
@BradleyHolt! Faster User Experience! Image Credit: Speed DLR on Doklands
by Umberto Rotundo, on Flickr -
@BradleyHolt! Works Offline! Image Credit: Lynn Camp Prong (Explored) by
AllieKF, on Flickr -
@BradleyHolt! Battery and Bandwidth! Image Credit: Panorama of the Molasses
Disaster site by Boston Public Library, on Flickr -
@BradleyHolt! Image Credit: A mockup of the golden Apple iPhone
5S by Zach Vega, on Wikimedia Commons -
@BradleyHolt! Image Credit: A mockup of the golden Apple iPhone
5S by Zach Vega, on Wikimedia Commons -
@BradleyHolt! Image Credit: A mockup of the golden Apple iPhone
5S by Zach Vega, on Wikimedia Commons -
@BradleyHolt! Image Credit: A mockup of the golden Apple iPhone
5S by Zach Vega, on Wikimedia Commons -
@BradleyHolt! Image Credit: A mockup of the golden Apple iPhone
5S by Zach Vega, on Wikimedia Commons -
@BradleyHolt! Frontend Web Apps • Build responsive mobile web apps
that work offline • PouchDB adapters available for many popular frameworks • Enable full offline usage with service workers -
@BradleyHolt! Backend Web Apps • Use PouchDB as the database
for your Node.js applications • Installable via npm (pouchdb) • Use PouchDB Server (pouchdb-server) as a drop-in replacement for CouchDB -
@BradleyHolt! Mobile Apps • Hybrid Mobile Web Apps • HTML5,
CSS and JavaScript apps compiled into native mobile apps • Fully-featured, cross-platform native apps • High-fidelity prototypes • Native Mobile Web Apps • Cloudnat Sync for iOS • Cloudant Sync for Android -
@BradleyHolt! Desktop Apps • Use Electron to build cross-platform desktop
apps with web technologies • Formerly known as Atom Shell • HTML5, CSS and JavaScript apps compiled into native desktop apps -
@BradleyHolt! Internet of Things (IoT) Apps • Headless Node.js apps
• PouchDB includes a LevelDB adapter for use in Node.js • Redis, Riak, and in-memory adapters are also available • Good for: • Internet of Things (IoT) applications • Content delivery networks (CDN) • Purpose-built devices Image Credit: Ethernet IoT Starter Kit -
@BradleyHolt! PouchDB Data Storage Limits Firefox Chrome Opera 15+ Internet
Exporer 10+ iOS Safari Safari (desktop) Android PhoneGap / Cordova Data Storage Limit 50MB (more with user permission) calculated calculated 250MB (prompts user at 10 MB) 50MB (prompts user at 5MB and at increments) unlimited (prompts user at 5MB and at increments) calculated / 200MB unlimited Adapter IndexedDB IndexedDB / WebSQL IndexedDB / WebSQL IndexedDB WebSQL WebSQL IndexedDB / WebSQL SQLite Source: http://pouchdb.com/faq.html#data_limits -
@BradleyHolt! IBM Cloudant • Globally distributed data layer for web
and mobile applications • MongoDB-style queries • Advanced geospatial capabilities • Full text search indexing -
@BradleyHolt! JSON Documents { _id: "6EF9D2B0-13D3-1378-8D30-39E3CE0B36C2", _rev: "1-0b457efcf82fb29492ef927ba5b6ee15", type: "Feature",
geometry: { type: "Point", coordinates: [ -71.1028, 42.3691 ] }, properties: { session_id: "3486b13f-7b8a-8a96-dfbf-9b82800e367f", timestamp: 1422928591717 } } -
@BradleyHolt! Creating a Local PouchDB Database var db = new
PouchDB("smart-meter");" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/01-create-local-database.js -
@BradleyHolt! Creating a Remote PouchDB Database var remoteDb = new
PouchDB("https://bradley-holt.cloudant.com/smart-meter");" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/02-create-remote-database.js -
@BradleyHolt! Cross-Origin Resource Sharing (CORS) • Enable Cross-Origin Resource Sharing
(CORS) on remote database • Browsers place security restrictions on cross-site HTTP requests • If you run into a problem, remember this warning! Image Credit: Grunge Warning Sign - Do Not Read This Sign by Nicolas Raymond, on Flickr -
@BradleyHolt! Creating a New Document var db = new PouchDB("smart-meter");"
db.put({" _id: "2014-11-12T23:27:03.794Z"," kilowatt_hours: 14" }).then(function() {" console.log("Document created");" }).catch(function(error) {" console.log(error);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/04-create-document-put.js -
@BradleyHolt! Updating a Document db.put({" _id: "2014-11-12T23:27:03.794Z"," kilowatt_hours: 14" }).then(function(response)
{" return db.get(response.id);" }).then(function(doc) {" // Update the value for kilowatt hours" doc.kilowatt_hours = 15;" // Put the document back to the database" return db.put(doc);" }).catch(function(error) {" console.log(error);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/05-update-document.js -
@BradleyHolt! Deleting a Document db.put({" _id: "2014-11-12T23:27:03.794Z"," kilowatt_hours: 14" }).then(function(response)
{" // Get the document" return db.get(response.id);" }).then(function(doc) {" // Remove the document from the database" return db.remove(doc);" }).catch(function(error) {" console.log(error);" });" " https://github.com/bradley-holt/offline-first/blob/master/pouchdb/06-delete-document.js -
@BradleyHolt! Querying a Database with allDocs! db.bulkDocs([" {_id: "2014-11-12T23:27:03.794Z", kilowatt_hours:
14}," {_id: "2014-11-13T00:52:01.471Z", kilowatt_hours: 15}," {_id: "2014-11-13T01:39:28.911Z", kilowatt_hours: 16}," {_id: "2014-11-13T02:52:01.471Z", kilowatt_hours: 17}" ]).then(function(result) {" // Get all documents" return db.allDocs({include_docs: true});" }).then(function(response) {" console.log(response);" }).catch(function(error) {" console.log(error);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/07-query-database-all-docs.js -
@BradleyHolt! allDocs Options • include_docs" • conflicts" • attachments" •
startkey" • endkey" • inclusive_end (true by default) • limit" • skip" • descending" • key" • keys" -
@BradleyHolt! Querying a Database with Map/Reduce • Most queries can
be done with allDocs (in PouchDB) • Map functions transform documents into indexes • Reduce functions aggregate results of Map functions • _sum" • _count" • _stats" -
@BradleyHolt! Querying a Database with PouchDB Find • Based on
Cloudant Query (Mango) • MongoDB-style query language • Define fields to index Image Credit: Mango with section on a white background by bangdoll, on Flickr -
@BradleyHolt! Listening for Database Changes var changes = remoteDb.changes({" since:
"now"" }).on("change", function(change) {" // A document has changed" console.log(change);" }).on("complete", function(info) {" // changes() was canceled" console.log(info);" }).on("error", function(error) {" // changes() has errored" console.log(error);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/11-database-changes.js -
@BradleyHolt! Listening for Database Changes // Create several documents" remoteDb.bulkDocs(["
{_id: "2014-11-11T22:35:01.433Z", kilowatt_hours: 11}," {_id: "2014-11-12T00:43:01.633Z", kilowatt_hours: 13}," {_id: "2014-11-12T02:42:52.284Z", kilowatt_hours: 14}," {_id: "2014-11-12T02:46:23.730Z", kilowatt_hours: 16}" }).catch(function(error) {" console.log(error);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/11-database-changes.js -
@BradleyHolt! Clemmie Danyel Shelba Manuel Francis Marissa Mitchel Georgianne Garnet
Audrey Kalyn Image Credit: database by Tim Morgan, on Flickr -
@BradleyHolt! 1b40d0a4 c28e6965 3fa0bee7 e83a0aeb cbdca6de ef9443e2 8e4d5a03 2e070be6 271dc425
9a278e5e f4215dfa Image Credit: database by Tim Morgan, on Flickr -
@BradleyHolt! Write-Only Replication • Data generated on the device •
Replicate this data to the cloud from multiple users and/or devices • Example uses: • User updates • Sensor data -
@BradleyHolt! Write-Only Replication var db = new PouchDB("smart-meter");" var remoteDb
= new PouchDB(" "https://bradley-holt.cloudant.com/smart-meter"" );" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/08-replicate-database.js -
@BradleyHolt! Write-Only Replication db.bulkDocs([" {_id: "2014-11-12T23:27:03.794Z", kilowatt_hours: 14}," {_id: "2014-11-13T00:52:01.471Z",
kilowatt_hours: 15}," {_id: "2014-11-13T01:39:28.911Z", kilowatt_hours: 16}," {_id: "2014-11-13T02:52:01.471Z", kilowatt_hours: 17}" ]).then(function(result) {" …" }).catch(function(error) {" console.log(error);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/08-replicate-database.js -
@BradleyHolt! Write-Only Replication db.replicate.to(remoteDb, {" live: false," retry: false" }).on("change",
function(info) {" // Replication has written a new document" console.log(info);" }).on("complete", function(info) {" // Replication has complete or been cancelled" console.log(info);" }).on("error", function(error) {" // Replication has stopped due to an unrecoverable failure" console.log(error);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/08-replicate-database.js -
@BradleyHolt! Read-Only Replication • Data generated in the cloud •
Replicate this data to multiple users and/or devices from the cloud • Example uses: • Weather • Notifications -
@BradleyHolt! Read-Only Replication remoteDb.replicate.to(db, {" live: false," retry: false" }).on("change",
function(info) {" // Replication has written a new document" console.log(info);" }).on("complete", function(info) {" // Replication has complete or been cancelled" console.log(info);" }).on("error", function(error) {" // Replication has stopped due to an unrecoverable failure" console.log(error);" });" -
@BradleyHolt! Bidirectional Replication • Data generated on both the device
and in the cloud • Replicate this data to/from the cloud and to/from multiple users and/or devices • Useful when you need to share data between users and/or devices -
@BradleyHolt! Bidirectional Replication db.sync(remoteDb, {" live: false," retry: false" }).on("change",
function(info) {" // Replication has written a new document" console.log(info);" }).on("complete", function(info) {" // Replication has complete or been cancelled" console.log(info);" }).on("error", function(error) {" // Replication has stopped due to an unrecoverable failure" console.log(error);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/09-replicate-database-bidirectional.js -
@BradleyHolt! Live Replication var sync = db.sync(remoteDb, {" live: true,"
retry: true" }).on("change", function(info) {" // Replication has written a new document" console.log(info);" }).on("complete", function(info) {" // Replication has complete or been cancelled" console.log(info);" }).on("error", function(error) {" // Replication has stopped due to an unrecoverable failure" console.log(error);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/10-replicate-database-live.js -
@BradleyHolt! Filtered Replication • Select (with a function) which documents
to replicate • Filter can be defined locally within PouchDB, or remotely on Cloudant -
@BradleyHolt! Filtered Replication db.replicate.to(remoteDb, {" filter: function(doc) {" return doc._id
>= "2014-11-13T00:00:00.000Z";" }" }).on("change", function(info) {" // Replication has written a new document" console.log(info);" }).on("complete", function(info) {" // Replication has complete or been cancelled" console.log(info);" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/12-replicate-database-filtered.js -
@BradleyHolt! Boilerplates & Tools • Frontend Web Apps • React
Boilerplate with Service Workers <https://github.com/mbrio/react-boilerplate/tree/react-0.13-flummox-service> • Backend Web Apps • PouchDB npm Package <https://www.npmjs.com/package/pouchdb> • PouchDB Server npm Package <https://www.npmjs.com/package/pouchdb-server> • Mobile Apps • PouchDB for Ionic Framework <https://github.com/nolanlawson/pouchdb-ionic> • "Hello world" Cordova app with PouchDB <https://github.com/nolanlawson/pouchdb-cordova-hello-world> • "Hello world" Cordova app with PouchDB, using the SQLite Plugin <https://github.com/nolanlawson/pouchdb-cordova-hello-world-with-sqlite-plugin> • Cloudant FoodTracker (uses Cloudant Sync for iOS) <https://github.com/ibm-cds-labs/cloudant-food-tracker> • Desktop Apps • PouchDB for Electron (formerly Atom Shell) <https://github.com/nolanlawson/pouchdb-electron> • PouchDB for Chrome packaged apps <https://github.com/nolanlawson/pouchdb-chrome-app> • "Hello world" Chrome app with PouchDB <https://github.com/nolanlawson/pouchdb-chrome-app-hello-world> • PouchDB for NW.js (aka Node-Webkit) <https://github.com/nolanlawson/pouchdb-nw> • Internet of Things (IoT) Apps • Node-RED <http://nodered.org/> -
IBM Cloud Data Services Open for Data A comprehensive por.olio
of open source data services -
@BradleyHolt! Image Credits • A mockup of the golden Apple
iPhone 5S by Zach Vega, on Wikimedia Commons <https://commons.wikimedia.org/wiki/File:IPhone_5s.png> • Joan Touzet (@wohali), ASF Member, CouchDB PMC Member <https://twitter.com/wohali/status/595689720933445632> • Device landscape by Jeremy Keith, on Flickr <https://flic.kr/p/anLcHu> • Cloud Formation Over the Adirondacks by Bradley Holt <https://twitter.com/BradleyHolt/status/623030107679002624> • Cell phone tower by Gary Lerude, on Flickr <https://flic.kr/p/crLdJE> • Internet Splat Map by Steve Jurvetson, on Flickr <https://flic.kr/p/5Gky> • Tangled Network by Bruno Girin, on Flickr <https://flic.kr/p/7sdJw> • Wired by Alexandre Duret-Lutz, on Flickr <https://flic.kr/p/2ZCmpx> • connect me to BR549 by frankieleon, on Flickr <https://flic.kr/p/a1C62U> • Pneumatic Central by Sleestak, on Flickr <https://flic.kr/p/mRvRQ> • Connected version 2 by Hans Kylberg, on Flickr <https://flic.kr/p/4yN2FZ> • Speed DLR on Doklands by Umberto Rotundo, on Flickr <https://flic.kr/p/7GmcUo> • Lynn Camp Prong (Explored) by AllieKF, on Flickr <https://flic.kr/p/o6q1UG> • Panorama of the Molasses Disaster site by Boston Public Library, on Flickr <https://flic.kr/p/8t8KCM> • Ethernet IoT Starter Kit <https://developer.mbed.org/platforms/IBMEthernetKit/> • Grunge Warning Sign - Do Not Read This Sign by Nicolas Raymond, on Flickr <https://flic.kr/p/cirSCd> • Mango with section on a white background by bangdoll, on Flickr <https://flic.kr/p/9CBP2h> • database by Tim Morgan, on Flickr <https://flic.kr/p/7DUk5>