Building a Simple Blog

Exclusive offer: get 50% off this eBook here
Backbone.js Blueprints

Backbone.js Blueprints — Save 50%

Understand Backbone.js pragmatically by building seven different applications from scratch with this bpook and ebook

$29.99    $15.00
by Andrew Burgess | May 2014 | Open Source

In this article, by Andrew Burgess, the author of the book Backbone.js Blueprints, we're going to begin by assuming that your experience in Backbone is very minimal; in fact, even if you've never used Backbone before, you should still be able to follow along just fine. The application we're going to build in this article is a very simple blog. As blogs go, it's going to have very few features; there will be posts that viewers can read and make comments on. However, it will introduce you to every major feature in the Backbone library, get you comfortable with the vocabulary, and how these features work together in general.

In this article, we'll know how to:

  • Use Backbone's model, collection, and view components
  • Program the server side with Node.js (and Express.js) to create a backend for our Backbone app

So let's get started!

(For more resources related to this topic, see here.)

Setting up the application

Every application has to be set up, so we'll begin with that. Create a folder for your project—I'll call mine simpleBlog—and inside that, create a file named package.json. If you've used Node.js before, you know that the package.json file describes the project; lists the project home page, repository, and other links; and (most importantly for us) outlines the dependencies for the application.

Here's what the package.json file looks like:

{ "name": "simple-blog", "description": "This is a simple blog.", "version": "0.1.0", "scripts": { "start": "nodemon server.js" }, "dependencies": { "express": "3.x.x", "ejs" : "~0.8.4", "bourne" : "0.3" }, "devDependencies": { "nodemon": "latest" } }

This is a pretty bare-bones package.json file, but it has all the important bits. The name, description, and version properties should be self-explanatory. The dependencies object lists all the npm packages that this project needs to run: the key is the name of the package and the value is the version. Since we're building an ExpressJS backend, we'll need the express package. The ejs package is for our server-side templates and bourne is our database (more on this one later).

The devDependencies property is similar to the dependencies property, except that these packages are only required for someone working on the project. They aren't required to just use the project. For example, a build tool and its components, such as Grunt, would be development dependencies. We want to use a package called nodemon. This package is really handy when building a Node.js backend: we can have a command line that runs the nodemon server.js command in the background while we edit server.js in our editor. The nodemon package will restart the server whenever we save changes to the file. The only problem with this is that we can't actually run the nodemon server.js command on the command line, because we're going to install nodemon as a local package and not a global process. This is where the scripts property in our package.json file comes in: we can write simple script, almost like a command-line alias, to start nodemon for us. As you can see, we're creating a script called start, and it runs nodemon server.js. On the command line, we can run npm start; npm knows where to find the nodemon binary and can start it for us.

So, now that we have a package.json file, we can install the dependencies we've just listed. On the command line, change to the current directory to the project directory, and run the following command:

npm install

You'll see that all the necessary packages will be installed. Now we're ready to begin writing the code.

Starting with the server

I know you're probably eager to get started with the actual Backbone code, but it makes more sense for us to start with the server code. Remember, good Backbone apps will have strong server-side components, so we can't ignore the backend completely.

We'll begin by creating a server.js file in our project directory. Here's how that begins:

var express = require('express'); var path = require('path'); var Bourne = require("bourne");

If you've used Node.js, you know that the require function can be used to load Node.js components (path) or npm packages (express and bourne). Now that we have these packages in our application, we can begin using them as follows:

var app = express(); var posts = new Bourne("simpleBlogPosts.json"); var comments = new Bourne("simpleBlogComments.json");

The first variable here is app. This is our basic Express application object, which we get when we call the express function. We'll be using it a lot in this file.

Next, we'll create two Bourne objects. As I said earlier, Bourne is the database we'll use in our projects in this article. This is a simple database that I wrote specifically for this article. To keep the server side as simple as possible, I wanted to use a document-oriented database system, but I wanted something serverless (for example, SQLite), so you didn't have to run both an application server and a database server. What I came up with, Bourne, is a small package that reads from and writes to a JSON file; the path to that JSON file is the parameter we pass to the constructor function. It's definitely not good for anything bigger than a small learning project, but it should be perfect for this article. In the real world, you can use one of the excellent document-oriented databases. I recommend MongoDB: it's really easy to get started with, and has a very natural API. Bourne isn't a drop-in replacement for MongoDB, but it's very similar. You can check out the simple documentation for Bourne at https://github.com/andrew8088/bourne.

So, as you can see here, we need two databases: one for our blog posts and one for comments (unlike most databases, Bourne has only one table or collection per database, hence the need for two).

The next step is to write a little configuration for our application:

app.configure(function(){ app.use(express.json()); app.use(express.static(path.join(__dirname, 'public'))); });

This is a very minimal configuration for an Express app, but it's enough for our usage here. We're adding two layers of middleware to our application; they are "mini-programs" that the HTTP requests that come to our application will run through before getting to our custom functions (which we have yet to write). We add two layers here: the first is express.json(), which parses the JSON requests bodies that Backbone will send to the server; the second is express.static(), which will statically serve files from the path given as a parameter. This allows us to serve the client-side JavaScript files, CSS files, and images from the public folder.

You'll notice that both these middleware pieces are passed to app.use(), which is the method we call to choose to use these pieces.

You'll notice that we're using the path.join() method to create the path to our public assets folder, instead of just doing __dirname and 'public'. This is because Microsoft Windows requires the separating slashes to be backslashes. The path.join() method will get it right for whatever operating system the code is running on. Oh, and __dirname (two underscores at the beginning) is just a variable for the path to the directory this script is in.

The next step is to create a route method:

app.get('/*', function (req, res) { res.render("index.ejs"); });

In Express, we can create a route calling a method on the app that corresponds to the desired HTTP verb (get, post, put, and delete). Here, we're calling app.get() and we pass two parameters to it. The first is the route; it's the portion of the URL that will come after your domain name. In our case, we're using an asterisk, which is a catchall; it will match any route that begins with a forward slash (which will be all routes). This will match every GET request made to our application. If an HTTP request matches the route, then a function, which is the second parameter, will be called.

This function takes two parameters; the first is the request object from the client and the second is the response object that we'll use to send our response back. These are often abbreviated to req and res, but that's just a convention, you could call them whatever you want.

So, we're going to use the res.render method, which will render a server-side template. Right now, we're passing a single parameter: the path to the template file. Actually, it's only part of the path, because Express assumes by default that templates are kept in a directory named views, a convention we'll be using. Express can guess the template package to use based on the file extension; that's why we don't have to select EJS as the template engine anywhere. If we had values that we want to interpolate into our template, we would pass a JavaScript object as the second parameter. We'll come back and do this a little later.

Finally, we can start up our application; I'll choose to use the port 3000:

app.listen(3000);

We'll be adding a lot more to our server.js file later, but this is what we'll start with. Actually, at this point, you can run npm start on the command line and open up http://localhost:3000 in a browser. You'll get an error because we haven't made the view template file yet, but you can see that our server is working.

Backbone.js Blueprints Understand Backbone.js pragmatically by building seven different applications from scratch with this bpook and ebook
Published: May 2014
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Creating the template

All web applications will have templates of some kind. Most Backbone applications will be heavy on the frontend templates. However, we will need a single server-side template, so let's build that.

While you can choose from different template engines, many folks (and subsequently, tutorials) use Jade (http://jade-lang.com/), which is like a Node.js version of the Ruby template engine Haml (http://haml.info/). However, as you already know, we're using EJS (https://github.com/visionmedia/ejs), which is similar to Ruby's ERB. Basically, we're writing regular HTML with template variables inside <%= %>tags.

As we saw earlier, Express will be looking for an index.ejs file in the views folder, so let's create that and put the following code inside it:

<!DOCTYPE html> <html> <head> <title> Simple Blog </title> </head> <body> <div id="main"></div> <script src ="/jquery.js"></script> <script src ="/underscore.js"></script> <script src ="/backbone.js"></script> <script src ="/app.js"></script> </body> </html>

At this point, if you still have the server running (remember npm start on the command line), you should be able to load http://localhost:3000 without getting an error. The page will be blank, but you should be able to view the source and see the HTML code that we just wrote. That's a good sign; it means we're successfully sending stuff from the server to the client.

Adding the public folder

Since Backbone is a frontend library, it's something we'll need to be serving to the client. We've set up our Express app to statically serve the files in our public directory, and added several script tags to the index.ejs file, but we haven't created these things yet.

So, create a directory named public in your project directory. Now download the latest versions of Underscore (http://underscorejs.org), Backbone (http://backbonejs.org), and jQuery (http://jquery.com) and put them in this folder. It's very likely that newer versions of these libraries have come out since this article was written. Since updates to these projects could change the way they work, it's best to stick to the following versions:

  • Backbone: Version 1.1.2
  • Underscore: Version 1.6.0
  • jQuery: Version 2.0.3

I will mention here that we're including Underscore and jQuery because Backbone depends on them. Actually, it only really depends on Underscore, but including jQuery does give us a few extra features that we'll be happy to have. If you need to support older versions of Internet Explorer, you'll also want to include the json2.js library (https://github.com/douglascrockford/JSON-js), and switch to a version of jQuery 1 (jQuery 2 doesn't support older versions of IE).

Beginning the Backbone code

Once you have these three files in the public folder, you're ready to create the app.js file. In most of our Backbone applications, this is where the major portion of the work is going to be done. Now that everything else is in place, we can begin the app-specific code.

Creating a model and collection

When building a Backbone app, the first thing I like to think about is this: what data will I be working with? This is my first question because Backbone is very much a data-driven library: almost everything the user will see and work will in some way be related to a piece of data. This is especially true in the simple blog we're creating; every view will either be for viewing data (such as posts) or creating data (such as comments). The individual pieces of data that your application will work on (such as titles, dates, and text) will be grouped into what are usually called models: the posts and comments in our blog, the events in a calendar app, or the contacts in an address book. You get the idea.

To start with, our blog will have a single model: the post. So, we create the appropriate Backbone model and collection classes. The code snippet for our model is as follows:

var Post = Backbone.Model.extend({}); var Posts = Backbone.Collection.extend({ model: Post, url: "/posts" });

There's actually a lot going on in these five lines. First, all the main Backbone components are properties of the global variable Backbone. Each of these components is a class. JavaScript does not actually have proper classes; the prototype-backed functions pass for classes in JavaScript. They also have an extend method, which allows us to create subclasses. We pass an object to this extend method, and all properties or methods inside that object will become part of the new class we're creating, along with the properties and methods that make up the class we're extending.

In this code, we're creating a model class and a collection class. We actually don't need to extend the model class at all for now; just a basic Backbone model will do. However, for the collection class, we'll add two properties. First, we need to associate this collection with the appropriate model. We do this because a collection instance is basically just a glorified array for a bunch of model instances. The second property is url: this is the location of the collection on the server. What this means is that if we do a GET request to /posts, we'll get back a JSON array of the posts in our database. This also means that we will be able to send a POST request to /posts and store a new post in our database.

At this point, now that we have our data-handling classes on the frontend, I'd like to head back to the server.js file to create the routes required by our collection. So, in the file, add the following piece of code:

app.get("/posts", function (req, res) { posts.find(function (results) { res.json(results); }); });

First off, I'll mention that it's important that this call to app.get goes above our /*route. This is because of the fact that Express sends the requests through our routes sequentially and stops (by default, anyway) when it finds a matching one. Since /posts will match both /posts and /*, we need to make sure it hits the /posts route first.

Next, you'll recall our posts database instance, which we made earlier. Here, we're calling its find method with only a callback, which will pass the callback an array of all the records in the database. Then, we can use the response object's json method to send that array back as JSON (the Content-Type header will be application/json). That's it!

While we're here in the server.js file, we add the POST method for the same route: this is where the post data will come in from the browser and be saved to our database. The following is the code snippet for the post()method:

app.post("/posts", function (req, res) { posts.insert(req.body, function (result) { res.json(result); }); });

The req object has a body property, which is the JSON data that represents our post data. We can insert it directly into the posts database. When Backbone saves a model to the server in this way, it expects the response to be the model it sent with an ID added to it. Our database will add the ID for us and pass the updated model to the callback, so we only have to send it as a response to the browser, just as we did when sending all the posts in the previous method using res.json.

Of course, this isn't very useful without a form to add posts to the database, right? We'll build a form to create new posts soon, but for now we can manually add a post to the simpleBlogPosts.json file; this file may not exist yet because we haven't written any data, so you'll have to create it. Just make sure the file you create has the right name, that is, the same name as the parameter we passed to the Bourne constructor in our server.js file. I'm going to put the following code in that file:

[ { "id": 1, "pubDate": "2013-10-20T19:42:46.755Z", "title": "Lorem Ipsum", "content": "<p>Dolor sit amet . . .</p>" } ]

Of course, you can make the content field longer; you get the idea. This is the JSON field that will be sent to our Posts collection instance and become a set of the Post model instance (in this case, a set of only one).

Performing a quick and dirty test

We've actually written enough code at this point to test things out. Head to http://localhost:3000 in your browser and pop open a JavaScript console; I prefer Chrome and the Developer tools but use whatever you want. Now try the following lines:

var posts = new Posts(); posts.length // => 0

We can create a Posts collection instance; as you can see, it's empty by default. We can load the data from the server by running the following line:

posts.fetch();

A collection instance's fetch method will send a GET request to the server (in fact, if your in-browser tools allow you to see a network request, you'll see a GET request to /posts). It will merge the models that it receives from the server with the ones already in the collection. Give a second to get a response and then run the following lines:

posts.length // => 1 var post = posts.get(1); post.get("title"); // Lorem Ipsum

Every collection instance has a get method; we pass it an ID and it will return the model instance with that ID (note that this is the id field from the database, and not the index number in the collection). Then, each model instance has a get method that we can use to get properties.

Backbone.js Blueprints Understand Backbone.js pragmatically by building seven different applications from scratch with this bpook and ebook
Published: May 2014
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Writing some views

In simple applications, most of the Backbone code that we write will be in views. I think it's fair to say that views can be the most challenging part of a Backbone app, because there are so many ways that almost everything can be done.

It's important to understand that a Backbone.View instance and a screen full of web apps aren't the same thing. One view in the browser may actually be many Backbone views. The first view that we want to create is a list of all the posts; these will be links to individual post pages. We could do this in two ways: as one big view or as multiple smaller views put together. In this instance, we're going to be using multiple views. Here's how we'll break it down: each list item will be generated by its own view instance. Then, the wrapper around the list items will be another view. You can picture it as looking something like this:

The PostListView class

Let's start with the child views. We'll call this PostListView class. Naming views can be a little tricky. Often, we'll have a view for the collection and a view for the model, and we'll just append View to the end of their names, for example, PostView and PostsView. However, a model or collection will have multiple views. The one we're about to write is to list our models. That's why we're calling it PostListView:

var PostListView = Backbone.View.extend({ tagName: "li", template: _.template("{{title}}"), render: function () { this.el.innerHTML = this.template(this.model.toJSON()); return this; } });

Just like Backbone.Model and Backbone.Collection, we create a view class by extending Backbone.View. We have three properties in the extending object that make up our PostListView. The first one to look at is the template property; this property holds the template that our view will render. There are plenty of ways to create a template; in this case, we're using the Underscore's template function; we pass a string to _.template, and it returns a function which we can use to generate the correct HTML. Take a look at this template string: it's regular HTML with variables placed within double curly braces.

Next, let's look at the render method. By convention, this is the method that we call to actually render the view. Every view instance has a property named el. This is the base element for the view instance: all other elements for this view go inside it. By default, this is a div element, but we've set the tagName property to li, which means we'll get a list item instead. By the way, there's also a $el property, which is a jQuery object wrapping the el property; this only works if we have jQuery included in our application.

So, inside our render function, we need to fill in this element. In this case, we'll do that by assigning the innerHTML property. To get the HTML output, we use the template we just wrote. That's a function, so we call it, and pass this.model.toJSON(). The this.model portion comes from when we instantiate this view: we'll pass it a model. Every model has a toJSON method, which returns a raw object with just the attributes of the model. Since our model will have the id and title attributes, passing this to our template function will return a string with those values interpolated into the template string we wrote.

We end our render function by returning the view instance. Again, this is just convention. Because of this, we can use the convention where we get the element for this view via view.render().el; this will render the view and then get the el property. Of course, there's no reason you couldn't return this.el directly from render.

There's one more thing to address here, but it's about Underscore and not Backbone. If you've used the Underscore's template function before, you know that curly braces aren't its normal delimiters. I've switched from the default <%= %>delimiters, because those are the delimiters for our server-side template engine. To change Underscore's delimiters, just add the following code snippet to the top of our app.js file:

_.templateSettings = { interpolate: /\{\{(.+?)\}\}/g };

Of course, you realize that we could make the delimiters whatever we want, as long as a regular expression can match it. I like the curly braces.

The PostsListView class

Now that we have the view for our list items, we need the parent view that wraps those list items:

var PostsListView = Backbone.View.extend({ template: _.template("<h1>My Blog</h1><ul></ul>"), render: function () { this.el.innerHTML = this.template(); var ul = this.$el.find("ul"); this.collection.forEach(function (post) { ul.append(new PostListView({ model: post }).render().el); }); return this; } });

As views go, this is pretty simple, but we can learn a few new things from it. First, you'll notice that our template doesn't actually use any variables, so there's no reason for us to actually use a template. We could directly assign that HTML string as this.el.innerHTML; however, I like to do the little template dance anyway because I might change the template string to include some variables in the future.

Notice the second line of the render function: we're finding an ul element; the same ul element that we just made as a child element of our root element, this.el. However, instead of using this.el, we're using this.$el.

Next, we're looping over each item in the collection that we'll associate with this view (when we instantiate it). For each post in the collection, we will create a new PostListView class. We pass it an options object, which assigns the view's model as the current post. Then, we render the view and return the view's element. This is then appended to our ul object.

We'll end by returning the view object.

Using our views

We're almost ready to actually display some content in the browser. Our first stop is back in the server.js file. We need to send the array of posts from the database to our index.ejs template. We do this by using the following code snippet:

app.get('/*', function (req, res) { posts.find(function (err, results) { res.render("index.ejs", { posts: JSON.stringify(results) }); }); });

Just as we do in the /posts route, we call posts.find. Once we get the results back, we render the view as before. But this time, we pass an object of values that we want to be able to use inside the template. In this case, that's only the posts. We have to run the results through JSON.stringify, because we can't serve an actual JavaScript object to the browser; we need a string representation (the JSON form) of the object.

Now, in the index.ejs file of the views folder, we can use these posts. Create a new script tag under the other ones we created before. This time, it will be an inline script:

<script> var posts = new Posts(<%- posts %>); $("#main").append(new PostsListView({ collection: posts }).render().el); </script>

The first line creates our posts collection; notice our use of the template tags. This is how to interpolate our posts array into the template. There's no typo there by the way; you might have expected an opening tag of <%=, but that opening tag will escape any possible characters in the string, which wrecks the quotes in our JSON code. So, we use <%-, which doesn't escape characters.

The next line should be pretty straightforward. We're using jQuery to find our main element and appending the element of a new PostsListView instance. In the options object, we'll set the collection for this view. We then render it and find the element to append.

Now, make sure your server is running, and go to http://localhost:3000 in the browser. You should see the following screenshot:

You're using the three main Backbone components—collection, models, and views—to create a mini-application! That's great, but we've only just got started.

Summary

In this article, we looked briefly at all the main components of Backbone. We saw how models and collections are the homes for our data records, and how they drive the web application. We made a handful of views, some to display individual model instances, some to display a collection, and some to display other page components or wrap other views. We even got a little taste of Backbone's robust events API.

Resources for Article:


Further resources on this subject:


About the Author :


Andrew Burgess

Andrew Burgess writes code and writes about code. While he dabbles with around half a dozen different programming languages, JavaScript is his favorite and is also his first love. He's been writing tutorials for Nettuts+ since 2009, and he has been creating screencasts for Tuts+ since 2012. He's written a few small e-books on other web development topics; some of them are:

  • Getting Good with Git, Rockable Press
  • Getting Good with JavaScript, Rockable Press
  • Getting Good with PHP, Rockable Press

Books From Packt


Backbone.js Patterns and Best Practices
Backbone.js Patterns and Best Practices

Backbone.js Testing
Backbone.js Testing

Instant Backbone.js Application Development [Instant]
Instant Backbone.js Application Development [Instant]

Backbone.js Cookbook
Backbone.js Cookbook

iPad Enterprise Application Development BluePrints
iPad Enterprise Application Development BluePrints

Service Oriented Architecture: An Integration Blueprint
Service Oriented Architecture: An Integration Blueprint

iPhone Game Blueprints
iPhone Game Blueprints

WordPress 3 Site Blueprints
WordPress 3 Site Blueprints

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software