Koa ETag Middleware
koa-etag is a Koa middleware package designed to provide ETag support for HTTP responses, leveraging the `etag` library to automatically generate ETag headers. This functionality is crucial for enhancing caching efficiency, as it allows clients (browsers, proxies) to conditionally request resources, thereby reducing bandwidth consumption and server load. The current stable version is 5.0.0, which notably features a complete rewrite in TypeScript, offering both ESM and CJS bundles, and requiring Node.js 18+. While there isn't a strict, frequent release cadence, major updates like v5.0.0 represent significant overhauls. Its primary differentiator is its seamless integration within the Koa ecosystem, typically working in conjunction with `koa-conditional-get` to enable full HTTP conditional GET support. However, it is important to note that the package's README strongly advises migrating to `@koa/etag` (v5+) as `koa-etag` is slated for deprecation in its next major release.
Common errors
-
TypeError: etag is not a function
cause This error typically occurs when attempting to import `koa-etag` using a named import syntax (e.g., `import { etag } from 'koa-etag'`) or destructuring with `require` (`const { etag } = require('koa-etag')`), despite the package providing a default export.fixFor CommonJS, use `const etag = require('koa-etag');`. For ESM, use `import etag from 'koa-etag';` to correctly import the default middleware function. -
ETag headers are missing or not functioning correctly, despite `koa-etag` being installed.
cause A common cause is `koa-conditional-get` not being installed or used, or `koa-compress` being placed after `koa-etag` in the middleware stack. `koa-etag` only *generates* the ETag; `koa-conditional-get` handles the client-side conditional requests, and `koa-compress` must run first to ensure the ETag is calculated on the final (compressed) body.fixEnsure both `koa-conditional-get` and `koa-etag` are applied, and crucially, `app.use(compress())` must be called before `app.use(conditional())` and `app.use(etag())`.
Warnings
- deprecated The `koa-etag` package is in maintenance mode and will be formally deprecated in its next major release. Users are strongly advised to migrate to the `@koa/etag` package for continued support, bug fixes, and future feature updates, as it is the direct successor and recommended alternative.
- gotcha For correct ETag generation and response caching, the `koa-compress` middleware must be applied *before* `koa-conditional-get` and `koa-etag` in the middleware chain. Applying compression after ETag calculation will result in mismatched ETags for compressed content.
- breaking Version 5.x of `koa-etag` dropped support for older Node.js versions. It now explicitly requires Node.js 18 or higher due to modern language features and tooling updates.
- gotcha Version 5.x was rewritten in TypeScript and bundled for both ESM and CJS. While `v5.0.2` improved CJS interop, incorrect import statements (e.g., named imports for default exports) can lead to errors.
Install
-
npm install koa-etag -
yarn add koa-etag -
pnpm add koa-etag
Imports
- etag
import { etag } from 'koa-etag';import etag from 'koa-etag';
- etag (CommonJS)
const { etag } = require('koa-etag');const etag = require('koa-etag'); - KoaEtagOptions (TypeScript type)
import type { KoaEtagOptions } from 'koa-etag';
Quickstart
const Koa = require('koa');
const etag = require('koa-etag');
const conditional = require('koa-conditional-get');
const compress = require('koa-compress');
const app = new Koa();
// compress must be used before conditional and etag for correct ETag calculation
app.use(compress());
// etag works together with conditional-get for full HTTP caching support
app.use(conditional());
app.use(etag());
app.use(function (ctx) {
ctx.body = 'Hello World';
});
app.listen(3000);
console.log('Server listening on port 3000');