Koa Static File Server
Koa-static is a middleware for the Koa web framework designed to efficiently serve static files such as HTML, CSS, JavaScript, images, and other assets. It acts as a wrapper around `koa-send`, providing a streamlined interface for common static file serving patterns. The current stable version is 5.0.0. This package is mature and stable, with infrequent releases (v5.0.0 published 8 years ago), indicating a solid and well-understood functionality rather than rapid ongoing development. Key features include comprehensive caching controls via `maxage`, support for serving hidden files, configurable default index filenames (e.g., `index.html`), and automatic Gzip/Brotli compression where supported by the client. It also offers a `defer` option to allow other middleware to handle requests first and the ability to set custom response headers. Its primary differentiator is its deep integration and idiomatic usage within the Koa ecosystem, offering a lightweight and unopinionated approach compared to more feature-rich alternatives like `koa-static-cache` which offer in-memory caching or complex routing extensions.
Common errors
-
GET http://localhost:3000/app.js net::ERR_ABORTED 404 (Not Found)
cause The requested static file (e.g., `app.js`) does not exist in the configured static directory, or the path to the static directory is incorrect, or `koa-static` is not mounted correctly.fixVerify that the file exists in the directory provided to `koa-static`. Ensure the `publicPath` is resolved correctly (e.g., `path.join(__dirname, 'public')`). If serving from a subpath, use `koa-mount`. -
Error: "root" is required in koa-send
cause The `root` directory parameter (the path to the folder containing your static files) was not provided to `koa-static`.fixAlways pass the absolute path to your static files directory as the first argument to `koa-static`: `app.use(serve(path.join(__dirname, 'public')));` -
Cannot serve files outside the 'root' directory.
cause Attempting to access a file via a URL that resolves to a path outside the configured `root` directory for security reasons.fixEnsure all files intended to be served statically are located within the `root` directory specified in `koa-static`. Adjust your application's file structure or URL routing accordingly.
Warnings
- breaking Upgrading from Koa 1.x (generator-based middleware) to Koa 2.x (async/await middleware) requires updating `koa-static` to a compatible version (v5.x). The middleware signature changed from `function* (next)` to `async (ctx, next) => { ... }`. Direct usage of `koa-static` in a Koa 1.x application will lead to errors.
- gotcha To serve static files from a specific URL subpath (e.g., `/assets`), `koa-static` must be combined with `koa-mount`. Directly passing a path like `app.use(serve('/assets', publicPath))` will not mount it correctly.
- gotcha The `defer` option, when set to `true`, ensures that `koa-static` only attempts to serve files *after* all downstream middleware have had a chance to respond. If a downstream middleware handles the request, `koa-static` will be skipped. This can be unexpected if you intend static files to be served first.
- gotcha When using `koa-static` in an ESM project (with `"type": "module"` in `package.json`), ensure your path resolution for the root directory is correct. Node.js's native `__dirname` and `__filename` are not available in ESM modules.
Install
-
npm install koa-static -
yarn add koa-static -
pnpm add koa-static
Imports
- serve
import { serve } from 'koa-static';import serve from 'koa-static';
- serve (CommonJS)
const serve = require('koa-static'); - Options Interface (TypeScript)
import Koa from 'koa'; import serve from 'koa-static'; const options: koaStatic.Options = { maxage: 3600000 };import Koa from 'koa'; import serve, { Options } from 'koa-static'; const options: Options = { maxage: 3600000 };
Quickstart
import Koa from 'koa';
import serve from 'koa-static';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = new Koa();
const publicPath = path.join(__dirname, 'public');
// Create a 'public' directory in your project root and add some files (e.g., index.html)
// Example public/index.html:
// <h1>Hello from Koa Static!</h1>
app.use(serve(publicPath, {
// Optional: Enable gzip compression if client supports it and .gz file exists
gzip: true,
// Optional: Cache assets in browser for 7 days
maxage: 1000 * 60 * 60 * 24 * 7,
// Optional: Serve 'index.html' when root path is requested
index: 'index.html'
}));
// Fallback for non-static routes
app.use(async (ctx) => {
if (!ctx.response.status || ctx.response.status === 404) {
ctx.body = 'Hello Koa! No static file found or served.';
}
});
const PORT = process.env.PORT ?? 3000;
app.listen(PORT, () => {
console.log(`Koa static server running on http://localhost:${PORT}`);
console.log(`Serving files from: ${publicPath}`);
});