How to Build a Koa Web Application – Part 1

0
2082
7 min read

You may be a seasoned or novice web developer, but no matter your level of experience, you must always be able to set up a basic MVC application.

This two part series will briefly show you how to use Koa, a bleeding edge Node.js web application framework to create a web application using MongoDB as its database. Koa has a low footprint and tries to be as unbiased as possible.

For this series, we will also use Jade and Mongel, two Node.js libraries that provide HTML template rendering and MongoDB model interfacing, respectively. Note that this series requires you to use Node.js version 0.11+.

At the end of the series, we will have a small and basic app where you can create pages with a title and content, list your pages, and view them.


Let’s get going!

Using NPM and Node.js

If you do not already have Node.js installed, you can download installation packages at the official Node.js website, http://nodejs.org. I strongly suggest that you install Node.js in order to code along with the article.

Once installed, Node.js will add two new programs to your computer that you can access from your terminal; they’re node and npm. The first program is the main Node.js program and is used to run Node.js applications, and the second program is the Node Package Manager and it’s used to install Node.js packages.

For this application we start out in an empty folder by using npm to install four libraries:

$ npm install koa jade mongel co-body

Once this is done, open your favorite text editor and create an index.js file in the folder in which we will now start our creating our application. We start by using the require function to load the four libraries we just installed:

var koa = require('koa');
var jade = require('jade');
var mongel = require('mongel');
var parse = require(‘co-body');

This simply loads the functionality of the libraries into the respective variables. This lets us create our Page model and our Koa app variables:

var Page = mongel('pages', ‘mongodb://localhost/app');
var app = koa();

As you can see, we now use the variables mongel and koa that we previously loaded into our program using require.

To create a model with mongel, all we have to do is give the name of our MongoDB collection and a MongoDB connection URI that represents the network location of the database; in this case we’re using a local installation of MongoDB and a database called app.

It’s simple to create a basic Koa application, and as seen in the code above, all we do is create a new variable called app that is the result of calling the Koa library function.

Middleware, generators, and JavaScript

Koa uses a new feature in JavaScript called generators. Generators are not widely available in browsers yet except for some versions of Google Chrome, but since Node.js is built on the same JavaScript as Google Chrome it can use generators.

The generators function is much like a regular JavaScript function, but it has a special ability to yield several values along with the normal ability of returning a single value. Some expert JavaScript programmers used this to create a new and improved way of writing asynchronous code in JavaScript, which is required when building a networked application such as a web application.

The generators function is a complex subject and we won’t cover it in detail. We’ll just show you how to use it in our small and basic app.

In Koa, generators are used as something called middleware, a concept that may be familiar to you from other languages such as Ruby and Python. Think of middleware as a stack of functions through which an HTTP request must travel in order to create an appropriate response.

Middleware should be created so that the functionality of a given middleware is encapsulated together. In our case, this means we’ll be creating two pieces of middleware: one to create pages and one to list pages or show a page. Let’s create our first middleware:

app.use(function* (next) {
…
});

As you can see, we start by calling the app.use function, which takes a generator as its argument, and this effectively pushes the generator into the stack. To create a generator, we use a special function syntax where an asterisk is added as seen in the previous code snippet. We let our generator take a single argument called next, which represents the next middleware in the stack, if any.

From here on, it is simply a matter of checking and responding to the parameters of the HTTP request, which are accessible to us in the Koa context. This is also the function context, which in JavaScript is the keyword this, similar to other languages and the keyword self:

if (this.path != '/create') {
yield next;
return
}

Since we’re creating some middleware that helps us create pages, we make sure that this request is for the right path, in our case, /create; if not, we use the yield keyword and the next argument to pass the control of the program to the next middleware. Please note the return keyword that we also use; this is very important in this case as the middleware would otherwise continue while also passing control to the next middleware. This is not something you want to happen unless the middleware you’re in will not modify the Koa context or HTTP response, because subsequent middleware will always expect that they’re now in control.

Now that we have checked that the path is correct, we still have to check the method to see if we’re just showing the form to create a page, or if we should actually create a page in the database:

if (this.method == 'POST') {
var body = yield parse.form(this);
var page = yield Page.createOne({
   title: body.title,
   contents: body.contents
});
this.redirect('/' + page._id);
return
} else if (this.method != 'GET') {
this.status = 405;
this.body = 'Method Not Allowed';
return
}

To check the method, we use the Koa context again and the method attribute. If we’re handling a POST request we now know how to create a page, but this also means that we must extract extra information from the request. Koa does not process the body of a request, only the headers, so we use the co-body library that we downloaded early and loaded in as the parse variable. Notice how we yield on the parse.form function; this is because this is an asynchronous function and we have to wait until it is done before we continue the program.

Then we proceed to use our mongel model Page to create a page using the data we found in the body of the request, again this is an asynchronous function and we use yield to wait before we finally redirect the request using the page’s database id.

If it turns out the method was not POST, we still want to use this middleware to show the form that is actually used to issue the request. That means we have to make sure that the method is GET, so we added an else if statement to the original check, and if the request is neither POST or GET we respond with an HTTP status 405 and the message Method Not Allowed, which is the appropriate response for this case. Notice how we don’t yield next; this is because the middleware was able to determine a satisfying response for the request and it requires no further processing.

Finally, if the method was actually POST, we use the Jade library that we also installed using npm to render a create.jade template in HTML:

var html = jade.renderFile('create.jade');
this.body = html;

Notice how we set the Koa context’s body attribute to the rendered HTML from Jade; all this does is tell Koa that we want to send that back to the browser that sent the request.

Wrapping up

You are well on your way to creating your Koa app. In Part 2 we will implement Jade templates and list and view pages.

Ready for the next step? Read Part 2 here.

Explore all of our top Node.js content in one place – visit our Node.js page today!

About the author

Christoffer Hallas is a software developer and entrepreneur from Copenhagen, Denmark. He is a computer polyglot and contributes to and maintains a number of open source projects. When not contemplating his next grand idea (which remains an idea) he enjoys music, sports, and design of all kinds. Christoffer can be found on GitHub as hallas and at Twitter as @hamderhallas.

LEAVE A REPLY

Please enter your comment!
Please enter your name here