Repository navigation
Conversation
Client navigation to a URL that only exists through a server rewrite() to a different route rendered the 404 page (or the wrong dynamic route), because the client matches routes from its own route table. With the new `serverRewrites` plugin option, the client asks the server (`q-route.json`) where such a URL finally routes to and renders that route, keeping the original URL. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Don't hard-code no-store. The q-route.json answer carries the headers the middleware set before rewrite() (cacheControl(), CDN-Cache-Control, Cache-Tag, ...), and defaults to private like loaders. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
omerman
marked this pull request as ready for review
October 18, 2026 04:31
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Draft for review on my fork only (not for QwikDev/qwik yet).
Problem
rewrite()only runs on the server. In v1 the client asked the server forq-data.jsonon every navigation, and the response carried the finalhref/isRewrite, so a click on a URL that only exists through a rewrite to a different route worked. Sinceq-data.jsonwas split per loader (QwikDev#8501), the client matches routes from its own route table, so such a click renders the 404 page, or whatever dynamic/wildcard route happens to match. A full page load still works. The only SPA rewrite e2e (products/shirt-rewrite) rewrites to the same[id]route, so it doesn't catch this.Real-world case: SEO URLs like
/artists/<name>/<song>/chordsrewritten by a DB lookup to/track/chords/<id>.Change
serverRewrites(defaultfalse).q-route.jsonis sent with the headers set beforethrow rewrite()(cacheControl(),CDN-Cache-Control,Cache-Tag, ...) andprivateif none, like loaders. Nothing is hard-coded to no-store.q-route.json(recognised likeq-loader-*.json) answers{ p: <pathname after rewrites> }. It is not aninternalRequest, so rewrite middleware treats it as a normal navigation. Placed after plugins/route middleware, so any rewrite has already re-resolved the route.q-route.json,loadRoute()the returned path, keep the original URL. Loaders are still fetched through the visible URL so the server re-applies the rewrite exactly as in SSR. A redirect answer falls back to a full page load.Tests
recognizeRequest/ trim forq-route.json.rewrite-spa.e2e.ts+rewrite-spa/routes +plugin@rewrite-spa.ts: SSR serves the target under the original URL; SPA click renders the target, keeps the URL, no reload, no page errors. Fails withserverRewrites: false("Loader … returned empty response"), passes with it on.e2e/qwik-e2e/tests/qwikrouteron chromium: 196 passed, 1 failed (ssg-snapshotcore bundle brotli budget; I only had a dev build, the test asks for the production build).Known limits / open questions
X-Qwik-fullpath, but thenoriginalUrldiffers from SSR..api.mdfiles not regenerated.Based on the
@qwik.dev/router@2.0.0-rc.3release commit.🤖 Generated with Claude Code