In this series of blog posts, we’re looking at how to set up a simple web app in node.
In the previous installment we looked at serving angle brackets, both static files and server-side templates.
In this post we’ll look at persisting data to a database. The node way.
A Basic Todo List
A simple todo list is a great way to explore persisting data. Let’s create a new view to allow users to add/delete a list of todo items.
We’ll call this view todos.html
:
(please note I’ve had to put a space between my curly braces which shouldn’t be there)
Let’s have a quick run through of what’s in this view:
- It writes out a list of todos.
- Each todo has a ‘delete’ link.
- It displays a form, allowing you to add new todo items.
Parsing form posts
This page will post forms to us. Express doesn’t handle HTTP bodies any more (it used to!), you need to install some middleware to parse the HTTP body and convert it into an object (req.body
). Let’s use the body-parser
module. Install it like this:
In your server.js
file you can now include the module, and plug it in:
You can add the app.use
line directly after the app.use
for serving static files, which we added last time.
Databases
Node support lots of databases, everything from SQL Server to Mongo DB, but the node way of doing databases is a bit different. Instead of connecting to an external database system, we’ll run the database inside the node server!
LevelDB is a key-value store developed by Google, it’s a C++ library which you can include within your application to provide basic database features. The node community has fantastic support for level, with a rich ecosystem of modules around level.
There are command line and graphical tools to allow you to view you data. There are libraries which build upon level’s interface, to provide more complex data structures. But interestingly, there are modules which replace the guts of the level module with alternative forms of persistence, such as Redis, or my own, which connects to Azure’s Table Storage.
The advantage with going with level is that it presents a ‘lowest common denominator’ interface. This allows you to change your mind later about exactly where you data is stored, without you having to refactor your code.
Let’s install it. This command will download the level, and build the C++ code:
If you have any trouble installing the module, make sure you have the prerequisites installed. This generally work well for me on Ubuntu, on Windows it can be more of a challenge :¬(
Level will use the local filesystem to save the data. We’ll call the database ‘todos’, and use it in our server.js
like this:
Note: You can create multiple databases within the same application, but it’s generally better to have less databases, and create different ranges of keys to store the data.
Guid keys
There’s one more thing we’ll need. In order to create the keys in the database we’ll need to create unique strings. A simple way of doing this is just to create guids. Of course, there’s a module (well there’s several) for that:
Which we can use like this:
Working with the database
Let’s listen to HTTP posts, and insert records into the database. Call the method put
on the database, passing in your key and value as well as a callback to fire when the record is saved. Once saved, we’ll redirect back to the home page:
To delete todos, we’ll listen for gets on this path /delete/{key}
and delete the key from the database accordingly. We’ll also redirect back to the homepage once complete:
On the main page we need to read all the data out of the database, and send it to the new todos.html
view. Level will allow us to stream ranges of keys from the database. In this case, we’ll stream everything out (listening to the on
event), add it to an array, and once finished render the view (listening out for the end
event):
Simple.
Let’s pull it all together, and see what our server.js
file looks like:
There are a few lines of code there, but this is a web server and a database, all in one JavaScript file :¬)
Next we’ll shift our focus over to the browser, and convert our todo list into a single page application.
UPDATE
If you’re experiencing problems with LevelDB (Paul Grenyer reported that his database wasn’t persisting on Heroku) I suggest using Redis to persist the data.
Install a couple of modules:
Then create the db
object like this instead:
Now you’re running on Redis instead :¬)