Skip to content

The latest news releases from the Qwik team

July 16th, 2026

@qwik.dev/router@2.0.0-beta.38

Major Changes

  • BREAKING: 404.tsx and error.tsx now render inside their layouts (with @layout/! modifiers), a route miss resolves the nearest 404.tsx, and the 404 page is prerendered for static hosts. Rename 404.tsx to 404!.tsx if you do not want to add the layout. (by @briancarbone in #8762)

  • BREAKING: SPA view transitions are now opt-in; set viewTransition={true} on QwikRouterProvider to re-enable them. (by @maiieul in #8778)

  • ✨ relocate built assets with output.assetFileNames; remove build.assetsDir handling (by @maiieul in #8817)

  • ✨ rename the Link prefetchBundle prop to prefetchBundles (by @maiieul in #8828)

Minor Changes

  • feat(router): automatically omit fully-prerendered, server-free routes from the production SSR route plan so their chunks tree-shake out of size-capped server bundles. (by @briancarbone in #8742)

  • ✨ route loaders gain a blockSSR option (default true); set blockSSR: false to run a loader in the background without blocking SSR (experimental, requires the blockSSR feature flag) (by @wmertens in #8793)

  • ✨ returning ev.redirect(), ev.error() or ev.rewrite() from a loader, action, request handler or server function now behaves the same as throwing them (by @wmertens in #8775)

  • feat(router): add an exclude option to rewriteRoutes to skip generating localized routes for matching path patterns. (by @briancarbone in #8751)

  • ✨ render SSG in a dedicated Vite build environment, so prerendered route code stays out of the deployed server bundle (by @briancarbone in #8760)

    SSG now runs from the buildApp step of the Vite builder. The Qwik CLI and adapters already build via createBuilder().buildApp(), so they need no change. Code that prerenders by calling Vite's programmatic build() directly must switch to builder.buildApp(), otherwise the SSG step is silently skipped.

  • ✨ add configurable server request body limits (by @Varixo in #8839)

Patch Changes

  • 🐞🩹 render navigation state before loading the next route (by @Varixo in #8821)

  • 🐞🩹 prerendered routes are now correctly excluded from the server route plan (by @briancarbone in #8759)

  • fix(router): honor the routeLoader$ id option so loaders created through a shared wrapper (which share one optimizer-assigned QRL hash) get distinct ids instead of all but the first being silently deduped in getModuleRouteLoaders. A dev-mode warning is now logged when two distinct loaders share an id. (by @maiieul in #8749)

  • 🐞🩹 prevent cold dev route loader requests from failing during SPA navigation (by @Varixo in #8787)

  • 🐞🩹 keep expiring loader responses private by default (by @Varixo in #8839)

  • 🐞🩹 action redirects work again (by @wmertens in #8780)

  • 🐞🩹 resolve image jsx imports with extra query parameters. (by @Varixo in #8753)

  • 🐞🩹 avoid prefetching loader data already fetched by route loaders (by @wmertens in #8836)

  • 🐞🩹 keep Azure response collection work proportional to output size (by @Varixo in #8839)

  • 🐞🩹 keep deeply nested form parsing work proportional (by @Varixo in #8839)

  • 🐞🩹 ensure SPA navigation correctly refreshes route loader data for catch-all routes, including when loader data is shared through context (by @Varixo in #8748)

  • 🐞🩹 routeLoader$ fail() now sets the loader value to { failed } instead of throwing an error, as it was before. (by @wmertens in #8756)

  • 🐞🩹 prerendered route loaders no longer 404 when the client and server are built as separate processes (by @briancarbone in #8760)

  • 🐞🩹 route loader no longer resolves to undefined on the first dev SPA navigation (by @briancarbone in #8770)

  • 🐞🩹 routeLoader$ not re-running during SPA navigation between URLs that match the same catchall route (by @Varixo in #8730)

  • 🐞🩹 prefix dev CSS and HMR URLs with Vite base (by @Varixo in #8837)

  • 🐞🩹 refetch re-exported route loaders after navigation (by @wmertens in #8792)

  • 🐞🩹 route action type allows invalidate without validators (by @wmertens in #8807)

  • 🐞🩹 preserve scroll after spa action submits (by @Varixo in #8797)

  • 🐞🩹 hot-reload route-imported CSS in dev without a server restart (by @briancarbone in #8725)

  • 🐞🩹 streaming server$ no longer crashes the Bun server on client disconnect (by @aggyomfg in #8798)

  • 🐞🩹 register aliased server functions used only in client code like visible tasks (by @Varixo in #8818)

  • 🐞🩹 adapter post-build runs with ssg disabled, and the ssg build skips minify/sourcemaps (by @wmertens in #8806)

  • 🐞🩹 the ssg build no longer bundles the unused deploy server entry (by @wmertens in #8806)

  • 🐞🩹 a prerendered route's loader with no static sidecar now falls through to SSR instead of failing as a missing static asset (by @briancarbone in #8760)

  • 🐞🩹 preserve strict loader URL isolation during route resolution (by @wmertens in #8836)

  • 🐞🩹 ensure dev SPA navigation loads route loader data correctly for catch-all and base-prefixed routes (by @Varixo in #8805)

  • Updated dependencies [96fe9e1, b0bdbf3, 77ae28f, dbdf85f, 570aec5, b5a74df, 3672ae5, 2e2a913, 1921d7a, 8e75051, e28ae7c, 3710734, e9d5d98, 12387da, e70b299, 9fd1303, bed0127, 1da9aa6, f9a0e83, 2a47192, 3a0df67, ee013ae, d3b6678, 885367a, 8fc5762, 03fae8a, fd9f197, 4917019, abaae23, 15ea2d8]:

Contributors:

  • layout
  • briancarbone
  • maiieul
  • wmertens
  • Varixo
  • aggyomfg
  • qwik
  • 2

June 9th, 2026

@qwik.dev/router@2.0.0-beta.37

Major Changes

  • BREAKING: Route loaders are now AsyncSignals. This means that value.failed is no longer used to indicate a loader failure. Instead, if a loader fails, the error will be stored in error, and reading value will throw that error. (by @wmertens in #8501)

    This also means that you can now pass expires, poll, and allowStale options to route loaders. See the documentation for more details on these options and how to use them.

  • BREAKING: routeLoader$ cannot read action state any more, so that they are cacheable and predictable. All use cases can be achieved in other ways, like reading the action signal directly in the component or having the loader read from URL-derived state that the action updates. (by @wmertens in #8501)

  • BREAKING: Qwik Router no longer retrieves q-data.json files on every SPA navigation. You can remove any caching rules for these. (by @wmertens in #8501)

    Instead, Qwik Router now retrieves q-loader-${hash}.${manifestHash}.json for RouteLoader data. You can specify expiry for each RouteLoader individually, and it is automatically used to set browser caching headers. The manifestHash ensures that when you build a new version of your app, the old cached data will be invalidated and the new data will be fetched.

    The default expiry for RouteLoader data is 2 minutes, so that prefetching and caching of RouteLoader data is useful. You control this with the expiry option on each RouteLoader, and you can set it to 0 to disable caching.

    Furthermore, any RouteLoader that has expiry: 0 will be generated as a file during SSG, which allows SPA navigation to work even without a server.

    Note: Be careful with caching for RouteLoaders that return user-specific data, especially regarding logout and CDN caching. Use low expiry times for these and use eTag to still allow caching benefits.

  • BREAKING: cacheKey functions now get (requestEv: RequestEvent, eTag: string) as arguments, instead of (status: number, eTag: string, pathname: string) (by @wmertens in #8699)

Minor Changes

  • 🐞🩹 Route loaders now redirect in their JSON response instead of using HTTP redirect (by @wmertens in #8501)

  • ✨ route loaders now accept eTag to shortcut data retrieval when the data has not changed. See the documentation for more details on this option and how to use it. (by @wmertens in #8501)

  • ✨ Routeloaders now support a cacheKey and eTag property, similar to SSR pageConfig. The only difference is that the full value is known before sending, so cached entries generate an ETag before returning the initial request instead of after rendering as with SSR. (by @wmertens in #8699)

  • ✨ When routeConfig provides a cacheKey but no eTag, SSR will determine an ETag value by hashing the rendered output. When the cache entry is later retrieved, the ETag is provided to the client and later requests can use the ETag for conditional requests. (by @wmertens in #8699)

  • ✨ route loaders now accept search to only allow certain query parameters to trigger the loader. This means that random search parameters won't cause the loader to re-run. If you do not pass search, then all search parameters will be passed to the loader and will trigger it when they change. (by @wmertens in #8501)

    However, qwikRouter now has the option strictLoaders which is true by default, which means that if you do not specify search for a loader, then it will not receive any search parameters and will not re-run when the search parameters change.

Patch Changes

  • fix(router): Update route loader metadata in the dev route trie when route source files change. (by @wmertens in #8501)

  • ✨ expose RequestEvent.internalRequest for framework-internal JSON requests. (by @wmertens in #8698)

  • fix(router): run q-loader requests through the full page middleware chain and handle unfollowed HTTP redirects. (by @wmertens in #8698)

  • fix(router): fetch non-serialized route loader data after resume (by @Varixo in #8706)

  • 🐞🩹 don't run middleware defined in index.* for a routeloader on the same path, unless the routeloader is defined in index (by @wmertens in #8697)

  • 🐞🩹 fix "assignment to constant variable" errors when route loaders cache filtered search state across SPA navigations (by @Varixo in #8709)

  • Updated dependencies [d4f40ac, a8509c1, 9ff0dd4, 3dcb29b]:

Contributors:

  • wmertens
  • Varixo
  • qwik
  • 2
1
...
15
16
17
...
30