An Introduction To PouchDB
PouchDB is a great way to replicate data from a remote source in the browser. Once you’ve replicated the data, you can then query and process it. In this series of articles, we give a gentle introduction to PouchDB, including code to get you up and running.
NoSQL
Before around 2009, if you were building a website and you used a database then you used a relational database. This is a standard “columns and rows” affair where you write a schema for the column attributes and then add the row tuples yourself as your data.
That was great for a while, but there are times when working with a relational database can be painful, especially when you’re working with large distributed systems. Apache CouchDB was the first document database designed for the web, and following on from its success, an entire field of non-relational databases blossomed. This field later became known as NoSQL—SQL being the query language used with relational databases. (I’ll leave the merits of this particular choice of name for another post…)
Instead of columns of data with very specific granular datatypes, in a document database there is only an associative mapping of keys to documents. The format of the documents varies from framework to framework, but they are often either JSON or XML. CouchDB is one of the leading open source document store databases. PouchDB is, as the name suggests, an in-browser counterpart to CouchDB.
CouchDB
CouchDB is designed to provide availability in exchange for consistency, according to the CAP theorem. Or, as Coda Hale argues, when experiencing a network partition, CouchDB maintains yield (i.e. keeps answering requests) while reducing harvest (i.e. those answers are based on incomplete data). This model is a perfect fit for a loose network of heterogeneous nodes. For example, syncing between your phone (which regularly goes offline) and a remote database.
Because consistency is sacrificed, updates are propagated in such a way that you cannot perfectly rely on all databases being identical at all times. Adherents of the CAP theorem call this eventual consistency, because all databases eventually become consistent with one another.
What this means for PouchDB is that though your PouchDB instance in the browser will be kept eventually consistent with one or more remote CouchDB instances, either unidirectionally or bidirectionally, you will not be able to rely on all databases being identical at all times. This turns out to be fine for most kinds of applications we’ll want to handle.
Advantages
PouchDB is a database that lives inside your browser. The primary advantage of this is that you don’t have to perform queries over the network. This makes queries faster, since they’re not susceptible to the vagaries of network weather, and more reliable, since even if the user is offline they can use whatever information has been locally cached. In some cases, what has been locally cached may even be primary data. In this case PouchDB can store it for you, and will wait until the network connection comes back before syncing it to a remote server if asked to do so.
Another advantage with having a database inside your browser is that it comes with all the features you’d expect from a database. If you use a simple existing in-browser storage facility such as localStorage, then you don’t, for example, have the opportunity to efficiently sort query results. PouchDB can do that, because it’s a fully featured database.
Let’s get PouchDB set up, and then we can jump in to some code!
Database Setup
We’re going to be concentrating on PouchDB in the browser, but keep in mind that you can also use it with Node.js. Go to the PouchDB website and click the Download button. This will give you the most recent, production minimised JavaScript source. Save it somewhere, and now you can refer to it from your HTML:
<script src="pouchdb-3.0.2.min.js"></script>
That was easy, wasn’t it? This JavaScript file is very small, especially once aggressively minimized, so it will add minimal latency to your pages.
You’re also going to need a remote CouchDB server to synchronise with, so download CouchDB and install it. If you’re using OS X, then using Homebrew to brew install couchdb
is another great alternative installation method. To start the CouchDB server, just type couchdb start
on the command line, or follow the documentation. This starts the server on http://127.0.0.1:5984/. The OS X app and the Homebrew install both do this for you automatically.
CORS
To make CouchDB compatible with browser requests, you’ll have to make sure that CORS is enabled. CORS stands for Cross-Origin Resource Sharing, and is probably the single most frustrating—though necessary—security feature that web developers regularly have to deal with. Thankfully, setting up CouchDB to allow CORS is simple. Just set the following CouchDB configuration options:
put httpd/enable_cors '"true"'
put cors/origins '"*"'
put cors/credentials '"true"'
put cors/methods '"GET, PUT, POST, HEAD, DELETE"'
put cors/headers '"accept, authorization, content-type, origin"'
Here’s the fun part. If you use the following shell script function, the lines above actually become working shell script code!
function put() {
curl -X PUT "http://127.0.0.1:5984/_config/$1" -d "$2"
}
But you can also set the options manually by pointing your browser to the CouchDB configuration options page:
http://127.0.0.1:5984/_utils/config.html
One alternative to dealing with all this is to run:
npm install -g pouchdb-server && pouchdb-server
This is a PouchDB server running under Node.js. You can sync with it like you’d sync with CouchDB. It’s not as fully-featured as CouchDB, but CORS is on by default, so you might prefer to test against it.
Test Application
Okay, let’s get coding. We’re going to use CoffeeScript for this example. CoffeeScript allows you to develop JavaScript much more efficiently, and is easier to understand and document. You’ll want to compile it down to minified JavaScript source, however, before rolling it in a production app. We’ll also assume that you’re using jQuery. If you’re not familiar with either of these tools, do check them out! They’re indispensable on the modern web.
So you have jQuery and PouchDB set up and included in your page. CouchDB is up and running and you’ve enabled CORS. You’ve started the CouchDB server. Now let’s write a simple test application:
unixtime = () ->
new Date().getTime() / 1000
display = (text) ->
$("body").append "<p>#{ text }</p>"
$ ->
started = unixtime()
display "Creating a PouchDB database, and synchronising."
name = "test"
db = PouchDB name
db.replicate.from("http://127.0.0.1:5984/#{ name }", {live: true})
.on("uptodate", ->
display "Synchronised successfully!"
display "That took #{ unixtime() - started } seconds."
)
Save this as example.coffee and then compile the file:
$ coffee -c example.coffee
This creates an example.js
file for you. Include that file in your page:
<script src="example.js"></script>
Remember to put this after you include jQuery.
Then load the page up in your browser! It should display something like this:
If so, great! This means that all of the parts of the system are working together, and you can now start developing apps.
If it doesn’t work, then don’t panic. There are several things that you can check. Look at the JavaScript error console to see if any problems were reported. If you got an error such as net::ERR_CONNECTION_REFUSED
(Chrome) or Cross-Origin Request Blocked
(Firefox) then CouchDB might not be running. (Note that even though Firefox complains about a “Cross-Origin Request”, this covers network related issues as well as potential CORS issues.) Make sure you started CouchDB and that it’s still running. To check, you can just visit this page in the browser:
http://127.0.0.1:5984/
Once you see something that looks like this:
{"couchdb":"Welcome","uuid":"2a7edab40ea41ddf9b1e5c8c2c5f35fa","version":"1.5.0","vendor":{"version":"1.5.0-1","name":"Homebrew"}}
Then everything is okay. If you’re still having problems even with CouchDB running, try checking the CORS configuration settings given in the section about CORS above.
Conclusion
We learned about the history of NoSQL databases, the importance of document store databases in particular, and how to install PouchDB to actually use such a database in the browser. In the next article in this series, we’ll delve deeper into rolling a simple application.
P.S. Do you already have experience with PouchDB or CouchDB? Did you find this easy to follow? Perhaps you ran into some problems with the examples provided? If so, please let us know in the comments below!
Share your thoughts with @engineyard on Twitter