Skip to content
On this page

Koa Getting Started

Creating a Koa Project

First, create a directory named hello-koa as the root of your Koa project.

In the root directory, run npm install koa to install Koa and its dependencies. After installation, the directory structure will look like this:

hello-koa/
├── node_modules/      <-- Koa and all dependencies
├── package-lock.json
└── package.json       <-- npm description file

The package.json file contains dependency information and project descriptions, while package-lock.json is a snapshot of all dependencies to lock their versions.

Open package.json, which should contain:

json
{
    "dependencies": {
        "koa": "^2.15.3"
    }
}

This file only lists the Koa dependency, added by the npm install koa command.

The node_modules directory is where all dependencies are installed. You can delete this directory and run npm install again to reinstall. Running npm install will install dependencies based on package.json. You can also add a package with npm install xyz, which updates dependencies and installs xyz.

Next, manually add the following information to package.json:

json
{
    "name": "hello-koa",
    "version": "1.0",
    "description": "Hello koa webapp.",
    "type": "module",
    "dependencies": {
        "koa": "^2.15.3"
    }
}

Creating the App

Now, open hello-koa in VS Code and create a file named app.mjs. Enter the following code:

javascript
// Import Koa (note the capitalized class name):
import Koa from 'koa';

// Create a Koa instance representing the web app:
const app = new Koa();

// For any request, app will call this async function to handle the request:
app.use(async (ctx, next) => {
    await next();
    // Set response type and text:
    ctx.response.type = 'text/html';
    ctx.response.body = '<h1>Hello Koa!</h1>';
});

// Listen on port 3000:
app.listen(3000);
console.log('app started at port 3000...');

For every HTTP request, Koa will invoke the asynchronous function you provided:

javascript
async (ctx, next) => {
    await next();
    ctx.response.type = 'text/html';
    ctx.response.body = '<h1>Hello Koa!</h1>';
}

Here, ctx is an object encapsulating the request and response, and next refers to the next asynchronous function to handle. After calling await next(), you can set the response's content type and body.

Running the App

Now your project structure should look like this:

hello-koa/
├── node_modules/
├── app.mjs
├── package-lock.json
└── package.json

Run node app.mjs in the command line to start the web server. Open your browser and go to http://localhost:3000 to see the result.

hello-koa.webp

Koa Middleware

Let's take a closer look at Koa's execution logic. The core code is:

javascript
app.use(async (ctx, next) => {
    await next();
    ctx.response.type = 'text/html';
    ctx.response.body = '<h1>Hello Koa!</h1>';
});

For every HTTP request, Koa calls the async function registered via app.use(), passing in ctx and next.

You can manipulate ctx and set the return content. But why call await next()?

Koa chains multiple async functions together; each can perform its own tasks before calling await next(). Each async function is known as middleware, allowing you to compose multiple functionalities.

For example, you could use three middleware functions to log requests, track processing time, and output HTML:

javascript
app.use(async (ctx, next) => {
    console.log(`${ctx.request.method} ${ctx.request.url}`); // Log URL
    await next(); // Call next middleware
});

app.use(async (ctx, next) => {
    const start = Date.now(); // Current time
    await next(); // Call next middleware
    const ms = Date.now() - start; // Time taken
    console.log(`Time: ${ms}ms`); // Log time taken
});

app.use(async (ctx, next) => {
    await next();
    ctx.response.type = 'text/html';
    ctx.response.body = '<h1>Hello Koa!</h1>';
});

The order of middleware is crucial; the order you call app.use() determines their execution sequence.

If a middleware does not call await next(), subsequent middleware will not execute. This can be useful for functions that check user permissions, for example:

javascript
app.use(async (ctx, next) => {
    if (await checkUserPermission(ctx)) {
        await next();
    } else {
        ctx.response.status = 403;
    }
});

Understanding middleware is key to effectively using Koa!

Lastly, note that the ctx object has shorthand methods, such as ctx.url (equivalent to ctx.request.url) and ctx.type (equivalent to ctx.response.type).

Koa Getting Started has loaded