Appearance
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.
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
).