Files
skills/docs/foundation/data/pwa/src/caching-strategies/router.md
2026-05-29 08:20:56 +01:00

2.8 KiB

caching-strategies/router.ts

Purpose

Router evaluates incoming Requests against a list of registered routes in order and dispatches the first match to its strategy. The router is the glue between the SW fetch event and the package's caching strategies. It owns the default Cache and fetcher references so individual strategies stay free of global access — strategies receive their StrategyContext through the router and need not touch caches, fetch, or Date.now.

Features

  • HTTP-method filtering (GET, POST, PUT, …) with case-insensitive comparison.
  • Three pattern types: RegExp, substring string, and predicate function ((Request) => boolean).
  • Per-route cache-name override so different routes can write to isolated caches without re-instantiating the router.
  • Fall-through to fetcher(request) for unmatched requests — the router is always safe to respondWith() because every request gets a response.
  • OTel pwa_cache_strategy_ms histogram recording strategy latency.

Usage: Basic

import {
    Router,
    cacheFirst,
    networkFirst,
    staleWhileRevalidate,
} from "@suaveplan/pwa";

const router = new Router({ cacheName: "v1" });
router.registerRoute({
    pattern: /\.(png|jpg|webp)$/,
    strategy: cacheFirst({ ttlMs: 86_400_000 }),
});
router.registerRoute({
    pattern: /\/api\/static\//,
    strategy: staleWhileRevalidate(),
});
router.registerRoute({
    method: "GET",
    pattern: /\/api\//,
    strategy: networkFirst({ ttlMs: 30_000 }),
});
self.addEventListener("fetch", (event) =>
    event.respondWith(router.handle(event.request))
);

Usage: Advanced

Per-route cache + predicate matching:

import { Router, cacheOnly } from "@suaveplan/pwa";

const router = new Router();
router.registerRoute({
    method: "GET",
    pattern: (req) => req.url.startsWith("/offline-fallback/"),
    strategy: cacheOnly(),
    cacheName: "offline-fallbacks",
});

API Reference

  • new Router(options?: RouterOptions).
  • registerRoute(route: Route): void.
  • handle(request: Request): Promise<Response>.
  • size: number.
  • Route — { method?, pattern, strategy, cacheName? }.
  • RouterOptions — { cacheStorage?, cacheName?, fetcher?, clock?, observability? }.

Implementation Notes

The router opens caches lazily via cacheStorage.open() on every handle() call. The platform CacheStorage.open() is idempotent and returns the same underlying Cache instance for the same name, so the per-call open is a trivial pointer lookup rather than a heavy initialisation. The fall-through path bypasses both the cache open and the strategy invocation entirely, so unmatched requests pay no per-request cost beyond the linear route scan. For applications with hundreds of routes, the scan can be optimised by the caller via predicate matchers that group routes by URL prefix.