Conversation
🦋 Changeset detectedLatest commit: 2c12f9f The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
This PR extends Qwik Router’s server-side caching story by adding in-memory caching + ETag-based conditional request handling for both SSR HTML and routeLoader$ JSON responses, including automatic ETag generation (hash-based) when caching is enabled but no explicit ETag is provided.
Changes:
- Split caching into separate SSR and loader caches (LRU) and add
clearLoaderCache()alongsideclearSsrCache(). - Introduce shared ETag utilities (
normalizeETag,quoteETag,hashETag,checkETagMatch) and apply normalized/unquoted ETags tocacheKeycallbacks while quoting only for HTTP headers. - Update public types/docs:
CacheKeyFnnow takes(requestEv, eTag)and loaders gain acacheKeyoption whileeTag: trueis removed in favor ofcacheKey.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/qwik-router/src/ssg/resolve-request-handlers-ssg.ts | Wires new SSR/loader cache deps into SSG request handler resolver. |
| packages/qwik-router/src/runtime/src/types.ts | Updates public types/docs for ETag + cacheKey behavior; adds loader cacheKey support. |
| packages/qwik-router/src/runtime/src/route-loaders.unit.ts | Updates loader test helper to include __cacheKey. |
| packages/qwik-router/src/runtime/src/route-loaders.ts | Parses/stores new loader cacheKey option; exports filterSearchParams. |
| packages/qwik-router/src/runtime/src/qwik-router.runtime.api.md | Updates extracted API type for CacheKeyFn. |
| packages/qwik-router/src/runtime/src/not-found-wrapper.ts | Updates synthetic module cacheKey impl to new CacheKeyFn signature. |
| packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.ts | Wires new SSR/loader cache deps into runtime request handler resolver. |
| packages/qwik-router/src/middleware/request-handler/resolve-request-handlers-core.ts | Implements SSR cache hit/miss flow with optional auto-hashed ETag and new cache key resolution. |
| packages/qwik-router/src/middleware/request-handler/middleware.request-handler.api.md | Adds clearLoaderCache() to public middleware API docs. |
| packages/qwik-router/src/middleware/request-handler/index.ts | Exposes clearLoaderCache() from the middleware entrypoint. |
| packages/qwik-router/src/middleware/request-handler/handlers/loader-handler.unit.ts | Adds tests for normalized/unquoted eTag passed to cacheKey callback + quoted response header. |
| packages/qwik-router/src/middleware/request-handler/handlers/loader-handler.ts | Adds loader JSON caching + ETag handling (explicit and auto-hashed) and cache-key support. |
| packages/qwik-router/src/middleware/request-handler/etag.ts | Refactors caching into LRU caches for SSR and loaders; adds default key builders + clear functions. |
| packages/qwik-router/src/middleware/request-handler/etag-hash.unit.ts | Adds unit tests for ETag quoting/normalization/hashing and If-None-Match matching behavior. |
| packages/qwik-router/src/middleware/request-handler/etag-hash.ts | Adds shared ETag normalization/quoting/hashing and conditional request helper. |
| packages/docs/src/routes/docs/(qwikrouter)/caching/index.mdx | Documents SSR and loader caching behavior and new APIs. |
| packages/docs/src/routes/api/qwik-router/index.mdx | Updates generated API docs for CacheKeyFn and ContentModuleETag. |
| packages/docs/src/routes/api/qwik-router/api.json | Updates generated API JSON for CacheKeyFn and ContentModuleETag. |
| packages/docs/src/routes/api/qwik-router-middleware-request-handler/index.mdx | Documents clearLoaderCache() in generated middleware API docs. |
| packages/docs/src/routes/api/qwik-router-middleware-request-handler/api.json | Adds clearLoaderCache() to generated middleware API JSON. |
| .changeset/lucky-pugs-marry.md | Changeset entry for SSR auto-ETag hashing when caching without explicit eTag. |
| .changeset/free-poems-serve.md | Changeset entry for loader caching + ETag support. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
@qwik.dev/core
@qwik.dev/router
eslint-plugin-qwik
create-qwik
@qwik.dev/optimizer
commit: |
built with Refined Cloudflare Pages Action⚡ Cloudflare Pages Deployment
|
7fba4a6 to
f55c29d
Compare
| function createLoaderRequestEvent( | ||
| requestEv: RequestEventInternal, | ||
| filteredSearch: string, | ||
| getLoaderRequestEvent: LoaderRequestEventFactory | ||
| ): RequestEventInternal { | ||
| const url = new URL(requestEv.url); | ||
| url.search = filteredSearch; | ||
|
|
||
| return Object.create(requestEv, { | ||
| cookie: { | ||
| value: requestEv.cookie, | ||
| enumerable: true, | ||
| }, | ||
| pathname: { | ||
| get: () => url.pathname, | ||
| enumerable: true, | ||
| }, | ||
| query: { | ||
| get: () => url.searchParams, | ||
| enumerable: true, | ||
| }, | ||
| request: { | ||
| value: createRequestUrlView(requestEv.request, url), | ||
| enumerable: true, | ||
| }, | ||
| sharedMap: { | ||
| value: requestEv.sharedMap, | ||
| enumerable: true, | ||
| }, | ||
| url: { | ||
| value: url, | ||
| enumerable: true, | ||
| }, | ||
| resolveValue: { | ||
| value: (async (loaderOrAction: LoaderInternal | ActionInternal) => { | ||
| if (loaderOrAction.__brand === 'server_loader') { | ||
| const loaderValues = getRouteLoaderValues(requestEv); | ||
| if (loaderOrAction.__id in loaderValues) { | ||
| return loaderValues[loaderOrAction.__id]; | ||
| } | ||
| return loadRouteLoader(loaderOrAction, getLoaderRequestEvent(loaderOrAction)); | ||
| } | ||
| return undefined; | ||
| }) as RequestEventInternal['resolveValue'], | ||
| enumerable: true, | ||
| }, | ||
| }) as RequestEventInternal; | ||
| } |
There was a problem hiding this comment.
we had something like this somewhere, no?
- routeLoaders are now also cacheable - eTag is auto generated from content hash when caching - make cacheKey and eTag always string, empty when not set
- when `qwikRouterOptions.strictLoaders`, loader requestEv is scoped to own path - when `loaderOptions.search`, loader requestEv is scoped to own search - disable redirects for loader requests
Adds caching and eTag support to routeloaders, and adds auto eTag generation for SSR.
Breaking change if using previous beta: the
cacheKeycallback arguments changed, now you get the requestEv.Changes: