Javascript

Introduction to Koa.js

June 14th, 2016 | By Jscrambler | 5 min read

Koa.js, a next-generation web framework for node.js. In this article, we introduce this new framework so that you can decide whether it’s a valid alternative to Express or one you might like to try in your next project.

If you’re using Node.js to build an application that listens over HTTP - a web server, web application, or REST API - then chances are you’ll reach for Express, perhaps without even thinking about it.

Not without reason; it’s probably fair to say that it’s the “go-to” package for such purposes and is one of the most dependent packages in the Node ecosystem.

However, there are alternatives to Express. One such option is Koa.js.

What is Koa.js

Koa.js development belongs to the team behind Express. It aims to be a smaller, more expressive, and more robust foundation for web applications and APIs.

Its key feature is the use of ES6 generators. In practical terms, an application written using Koa.js contains far fewer callbacks. Behind the scenes, it still uses the asynchronous goodness from Node.js, but the code looks markedly different, cleaner, and easier to understand.

Judge for yourself when we come to look at some examples.

Hello World

Let’s implement the obligatory “Hello World”:

// server.js
var koa = require('koa');
var app = koa();

app.use(function*() {
    this.body = 'Hello World';
});

app.listen(80);


You’ll soon become accustomed to everything in Koa is middleware; app.use() is used extensively. You’ll note that there are no callbacks and that we can set the response body on the application object via the body property.

Depending on the version of Node you have installed, you may need to use the --harmony-generators flag when running it:

node--harmony - generators server.js


Rather than type this out each time, you can use the scripts property in your package.json file like so:

{
    ...
    "scripts": {
        "start": "node --harmony-generators server.js"
    }
    ...
}


You can run it simply by typing:

npm start


Now, let’s dive a little deeper.

Routing

Integral to any web application or API is routing.

One prominent characteristic of Koa.js is that it deliberately provides the minimum functionality out-of-the-box, so we’ll need to install some additional middleware.

The Koa route package provides middleware for routing. In other words, we can map URLs to methods.

Install it using npm:

npm install koa - route--save


Let’s modify our “Hello World” so that it returns the message for the URL /hello:

app.use(route.get('/hello', hello));

function* home() {
    this.body = 'Hello World';
}


Here’s a slightly more advanced example to demonstrate the use of route parameters:

app.use(route.get('/', home));
app.use(route.get('/page/:id', page));

function* home() {
    // Render the homepage
}

function* page(id) {
    // Render a page with the specified id
}


To implement these methods, it’s time to look at the templating.

Templating

We will use the co-views package, which uses the co for generator-based control flow to add templating functionality.

One of the great things about the co-views library is that it allows you to use one of many templating engine libraries — of which there are many options! — or even to use multiple engines in a single project. It also enables you to map file extensions to implementations.

Whichever engine you decide to use, note that you’ll need to make sure you install it separately; co-views doesn’t do that for you.


To illustrate how to use co-views, start by installing it along with a templating engine — in this example, ejs:

npm install co - views ejs--save


Then require it:

var views = require('co-views');


Now, we can use the views method to set up a render() method by supplying some configuration values.

In the following example, we’re specifying the location of our templates — a folder named views — and we’re “mapping” files with the .html extension to the EJS engine:

var render = views(__dirname + '/views', {
    map: {
        html: 'ejs'
    }
});


To render a view for a given route, you can do this; note that this assumes you have a template named views/index.html:

app.use(route.get('/', home));

function* home() {
    this.body =
        yield render('index');
}


Additionally, you can pass a hash of data as the second argument to render(), for example:

this.body =
    yield render('page', {
            title: 'Page title',
            body: 'The body of the page');


A typical page template might look like this:

<%- include( 'partials/header.html' ) -%>
    <h2><%= page.title %></h2>
    <%=p age.body %>

        <%- include( 'partials/footer.html' ) -%>


We can use this principle along with route parameters in a complete example, albeit one with a static hash of “pages” rather than something database-driven. Take a look at this example:

var pages = {
    about   :    {
        title: 'About',
        body: 'This is the about page'
    },
    contact   :    {
        title: 'Contact',
        body: 'This is the contact page'
    }
};

app.use(route.get('/', home));
app.use(route.get('/page/:id', page));

function* page(id) {
    var page = pages[id];
    if (!page) this.throw(404, 'No such page');
    this.body =
        yield render('page', {
            page: page
        });
}


This also demonstrates the throw method, which allows you to issue an error HTTP status: A 404 not found.

However, this will only throw a 404 when the route is prefixed with “page”; we also need a “catch-all” handler for routes that haven’t been defined. We’ll look at that in the next section.

Handling 404 Errors

One very important piece of functionality for web applications is handling page not found errors. We can do so by creating some simple middleware.

The code below shows how you might approach this with koa.js:

app.use(function* pageNotFound(next) {
    yield next;

    if (404 !== this.status) return;

    // Explictly set the status code
    this.status = 404;

    this.body =
        yield render('404');
});


Here we’re checking the status attribute of the application for the 404 status code; if we are indeed to handle a page not found, then we render out the 404.html template and tell koa.js to explicitly set the status code to 404 so that it doesn’t assign a status code of 200 to the rendered error page.

Here is a more advanced page not found handler, which customizes the output according to the request’s accept header:

switch (this.accepts('html', 'json')) {
    case 'html':
        this.type = 'html';
        this.body = '

        Page Not Found

            ';
        break;
    case 'json':
        this.body = {
            message: 'Page Not Found'
        };
        break;
    default:
        this.type = 'text';
        this.body = 'Page Not Found';
}


Summary

In this article, we’ve taken a brief look at Koa.js, an alternative to Express which leans heavily on generators.

It’s arguably easier to understand and debug than Express thanks to the lack of messy callbacks, which might be a convincing reason for you to give it a try.

On the flip side, because it’s younger than Express it doesn’t yet have the wide range of compatible packages available.

If you want to find out more about Koa.js, refer to its website, find it on Github, or check out this repository of examples.

If you want to secure your JavaScript source code against theft and reverse engineering, you can try Jscrambler for free.

Jscrambler

The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.

View All Articles

Must read next

Javascript

Migrate Your Express App to Koa 2.0

Get to know more about migrating your Express App to Koa, a more evolved form of Express whose main feature is the elimination of callbacks.

January 19, 2017 | By Samier Saeed | 8 min read

Web Development

Implementing Authentication in JavaScript with Express.js and MongoDB

Learn how to implement authentication in JavaScript with Express.js and MongoDB. Let’s navigate through the complexities of these processes.

September 26, 2023 | By Antonello Semeraro | 19 min read

Section Divider

Subscribe to Our Newsletter