Slide 1

Slide 1 text

ConFoo 2016 Bradley Holt, Developer Advocate Thursday, February 25, 2016 Offline-First Apps with PouchDB @BradleyHolt

Slide 2

Slide 2 text

Why offline first?

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Mobile First Design for the smallest device first and then apply progressive enhancement techniques to take advantage of larger screen sizes

Slide 6

Slide 6 text

Offline First Design for offline usage first and then apply progressive enhancement techniques to take advantage of network connectivity when available

Slide 7

Slide 7 text

Ubiquitous Connectivity Why offline first in a world of ubiquitous connectivity?

Slide 8

Slide 8 text

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 @BradleyHolt

Slide 9

Slide 9 text

Mobile Backend What happens when your mobile backend service is unreachable?

Slide 10

Slide 10 text

Benefits of Offline First

Slide 11

Slide 11 text

Faster User Experience Better, faster user experience — both offline and online

Slide 12

Slide 12 text

Works Offline Ability to disconnect and continue to work offline

Slide 13

Slide 13 text

Battery and Bandwidth Limited access to power and communications infrastructure in disaster scenarios

Slide 14

Slide 14 text

Offline-First Patterns and Anti-Patterns

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Tools and Use Cases

Slide 21

Slide 21 text

CouchDB Replication Protocol @BradleyHolt Cloudant Sync IBM Cloudant DBaaS CouchDB PouchDB CouchDB Replication Protocol

Slide 22

Slide 22 text

@BradleyHolt

Slide 23

Slide 23 text

PouchDB Code Examples

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

IBM Cloudant §  Globally distributed data layer for web and mobile applications §  MongoDB-style queries §  Advanced geospatial capabilities §  Full text search indexing @BradleyHolt

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

Creating a Local PouchDB Database var db = new PouchDB("smart-meter"); @BradleyHolt

Slide 28

Slide 28 text

Creating a Remote PouchDB Database var remoteDb = new PouchDB("https://bradley-holt.cloudant.com/smart-meter"); @BradleyHolt

Slide 29

Slide 29 text

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! @BradleyHolt

Slide 30

Slide 30 text

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); }); @BradleyHolt

Slide 31

Slide 31 text

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); }); @BradleyHolt

Slide 32

Slide 32 text

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); }); @BradleyHolt

Slide 33

Slide 33 text

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); }); @BradleyHolt

Slide 34

Slide 34 text

allDocs Options §  include_docs – conflicts – attachments §  startkey §  endkey §  inclusive_end (true by default) §  limit §  skip §  descending §  key §  keys @BradleyHolt

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Querying a Database with PouchDB Find §  Based on Cloudant Query, aka Mango §  MongoDB-style query language §  Define fields to index @BradleyHolt

Slide 37

Slide 37 text

Replication Patterns

Slide 38

Slide 38 text

One Database Per User @BradleyHolt Clemmie Danyel Shelba Manuel Francis Marissa Mitchel Georgianne Garnet Audrey Kalyn

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

Write-Only Replication var db = new PouchDB("smart-meter"); var remoteDb = new PouchDB( "https://bradley-holt.cloudant.com/smart-meter" ); @BradleyHolt

Slide 41

Slide 41 text

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); }); @BradleyHolt

Slide 42

Slide 42 text

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); }); @BradleyHolt

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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); }); @BradleyHolt

Slide 47

Slide 47 text

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); }); @BradleyHolt

Slide 48

Slide 48 text

Filtered Replication §  Select (with a function) which documents to replicate §  Filter can be defined locally within PouchDB, or remotely on Cloudant @BradleyHolt

Slide 49

Slide 49 text

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); }); @BradleyHolt

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

Boilerplates & Tools §  Frontend Web Apps –  React Boilerplate with Service Workers §  Backend Web Apps –  PouchDB npm Package –  PouchDB Server npm Package §  Mobile Apps –  PouchDB for Ionic Framework –  "Hello world" Cordova app with PouchDB –  "Hello world" Cordova app with PouchDB, using the SQLite Plugin –  Cloudant FoodTracker (uses Cloudant Sync for iOS) §  Desktop Apps –  PouchDB for Electron (formerly Atom Shell) –  PouchDB for Chrome packaged apps –  "Hello world" Chrome app with PouchDB –  PouchDB for NW.js (aka Node-Webkit) §  Internet of Things (IoT) Apps –  Node-RED @BradleyHolt

Slide 52

Slide 52 text

Cloudant FoodTracker

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

Image Credits §  A mockup of the golden Apple iPhone 5S by Zach Vega, on Wikimedia Commons §  Joan Touzet (@wohali), ASF Member, CouchDB PMC Member §  Device landscape by Jeremy Keith, on Flickr §  Cloud Formation Over the Adirondacks by Bradley Holt, on Twitter §  Cell phone tower by Gary Lerude, on Flickr §  Pneumatic Central by Sleestak, on Flickr §  Colunas by Daniel Zanini H., on Flickr §  Speed DLR on Doklands by Umberto Rotundo, on Flickr §  Waterfall by Paulo Valdivieso, on Flickr §  Wildfire by U.S. Fish and Wildlife Service Southeast Region, on Flickr §  Arduino Uno by Pete Prodoehl, on Flickr §  Grunge Warning Sign - Do Not Read This Sign by Nicolas Raymond, on Flickr §  Mango with section on a white background by bangdoll, on Flickr @BradleyHolt

Slide 55

Slide 55 text

Questions? @BradleyHolt