Slide 1

Slide 1 text

O'Reilly Fluent Bradley Holt, Developer Advocate Thursday, March 10, 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 when available

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 CouchDB PouchDB CouchDB Replication Protocol CouchDB

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

@BradleyHolt

Slide 24

Slide 24 text

PouchDB Code Examples github.com/bradley-holt/offline-first

Slide 25

Slide 25 text

No content

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 PouchDB Database var db = new PouchDB("smart-meter"); @BradleyHolt

Slide 28

Slide 28 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 29

Slide 29 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 30

Slide 30 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 31

Slide 31 text

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

Slide 32

Slide 32 text

PouchDB Data Storage Limits @BradleyHolt 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

Slide 33

Slide 33 text

Replication

Slide 34

Slide 34 text

Apache CouchDB CouchDB is a document database featuring an HTTP API, JSON documents, and peer-to-peer replication @BradleyHolt

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

Cross-Origin Resource Sharing (CORS) A security restriction implemented by browsers on cross-site HTTP requests @BradleyHolt

Slide 38

Slide 38 text

Bidirectional Replication @BradleyHolt

Slide 39

Slide 39 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 40

Slide 40 text

Live Replication @BradleyHolt

Slide 41

Slide 41 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 42

Slide 42 text

Filtered Replication @BradleyHolt

Slide 43

Slide 43 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 44

Slide 44 text

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

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 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 47

Slide 47 text

Cloudant FoodTracker An offline-first demo app built with Swift and Cloudant Sync for iOS

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 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 §  Warning by Stefano Brivio, on Flickr @BradleyHolt

Slide 50

Slide 50 text

Questions? @BradleyHolt