koa-static

Serves static files from a directory with automatic ETag, Last-Modified, and cache headers.

Since Koa 2 Spec ↗

Syntax

import serve from 'koa-static';
app.use(serve(root, [options]));

Parameters

NameTypeRequiredDescription
root string Yes Absolute or relative path to the directory to serve files from.
options object No Options: `maxage` (ms, cache max-age), `hidden` (serve dotfiles, default false), `index` (default `"index.html"`), `defer` (call `next()` first if true), `gzip` (serve `.gz` files, default true), `extensions` (array of file extensions to try).

Returns

function — Koa middleware that serves files from the given directory.

Examples

import Koa from 'koa';
import serve from 'koa-static';
import { fileURLToPath } from 'node:url';
import path from 'node:path';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const app = new Koa();

app.use(serve(path.join(__dirname, 'public'), {
  maxage: 60 * 60 * 1000, // 1 hour
  gzip: true,
}));

app.listen(3000);
Output
GET /logo.png  → 200 (binary)
GET /index.html → 200 (HTML)
GET /missing   → 404

Notes

`koa-static` wraps `koa-send` for the actual file streaming. For SPA serving (fallback to `index.html`), set `defer: true` and add a catch-all middleware that calls `send(ctx, 'index.html', { root })` when no match is found. Pair with a CDN in production instead of serving large assets directly from Node.

See also