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

Building Offline-Enabled Apps with PouchDB at NoSQL Now!

Building Offline-Enabled Apps with PouchDB at NoSQL Now!

Based on the Apache CouchDB database, PouchDB is an open source syncing JavaScript database that runs within a web browser. Learn how to use the HTML5 Offline Application Cache, PouchDB, CouchDB, and Cordova/PhoneGap to develop fully-featured and cross-platform native apps, responsive mobile web apps, or high-fidelity prototypes that work just as well offline as they do online.

This talk will demonstrate creating a PouchDB database, creating a new document, updating a document, deleting a document, querying a database, synchronization PouchDB with a remote database, and live updates to a user interface based on database changes.

PouchDB works within mobile browsers including iOS Safari, Android Browser, BlackBerry Browser, Opera Mobile, Chrome for Android, Firefox for Android, and Internet Explorer Mobile. PouchDB will also run within desktop web browsers including Firefox, Chrome, Opera, Safari, and Internet Explorer. Additionally, PouchDB can be used on the server side with Node.js.

8896271ee9d6f46d4b1783c9566cb645?s=128

Bradley Holt

August 18, 2015
Tweet

Transcript

  1. @BradleyHolt! Building Offline-Enabled Apps with PouchDB NoSQL Now! Tuesday, August

    18, 2015 Bradley Holt, Developer Advocate
  2. @BradleyHolt! Image Credit: Joan Touzet (@wohali), ASF Member, CouchDB PMC

    Member
  3. @BradleyHolt! Image Credit: Device landscape by Jeremy Keith, on Flickr

    Not just mobile first…!
  4. @BradleyHolt! Image Credit: Cloud Formation Over the Adirondacks by Bradley

    Holt Offline First! Because being offline shouldn't be an error condition.!
  5. @BradleyHolt! Doesn't ubiquitous connectivity make offline- enabled apps unnecessary?! Image

    Credit: Cell phone tower by Gary Lerude, on Flickr
  6. @BradleyHolt! No.! Image Credit: Internet Splat Map by Steve Jurvetson,

    on Flickr
  7. @BradleyHolt! Quite the opposite, in fact.! Image Credit: Tangled Network

    by Bruno Girin, on Flickr
  8. @BradleyHolt! Ubiquitous connectivity is driving the demand for 
 offline

    capabilities.! Image Credit: Wired by Alexandre Duret-Lutz, on Flickr
  9. @BradleyHolt! How?! Image Credit: connect me to BR549 by frankieleon,

    on Flickr
  10. @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
  11. @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!
  12. @BradleyHolt! Faster User Experience! Image Credit: Speed DLR on Doklands

    by Umberto Rotundo, on Flickr
  13. @BradleyHolt! Works Offline! Image Credit: Lynn Camp Prong (Explored) by

    AllieKF, on Flickr
  14. @BradleyHolt! Battery and Bandwidth! Image Credit: Panorama of the Molasses

    Disaster site by Boston Public Library, on Flickr
  15. @BradleyHolt! Offline Patterns & Anti-Patterns •  Don't return an error

    for no reason •  Do let users view cached/saved data •  Do synchronize data when connected
  16. @BradleyHolt! Offline Patterns & Anti-Patterns •  Don't return an error

    for no reason •  Do let users view cached/saved data •  Do synchronize data when connected
  17. @BradleyHolt! Offline Patterns & Anti-Patterns •  Don't return an error

    for no reason •  Do let users view cached/saved data •  Do synchronize data when connected
  18. @BradleyHolt! Offline Patterns & Anti-Patterns •  Don't return an error

    for no reason •  Do let users view cached/saved data •  Do synchronize data when connected
  19. @BradleyHolt! Introducing PouchDB

  20. @BradleyHolt! PouchDB •  A database in your web browser • 

    Can synchronize with any database that implements the CouchDB Replication Protocol •  Makes create, read, update and delete operations extremely fast
  21. @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
 }
 }
  22. @BradleyHolt! PouchDB Framework Adapters

  23. @BradleyHolt! Responsive Mobile Web Apps, Hybrid Mobile Web Apps, or

    Internet of Things (IoT)
  24. @BradleyHolt! Responsive Mobile Web Apps •  HTML5, CSS and JavaScript

    mobile web apps •  Responsive design •  Enhanced to enable offline usage
  25. @BradleyHolt! 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
  26. @BradleyHolt! Internet of Things (IoT) •  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
  27. @BradleyHolt! Apache CouchDB

  28. @BradleyHolt! Apache CouchDB •  JSON document database •  HTTP API

    •  Master-master replication
  29. @BradleyHolt! IBM Cloudant •  Globally distributed data layer for web

    and mobile applications •  MongoDB-style queries •  Advanced geospatial capabilities •  Full text search indexing
  30. @BradleyHolt! PouchDB and Cloudant Replication

  31. @BradleyHolt! CouchDB Replication Protocol •  One-off, one way operation • 

    Peer-to-peer (masterless) •  Incremental •  Conflict detection
  32. @BradleyHolt! Apache Cordova, PhoneGap and Ionic

  33. @BradleyHolt! Apache Cordova and PhoneGap Image Credit: build.phonegap by Andrés

    Álvarez Iglesias, on Flickr
  34. @BradleyHolt! Ionic •  Mobile-optimized HTML, CSS and JavaScript components • 

    Builds on Apache Cordova •  Utilizes AngularJS •  CLI installable via npm
  35. @BradleyHolt! Using Cordova and Ionic $ npm install -g cordova

    ionic" $ ionic start energy-monitor tabs" $ cd energy-monitor" $ ionic platform add ios" $ ionic build ios" $ ionic emulate ios" Image Credit: Getting Started with Ionic
  36. @BradleyHolt! HTML5 Offline Application Cache

  37. @BradleyHolt! 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
  38. @BradleyHolt! Cache Manifest File <html manifest="example.appcache">
 …
 </html>
 CACHE MANIFEST


    # v1 - 2015-01-08
 index.html
 logo.png
 app.css
 app.js
  39. @BradleyHolt! PouchDB Code Examples

  40. @BradleyHolt! Installing PouchDB <script src=
 "https://cdn.jsdelivr.net/pouchdb/3.5.0/pouchdb.min.js"
 ></script>
 CACHE MANIFEST
 #

    v2 - 2015-01-08
 index.html
 logo.png
 app.css
 app.js
 https://cdn.jsdelivr.net/pouchdb/3.5.0/pouchdb.min.js
  41. @BradleyHolt! PouchDB Code Examples •  Creating a local PouchDB database

    •  Creating a remote PouchDB database •  Creating a new document •  Updating a document •  Deleting a document •  Querying a database •  Replicating PouchDB •  Listening for database changes
  42. @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
  43. @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
  44. @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
  45. @BradleyHolt! Creating a New Document var db = new PouchDB("smart-meter");"

    db.post({" date: "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/03-create-document-post.js
  46. @BradleyHolt! Creating a New Document, Specifying its ID 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
  47. @BradleyHolt! Updating a Document db.put({" _id: "2014-11-12T23:27:03.794Z"," kilowatt_hours: 14" }).then(function()

    {" return db.get("2014-11-12T23:27:03.794Z");" }).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
  48. @BradleyHolt! Deleting a Document db.put({" _id: "2014-11-12T23:27:03.794Z"," kilowatt_hours: 14" }).then(function()

    {" // Get the document" return db.get("2014-11-12T23:27:03.794Z");" }).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
  49. @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
  50. @BradleyHolt! allDocs Options •  include_docs" •  conflicts" •  attachments" • 

    startkey" •  endkey" •  inclusive_end (true by default) •  limit" •  skip" •  descending" •  key" •  keys"
  51. @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"
  52. @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
  53. @BradleyHolt! Replicating a PouchDB Database 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
  54. @BradleyHolt! Replicating a PouchDB Database 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
  55. @BradleyHolt! Replicating a PouchDB Database 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
  56. @BradleyHolt! Bidirectionally Replicating a PouchDB Database Promise.all([" db.bulkDocs([" {_id: "2014-11-12T23:27:03.794Z",

    kilowatt_hours: 14}," {_id: "2014-11-13T00:52:01.471Z", kilowatt_hours: 15}" ])," remoteDb.bulkDocs([" {_id: "2014-11-11T22:35:01.433Z", kilowatt_hours: 11}," {_id: "2014-11-12T00:43:01.633Z", kilowatt_hours: 13}" ])" ]).then(function() {" …" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/09-replicate-database-bidirectional.js
  57. @BradleyHolt! Bidirectionally Replicating a PouchDB Database 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
  58. @BradleyHolt! Live Replication of a PouchDB Database Promise.all([" db.bulkDocs([" {_id:

    "2014-11-12T23:27:03.794Z", kilowatt_hours: 14}," {_id: "2014-11-13T00:52:01.471Z", kilowatt_hours: 15}" ])," remoteDb.bulkDocs([" {_id: "2014-11-11T22:35:01.433Z", kilowatt_hours: 11}," {_id: "2014-11-12T00:43:01.633Z", kilowatt_hours: 13}" ])" ]).then(function() {" …" });" https://github.com/bradley-holt/offline-first/blob/master/pouchdb/10-replicate-database-live.js
  59. @BradleyHolt! Live Replication of a PouchDB Database 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
  60. @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
  61. @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
  62. @BradleyHolt! 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/
  63. @BradleyHolt! A Deep Dive into Offline-First with PouchDB and IBM

    Cloudant Date: Thursday, August 27, 2015 Time: 1:00 PM - 2:00 PM EDT Register at: https://cloudant.com/resources/webinars/
  64. @BradleyHolt! Image Credits •  Joan Touzet (@wohali), ASF Member, CouchDB

    PMC Member <https://twitter.com/wohali/status/595689720933445632> •  Device landscape by Jeremy Keith, on Flickr <https://www.flickr.com/photos/adactio/6153481666> •  Cloud Formation Over the Adirondacks by Bradley Holt <https://twitter.com/BradleyHolt/status/623030107679002624> •  Cell phone tower by Gary Lerude, on Flickr <https://www.flickr.com/photos/garylerude/7511464618/> •  Internet Splat Map by Steve Jurvetson, on Flickr <https://www.flickr.com/photos/jurvetson/916142/> •  Tangled Network by Bruno Girin, on Flickr <https://www.flickr.com/photos/brunogirin/73014722/> •  Wired by Alexandre Duret-Lutz, on Flickr <https://www.flickr.com/photos/gadl/1308489717/> •  connect me to BR549 by frankieleon, on Flickr <https://www.flickr.com/photos/armydre2008/5914251874/> •  Pneumatic Central by Sleestak, on Flickr <https://www.flickr.com/photos/dlanod/235990854> •  Connected version 2 by Hans Kylberg, on Flickr <https://www.flickr.com/photos/visulogik/2340179011/> •  Speed DLR on Doklands by Umberto Rotundo, on Flickr <https://www.flickr.com/photos/turyddu/4394742730/> •  Lynn Camp Prong (Explored) by AllieKF, on Flickr <https://www.flickr.com/photos/allie_k/14501117120> •  Panorama of the Molasses Disaster site by Boston Public Library, on Flickr <https://www.flickr.com/photos/boston_public_library/4901555337/> •  Ethernet IoT Starter Kit <https://developer.mbed.org/platforms/IBMEthernetKit/> •  build.phonegap by Andrés Álvarez Iglesias, on Flickr <https://www.flickr.com/photos/doctorserone/5682929553> •  Getting Started with Ionic <http://ionicframework.com/getting-started/> •  Grunge Warning Sign - Do Not Read This Sign by Nicolas Raymond, on Flickr <https://www.flickr.com/photos/80497449@N04/7417352980> •  Mango with section on a white background by bangdoll, on Flickr <https://www.flickr.com/photos/bangdoll/5665235102>
  65. @BradleyHolt! Bradley Holt Developer Advocate bradley.holt@us.ibm.com @BradleyHolt github.com/bradley-holt