diff --git a/e2e/solid-start/basic-solid-query/package.json b/e2e/solid-start/basic-solid-query/package.json
index 9c1c86748c..3af15c514d 100644
--- a/e2e/solid-start/basic-solid-query/package.json
+++ b/e2e/solid-start/basic-solid-query/package.json
@@ -17,7 +17,6 @@
"@tanstack/solid-query-devtools": "^6.0.0-rc.1",
"@tanstack/solid-router": "workspace:^",
"@tanstack/solid-router-devtools": "workspace:^",
- "@tanstack/solid-router-ssr-query": "workspace:^",
"@tanstack/solid-start": "workspace:^",
"redaxios": "^0.5.1",
"solid-js": "^2.0.0-rc.4",
diff --git a/e2e/solid-start/basic-solid-query/src/router.tsx b/e2e/solid-start/basic-solid-query/src/router.tsx
index fb853d3c22..d7367f8078 100644
--- a/e2e/solid-start/basic-solid-query/src/router.tsx
+++ b/e2e/solid-start/basic-solid-query/src/router.tsx
@@ -1,9 +1,9 @@
-import { QueryClient } from '@tanstack/solid-query'
-import { createRouter } from '@tanstack/solid-router'
-import { setupRouterSsrQueryIntegration } from '@tanstack/solid-router-ssr-query'
+import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'
+import { createRouter, isRedirect } from '@tanstack/solid-router'
import { routeTree } from './routeTree.gen'
import { DefaultCatchBoundary } from './components/DefaultCatchBoundary'
import { NotFound } from './components/NotFound'
+import type { AnyRouter } from '@tanstack/solid-router'
export function getRouter() {
const queryClient = new QueryClient()
@@ -14,10 +14,43 @@ export function getRouter() {
defaultPreload: 'intent',
defaultErrorComponent: DefaultCatchBoundary,
defaultNotFoundComponent: () => ,
+ // No integration package: on Solid, SSR transfer is native to
+ // QueryClientProvider (it serializes the request's cache into Solid's
+ // hydration registry and primes the client cache from it).
+ Wrap: (props) => (
+
+ {props.children}
+
+ ),
})
- setupRouterSsrQueryIntegration({
- router,
- queryClient,
- })
+ routeCacheRedirects(router, queryClient)
return router
}
+
+// Redirects thrown where the router is driving — beforeLoad, loaders, and
+// any queryFn a loader awaits — are the router's own to handle. Cache-driven
+// fetches (mount fetches, background refetches, mutations) run outside it,
+// so redirect() errors from both caches hand off to the router here.
+// Client-only runtime navigation glue, not an SSR concern: on the server a
+// redirect thrown during render resolves through the stream handler.
+function routeCacheRedirects(router: AnyRouter, queryClient: QueryClient) {
+ if (typeof document === 'undefined') return
+ const navigateOnRedirect = >(
+ onError?: (error: Error, ...rest: TRest) => void,
+ ) => {
+ return (error: Error, ...rest: TRest) => {
+ if (isRedirect(error)) {
+ error.options._fromLocation = router.stores.location.get()
+ void router.navigate(router.resolveRedirect(error).options)
+ return
+ }
+ onError?.(error, ...rest)
+ }
+ }
+ const queryCache = queryClient.getQueryCache()
+ const mutationCache = queryClient.getMutationCache()
+ queryCache.config.onError = navigateOnRedirect(queryCache.config.onError)
+ mutationCache.config.onError = navigateOnRedirect(
+ mutationCache.config.onError,
+ )
+}
diff --git a/e2e/solid-start/server-functions/package.json b/e2e/solid-start/server-functions/package.json
index f2bcf3aaeb..febe0d7d9f 100644
--- a/e2e/solid-start/server-functions/package.json
+++ b/e2e/solid-start/server-functions/package.json
@@ -17,7 +17,6 @@
"@tanstack/solid-query-devtools": "^6.0.0-rc.1",
"@tanstack/solid-router": "workspace:^",
"@tanstack/solid-router-devtools": "workspace:^",
- "@tanstack/solid-router-ssr-query": "workspace:^",
"@tanstack/solid-start": "workspace:^",
"js-cookie": "^3.0.5",
"redaxios": "^0.5.1",
diff --git a/e2e/solid-start/server-functions/src/router.tsx b/e2e/solid-start/server-functions/src/router.tsx
index e5566c4617..fcf29d1bfc 100644
--- a/e2e/solid-start/server-functions/src/router.tsx
+++ b/e2e/solid-start/server-functions/src/router.tsx
@@ -1,6 +1,6 @@
-import { createRouter } from '@tanstack/solid-router'
-import { setupRouterSsrQueryIntegration } from '@tanstack/solid-router-ssr-query'
-import { QueryClient } from '@tanstack/solid-query'
+import { createRouter, isRedirect } from '@tanstack/solid-router'
+import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'
+import type { AnyRouter } from '@tanstack/solid-router'
import { routeTree } from './routeTree.gen'
import { DefaultCatchBoundary } from './components/DefaultCatchBoundary'
import { NotFound } from './components/NotFound'
@@ -18,13 +18,49 @@ export function getRouter() {
bar: 'baz',
},
},
+ // No integration package: on Solid, SSR transfer is native to
+ // QueryClientProvider (it serializes the request's cache into Solid's
+ // hydration registry and primes the client cache from it).
+ Wrap: (props) => (
+
+ {props.children}
+
+ ),
})
- setupRouterSsrQueryIntegration({ router, queryClient })
+ routeCacheRedirects(router, queryClient)
return router
}
+// Redirects thrown where the router is driving — beforeLoad, loaders, and
+// any queryFn a loader awaits — are the router's own to handle. Cache-driven
+// fetches (mount fetches, background refetches, mutations) run outside it,
+// so redirect() errors from both caches hand off to the router here.
+// Client-only runtime navigation glue, not an SSR concern: on the server a
+// redirect thrown during render resolves through the stream handler.
+function routeCacheRedirects(router: AnyRouter, queryClient: QueryClient) {
+ if (typeof document === 'undefined') return
+ const navigateOnRedirect = >(
+ onError?: (error: Error, ...rest: TRest) => void,
+ ) => {
+ return (error: Error, ...rest: TRest) => {
+ if (isRedirect(error)) {
+ error.options._fromLocation = router.stores.location.get()
+ void router.navigate(router.resolveRedirect(error).options)
+ return
+ }
+ onError?.(error, ...rest)
+ }
+ }
+ const queryCache = queryClient.getQueryCache()
+ const mutationCache = queryClient.getMutationCache()
+ queryCache.config.onError = navigateOnRedirect(queryCache.config.onError)
+ mutationCache.config.onError = navigateOnRedirect(
+ mutationCache.config.onError,
+ )
+}
+
declare module '@tanstack/solid-router' {
interface Register {
router: ReturnType
diff --git a/e2e/solid-start/server-routes/package.json b/e2e/solid-start/server-routes/package.json
index ffd0793be5..ab6ee05f1e 100644
--- a/e2e/solid-start/server-routes/package.json
+++ b/e2e/solid-start/server-routes/package.json
@@ -16,7 +16,6 @@
"@tanstack/solid-query": "^6.0.0-rc.1",
"@tanstack/solid-router": "workspace:^",
"@tanstack/solid-router-devtools": "workspace:^",
- "@tanstack/solid-router-ssr-query": "workspace:^",
"@tanstack/solid-start": "workspace:^",
"js-cookie": "^3.0.5",
"redaxios": "^0.5.1",
diff --git a/e2e/solid-start/server-routes/src/router.tsx b/e2e/solid-start/server-routes/src/router.tsx
index fd79f34af0..98b6ed85e6 100644
--- a/e2e/solid-start/server-routes/src/router.tsx
+++ b/e2e/solid-start/server-routes/src/router.tsx
@@ -1,9 +1,9 @@
-import { createRouter } from '@tanstack/solid-router'
-import { setupRouterSsrQueryIntegration } from '@tanstack/solid-router-ssr-query'
-import { QueryClient } from '@tanstack/solid-query'
+import { createRouter, isRedirect } from '@tanstack/solid-router'
+import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'
import { routeTree } from './routeTree.gen'
import { DefaultCatchBoundary } from './components/DefaultCatchBoundary'
import { NotFound } from './components/NotFound'
+import type { AnyRouter } from '@tanstack/solid-router'
export function getRouter() {
const queryClient = new QueryClient()
@@ -13,8 +13,44 @@ export function getRouter() {
defaultErrorComponent: DefaultCatchBoundary,
defaultNotFoundComponent: () => ,
scrollRestoration: true,
+ // No integration package: on Solid, SSR transfer is native to
+ // QueryClientProvider (it serializes the request's cache into Solid's
+ // hydration registry and primes the client cache from it).
+ Wrap: (props) => (
+
+ {props.children}
+
+ ),
})
- setupRouterSsrQueryIntegration({ router, queryClient })
+ routeCacheRedirects(router, queryClient)
return router
}
+
+// Redirects thrown where the router is driving — beforeLoad, loaders, and
+// any queryFn a loader awaits — are the router's own to handle. Cache-driven
+// fetches (mount fetches, background refetches, mutations) run outside it,
+// so redirect() errors from both caches hand off to the router here.
+// Client-only runtime navigation glue, not an SSR concern: on the server a
+// redirect thrown during render resolves through the stream handler.
+function routeCacheRedirects(router: AnyRouter, queryClient: QueryClient) {
+ if (typeof document === 'undefined') return
+ const navigateOnRedirect = >(
+ onError?: (error: Error, ...rest: TRest) => void,
+ ) => {
+ return (error: Error, ...rest: TRest) => {
+ if (isRedirect(error)) {
+ error.options._fromLocation = router.stores.location.get()
+ void router.navigate(router.resolveRedirect(error).options)
+ return
+ }
+ onError?.(error, ...rest)
+ }
+ }
+ const queryCache = queryClient.getQueryCache()
+ const mutationCache = queryClient.getMutationCache()
+ queryCache.config.onError = navigateOnRedirect(queryCache.config.onError)
+ mutationCache.config.onError = navigateOnRedirect(
+ mutationCache.config.onError,
+ )
+}
diff --git a/packages/solid-router-ssr-query/README.md b/packages/solid-router-ssr-query/README.md
index 2aadc50710..8bf561672c 100644
--- a/packages/solid-router-ssr-query/README.md
+++ b/packages/solid-router-ssr-query/README.md
@@ -16,6 +16,18 @@
# @tanstack/solid-router-ssr-query
+> [!IMPORTANT]
+> **Deprecated on the Solid v2 line.** Solid 2.0's native channels make this
+> package's transport unnecessary: `QueryClientProvider` in
+> `@tanstack/solid-query` v6 serializes the request's cache into Solid's
+> hydration registry during SSR and primes the client cache from it — running
+> this package alongside it ships every query payload twice. The two runtime
+> conveniences it bundled are each a few lines of userland composition on
+> public APIs (see the Solid Start e2e apps under `e2e/solid-start/`): wrap
+> the router tree in `QueryClientProvider` via the router's `Wrap` option,
+> and hand cache-driven `redirect()` errors to `router.navigate` from the
+> caches' `config.onError`.
+
SSR query integration for TanStack Solid Router and TanStack Solid Query.
This package provides seamless integration between TanStack Router and TanStack Query for server-side rendering in Solid applications.
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index fae47614b2..58430bdc88 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4934,9 +4934,6 @@ importers:
'@tanstack/solid-router-devtools':
specifier: workspace:^
version: link:../../../packages/solid-router-devtools
- '@tanstack/solid-router-ssr-query':
- specifier: workspace:*
- version: link:../../../packages/solid-router-ssr-query
'@tanstack/solid-start':
specifier: workspace:*
version: link:../../../packages/solid-start
@@ -5460,9 +5457,6 @@ importers:
'@tanstack/solid-router-devtools':
specifier: workspace:^
version: link:../../../packages/solid-router-devtools
- '@tanstack/solid-router-ssr-query':
- specifier: workspace:*
- version: link:../../../packages/solid-router-ssr-query
'@tanstack/solid-start':
specifier: workspace:*
version: link:../../../packages/solid-start
@@ -5533,9 +5527,6 @@ importers:
'@tanstack/solid-router-devtools':
specifier: workspace:^
version: link:../../../packages/solid-router-devtools
- '@tanstack/solid-router-ssr-query':
- specifier: workspace:*
- version: link:../../../packages/solid-router-ssr-query
'@tanstack/solid-start':
specifier: workspace:*
version: link:../../../packages/solid-start