JSPM

@canner-ca/next-cache

0.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q43244F
  • License MIT

One-line cache headers for Canner — set Cache-Control + Surrogate-Key in Next.js Route Handlers, Middleware, and getServerSideProps so Canner caches and purges your pages by tag.

Package Exports

  • @canner-ca/next-cache

Readme

@canner-ca/next-cache

One-line cache headers for Canner, for Next.js. It sets Cache-Control and Surrogate-Key exactly the way Canner's cache proxy expects, so your pages cache on Canner and purge by tag from your CMS.

Install

npm install @canner-ca/next-cache

Requires Node.js 20 or later. Zero runtime dependencies.

Use it

Call cache() wherever you set response headers in Next.js.

Route Handlers (app/.../route.ts):

import { NextResponse } from 'next/server';
import { cache } from '@canner-ca/next-cache';

export async function GET() {
  const posts = await getPosts();
  const res = NextResponse.json(posts);
  cache(res, { ttl: 3600, tags: ['blog-listing'] });
  return res;
}

Middleware (middleware.ts) — this is how you cache App Router pages, since server components can't set response headers themselves:

import { NextResponse } from 'next/server';
import { cache } from '@canner-ca/next-cache';

export function middleware(request) {
  const res = NextResponse.next();
  if (request.nextUrl.pathname.startsWith('/blog/')) {
    // Tag by a path-derived key your CMS webhook can purge.
    const slug = request.nextUrl.pathname.split('/')[2];
    cache(res, { ttl: 3600, tags: [slug, 'blog-listing'] });
  }
  return res;
}

Pages Router (getServerSideProps / API routes) — pass the Node response:

export async function getServerSideProps({ res, params }) {
  const post = await getPost(params.slug);
  cache(res, { ttl: 600, tags: [post.id] });
  return { props: { post } };
}

Full guide (the webhook setup, the dashboard token): https://canner.ca/docs/caching

How App Router caching works

A Next.js App Router URL serves two things: the HTML document (a cold load, a crawler, a hard navigation — no RSC header) and an RSC payload (client navigation/prefetch — sends an RSC header). Canner caches only the HTML document and passes every RSC request straight through to your app. So marking a page cacheable is safe: client-side navigation is never served a stale or mismatched response, and the cache speeds up exactly the requests that matter for SEO and first paint.

You don't configure any of that — it's how Canner's proxy treats Next.js. You just set the headers (via middleware for pages, or directly in route handlers).

API

cache(target, options)

target is a Response/NextResponse, a Node ServerResponse/NextApiResponse, or a Headers. Returns the same target for chaining.

applyCacheHeaders(headers, options)

Lower-level, when you already hold a Headers instance.

options

Option Type Notes
ttl number (required) Seconds Canner may serve the cached response. Sets s-maxage. Positive integer.
tags string | number | Array<string | number> Tags for purging. Sets Surrogate-Key. Numbers are coerced; duplicates and whitespace tags are dropped.
browserTtl number Optional. Seconds the visitor's browser may cache (sets max-age). Omit to keep tag purges instant.

What Canner caches

The same rules this helper produces:

  • method GET/HEAD, status 200, no RSC request header
  • Cache-Control: public with a positive s-maxage (or max-age)
  • no Set-Cookie
  • Vary absent, Accept-Encoding, or the Next.js router tokens (which Canner handles via the HTML/RSC split above)
  • body under 8 MB

It only ever adds headers

This package never strips or mutates anything your app set. It does not remove Set-Cookie: Canner already declines to cache a response that sets a cookie, so you get a development-only warning instead — your cookie is left untouched. A bad ttl sets no headers and warns; only passing something that isn't a response/Headers throws.

Non-goals

  • It doesn't configure your CMS webhook — that's two copy-paste values in the Canner dashboard (Settings → Caching).
  • It doesn't implement stale-while-revalidate; after a purge the next request re-renders once and re-caches.

For Astro, see @canner-ca/astro-cache.

License

MIT