Koa Implements a Nice Pattern For Writing Web Services

For Dendriform I needed a small library or framework to implement a JavaScript (or TypeScript) test server that I could use for running integration tests against. I needed basic HTTP protocol support, the ability to serve static content, define custom routes based on URL, HTTP method and Accept-Header.

The goto for backend JavaScript has long been Express and it is presumably still a good choice. I noticed some complaints of Express not having out of the box async support. Looking around further it was surprisingly hard to identify a viable and popular candidate that was lightweight enough for my purposes.

After looking at a handful of possibilities I decided to give Koa a shot. It is apparently made (or started) by the creator(s) of Express and claims to be a more modern alternative with some of the learnings of working on Express baked in.

Koa builds on the standard node.js HTTP server and offers a small middleware based API. The project is structured as one core library and then many different projects that contribute additional functionality that can be composed using its middleware API.

The imports for my tiny test server look like this:

import Koa from 'koa'
import Router from '@koa/router'
import bodyParser from 'koa-body'
import logger from 'koa-logger'
import mount from 'koa-mount'
import serve from 'koa-static'

This is the core Koa import and then additional modules for the functionality I need:

Koa Mount is a nice example of the composability of the middleware pattern: I use it to expose the static files provided by Koa Static on a certain URL inside of my own application. Neither of these components need to know about each other.

All in all it was a very pleasant experience to implement a simple web service with Koa and I can recommend it for this use case. You can have a look at the full service implementation here: tiny-dendriform-server.ts.

It feels like the middleware pattern is quasi-optimal for the use case of exposing web services and having the ability to add a bunch of cross-cutting concerns (logging, authentication, authorization, etc) on top of your actual service logic.

I discovered some non critical downsides to Koa during my very limited usage of the library.

It's unclear to me how alive this project is: there are occasional releases being made, but the main development effort was some years ago and there is disturbingly little traffic on the issues or code bases of some of the components. This may also just be a case of me no knowing where the actual community takes place, or perhaps the library is just really mature and works for most people.

Documentation exists but seems thin and somewhat spotty. I had to resort to reading a bunch of the example code and tests in their repository. And it was sometimes hard to figure out the exact recommended way to solve a particular problem. On the up side: there are tests and example code.