Conversation
* feat: add route caching core types, config schema, and AstroCache runtime Adds the foundational building blocks for the route caching feature (RFC #1245): - CacheOptions, CacheProvider, CacheProviderFactory, InvalidateOptions types - Zod config schema (CacheSchema) registered under experimental.cache - AstroCache class with set() merge semantics, tags accumulation, invalidate(), _applyHeaders() - NoopAstroCache for dev mode - Utility functions: normalizeCacheDriverConfig, cacheConfigToManifest, defaultSetHeaders - Public type exports from astro package * feat: wire cache driver into SSR pipeline and render context Integrates the cache system into the full request lifecycle: - Virtual module vite-plugin for cache driver resolution (resolves from project root) - SSRManifest: cacheDriver and cacheConfig fields - BasePipeline: getCacheProvider() with lazy resolution - RenderContext: creates AstroCache/NoopAstroCache per request, exposes on Astro.cache and context.cache (API routes, actions, middleware) - App base: wraps onRequest for runtime providers, strips CDN headers after; applies _applyHeaders for CDN-based providers - Serialized manifest: cache driver import + config serialization - Throwing getter on Astro global for prerendered routes * feat: add config-level cache route pattern matching Compiles cache.routes patterns using Astro's existing route parsing infrastructure (getParts, getPattern, routeComparator). Patterns use the same [param]/[...rest] syntax as file-based routing. Most specific route wins, computed once at startup via compileCacheRoutes(). * test: add cache unit tests, integration tests, and fixture 72 unit tests covering: - AstroCache runtime: set() merge semantics, tags, invalidate, _applyHeaders, _isActive - Utils: defaultSetHeaders, normalizeCacheDriverConfig, cacheConfigToManifest, isCacheHint, isLiveDataEntry - NoopAstroCache: all methods callable and no-op - Route matching: exact paths, dynamic params, rest params, priority ordering 6 integration tests with mock CDN provider: - CDN-Cache-Control and Cache-Tag from context.cache.set() - cache.set(false) opt-out, tags-only, config-level routes - .astro page and API route support * feat: add Node adapter in-memory LRU cache driver Runtime cache provider for @astrojs/node with: - In-memory LRU cache (custom Map-based, no external deps) - SWR support via stale-while-revalidate with background revalidation - Tag-based and path-based invalidation - X-Astro-Cache response header (HIT/MISS/STALE) for observability - Auto-set as default when experimental.cache is enabled without a driver - Exported as @astrojs/node/cache subpath * test: add Node adapter cache integration tests 8 tests covering the full runtime caching lifecycle: - Default driver auto-configuration - Cache hit/miss behavior with body verification - CDN header stripping for runtime providers - Tag-based and path-based invalidation - cache.set(false) opt-out - Uncached route passthrough * docs: add route caching implementation plan Full phased implementation plan for RFC #1245 covering: - Phases 1-3: Core types, pipeline wiring, route matching (complete) - Phase 4: Node adapter with in-memory LRU (complete) - Phase 5: Cloudflare adapter with CacheW - Phase 6: Vercel & Netlify adapters - Phase 7: Documentation * refactor: use symbols + helper functions for cache internals Replace _applyHeaders() and _isActive underscore convention with symbol-keyed methods behind applyCacheHeaders() and isCacheActive() helper functions. The symbols are not exported from the astro package, so users can't access them. Framework call sites import the helpers from the module directly. NoopAstroCache no longer needs the internal methods — the helpers handle the no-op case via 'in' checks. * Correctly disable when not configured * feat(cache): rename driver→provider, add routeRules config Breaking: cache.routes moved to experimental.routeRules This commit addresses RFC #1245 feedback: 1. Terminology: Rename 'driver' to 'provider' throughout the cache API. Providers have a richer interface (headers, middleware, invalidation) than the simpler driver pattern used by sessions/unstorage. 2. Configuration: Move cache route config from cache.routes to experimental.routeRules with Nitro-style shortcuts: - Flat cache options: { maxAge: 600, swr: 60 } - Nested form: { cache: { maxAge: 600 } } - Prerender control: { prerender: true } 3. API: Add cache.options getter for full cache state access, complementing the existing cache.tags getter. Files renamed: - cache-driver.ts → cache-provider.ts (both astro + node adapter) - mock-cache-driver.mjs → mock-cache-provider.mjs (test fixture) All 109 tests pass (95 unit + 7 core + 7 node adapter). * fix: remove prerender from routeRules (out of scope) routeRules is focused on cache configuration only. Prerender control will be handled separately if/when it's added to the feature. * chore: add exact-match comment on path invalidation * chore: move implementation plan to memory repo * Add slow page * fix: resolve lint errors (unexport internal schemas, fix generic constructor, fix test import) * fix: move cache runtime code to runtime/ dir, remove node: imports from SSR bundle - Move runtime cache code (AstroCache, noop, route-matching, utils) into cache/runtime/ directory following Astro conventions - Remove node:url and node:path imports that leaked into SSR bundle, breaking Cloudflare/edge deployments and verify-no-node-stuff test plugin - Guard getCacheProvider() call in hot path to skip async overhead when no cache provider is configured (addresses CodSpeed benchmark regression) * refactor: move memory cache to core, add type-safe config function - Move in-memory LRU cache provider from @astrojs/node to astro core (it's runtime-agnostic, not Node-specific) - Export memoryCache() from astro/config (follows sharpImageService pattern) - Runtime entrypoint at astro/cache/memory (separate from config context) - Remove bare string form for cache provider config (object-only) - Export CacheProviderConfig from public types * refactor: move memory cache tests from node adapter to astro core The memory cache provider is now in core, so its tests belong here too. Uses testAdapter() + app.render() instead of a live Node server. * docs: mention routeRules in changeset intro * perf: skip all cache code in render hot path when no provider configured * Changes from review * Tighten up memory cache * Fix import * Changes from review * Remove waitUntil from CacheProvider interface The built-in memory provider only runs on long-lived servers where fire-and-forget promises complete naturally. Platform-specific providers (Cloudflare, Vercel) have direct access to their own waitUntil APIs and don't need it on the shared interface. * Changes from review * Add memory provider unit tests and fix existing tests - New: 22 unit tests for memory-provider covering onRequest, LRU eviction, query parameter handling, Vary headers, SWR, invalidation, and response body/status/header preservation - Fix noop.test.js: use DisabledAstroCache class instead of removed singleton - Fix runtime.test.js: update frozen-object and error-message assertions to match review changes (Object.freeze removal, AstroError for invalidate) * Fix test:types: import cache types from dist/ instead of src/ Importing from src/ in the type test file pulls the src type tree into the same compilation as dist types from other imports, causing structural incompatibilities due to @internal-stripped members (e.g. fsPath on ImageMetadata, renderTemplateResultSym). * Revert "Fix test:types: import cache types from dist/ instead of src/" This reverts commit f323107. * Fix test:types cache types import mix Use cache schema from src but import cache types from dist so the schemas test still validates the public types without pulling the entire src type graph into the same compilation as dist.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )