Skip to content

fix(solid-start): bundle solid-query packages during SSR to fix duplicate QueryClientContext (#6151)#7267

Merged
birkskyum merged 6 commits intomainfrom
fix-6151
Apr 26, 2026
Merged

fix(solid-start): bundle solid-query packages during SSR to fix duplicate QueryClientContext (#6151)#7267
birkskyum merged 6 commits intomainfrom
fix-6151

Conversation

@birkskyum
Copy link
Copy Markdown
Member

@birkskyum birkskyum commented Apr 26, 2026

Close #6151

@tanstack/solid-query ships separate development and production builds (build/dev.js vs build/index.js), each with its own createContext() Symbol for QueryClientContext.

During dev SSR:

  • Source files go through Vite's transform pipeline → Vite resolves @tanstack/solid-query with the development condition → dev.js
  • @tanstack/solid-router-ssr-query is externalized → Node loads it directly → Node resolves its import { QueryClientProvider } from '@tanstack/solid-query' with default Node conditions (no development) → index.js

Two distinct module instances → two distinct QueryClientContext Symbols. The Provider sets one context, the route's useQueryClient() reads the other and gets undefined.

This is Solid-specific because @tanstack/react-query and @tanstack/vue-query ship a single build, so the same problem can't manifest there.

Fix

Add @tanstack/solid-router-ssr-query, @tanstack/solid-query, and @tanstack/solid-query-devtools to ssr.noExternal in the Solid Start Vite plugin so their resolution is consistent with the user's source.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed an SSR issue so query context is managed correctly, preventing duplicate query client contexts during server-side rendering.
  • New Features

    • Added a Nitro + Solid Start example showcasing SSR-integrated data fetching, routing, and hydration.
  • Tests

    • Added end-to-end Playwright tests to validate SSR query behavior and ensure no runtime errors.
  • Chores

    • Added release metadata for a patch update and project configuration for the new example.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9ccc1f9b-a25a-49f2-87ab-d8726dd68379

📥 Commits

Reviewing files that changed from the base of the PR and between 6380e00 and f2a4666.

📒 Files selected for processing (2)
  • e2e/solid-start/nitro-query/package.json
  • e2e/solid-start/nitro-query/playwright.config.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • e2e/solid-start/nitro-query/package.json
  • e2e/solid-start/nitro-query/playwright.config.ts

📝 Walkthrough

Walkthrough

Adds a changeset and a Vite plugin config override to force SSR noExternal for TanStack Solid Query/router; introduces a new e2e Nitro + Solid Start app (routes, generated route tree, router factory, QueryClient integration), Playwright config, Vite/Nitro setup, and an end-to-end test validating SSR query behavior.

Changes

Cohort / File(s) Summary
Vite plugin SSR config
packages/solid-start/src/plugin/vite.ts
Adds a config() override in the tanstack-solid-start:config Vite plugin to append TanStack Solid Query and router SSR packages to ssr.noExternal.
Changeset metadata
.changeset/dark-windows-occur.md
New Changeset file declaring a patch release for @tanstack/solid-start documenting an SSR fix to avoid duplicate QueryClientContext.
E2E Nitro app config & tooling
e2e/solid-start/nitro-query/package.json, e2e/solid-start/nitro-query/playwright.config.ts, e2e/solid-start/nitro-query/tsconfig.json, e2e/solid-start/nitro-query/vite.config.ts
Adds a new private e2e package with scripts, dependencies/devDependencies, Playwright config (dynamic port + webServer), TypeScript config, and Vite config wiring Nitro, tanstackStart plugin, and Solid SSR.
Generated route tree & router
e2e/solid-start/nitro-query/src/routeTree.gen.ts, e2e/solid-start/nitro-query/src/router.tsx
Adds a generated routeTree export, TS module augmentations, and a getRouter() factory that creates a QueryClient, builds the router with context, sets preloading to intent, and registers SSR-query integration.
Routes / UI shell
e2e/solid-start/nitro-query/src/routes/__root.tsx, e2e/solid-start/nitro-query/src/routes/index.tsx
New root document shell route (with hydration scripts) and an index file route that uses Solid Query with initialData and renders query.data.
E2E test
e2e/solid-start/nitro-query/tests/app.spec.ts
New Playwright test visiting /, asserting rendered query output equals ok, and that runtime errors do not include defaultQueryOptions.

Sequence Diagram(s)

sequenceDiagram
  participant Browser as Browser
  participant Server as Nitro\ SSR\ Server
  participant Router as Solid\ Router
  participant Query as QueryClient

  Note over Server,Query: Server-side render (SSR)
  Server->>Query: instantiate QueryClient
  Server->>Router: instantiate router with routeTree + context(QueryClient)
  Router->>Server: render route tree to HTML (uses QueryClient)
  Server->>Browser: send HTML + hydration scripts
  Browser->>Router: hydrate router
  Browser->>Query: reuse SSR cache / continue queries
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A tiny hop, a careful nudge and fix,
QueryClient stays single — no duplicate mix.
Routes wake under Nitro, tests give a cheer,
SSR hums, hydration’s near. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main fix: adding packages to SSR bundling to resolve duplicate QueryClientContext issues in Solid Start.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-6151

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud Bot commented Apr 26, 2026

View your CI Pipeline Execution ↗ for commit f524b5b

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 1m 2s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 4s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-26 02:10:23 UTC

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 26, 2026

Bundle Size Benchmarks

  • Commit: e085a0a6bdfe
  • Measured at: 2026-04-26T02:08:58.591Z
  • Baseline source: history:aebf4264767a
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.35 KiB 0 B (0.00%) 274.60 KiB 75.97 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-router.full 90.77 KiB 0 B (0.00%) 286.11 KiB 78.90 KiB ▅▅▅▅▅▅▅▅▅▅▅
solid-router.minimal 35.58 KiB 0 B (0.00%) 106.84 KiB 31.96 KiB ▁▁▁▁▁▁▁▁███
solid-router.full 40.32 KiB 0 B (0.00%) 121.06 KiB 36.15 KiB ▁▁▁▁▄▄▄▄▆██
vue-router.minimal 53.30 KiB 0 B (0.00%) 152.01 KiB 47.88 KiB ▅▅▅▅▅▅▅▅▅▅▅
vue-router.full 58.44 KiB 0 B (0.00%) 168.19 KiB 52.34 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-start.minimal 101.92 KiB 0 B (0.00%) 322.77 KiB 88.18 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-start.full 105.35 KiB 0 B (0.00%) 333.10 KiB 91.02 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-start.rsbuild.minimal 101.43 KiB 0 B (0.00%) 325.62 KiB 87.12 KiB ▁████████
react-start.rsbuild.full 104.74 KiB 0 B (0.00%) 336.31 KiB 89.93 KiB ▅▅▅▅▅▅▅▅▅
solid-start.minimal 49.58 KiB 0 B (0.00%) 152.67 KiB 43.69 KiB ▁▁▁▁▁▁▁▁███
solid-start.full 55.36 KiB 0 B (0.00%) 169.58 KiB 48.69 KiB ▁▁▁▁▄▄▄▄▆██

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 26, 2026

🚀 Changeset Version Preview

1 package(s) bumped directly, 0 bumped as dependents.

🟩 Patch bumps

Package Version Reason
@tanstack/solid-start 1.167.45 → 1.167.46 Changeset

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 26, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@7267

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@7267

@tanstack/eslint-plugin-start

npm i https://pkg.pr.new/@tanstack/eslint-plugin-start@7267

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@7267

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@7267

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@7267

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@7267

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@7267

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@7267

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@7267

@tanstack/react-start-rsc

npm i https://pkg.pr.new/@tanstack/react-start-rsc@7267

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@7267

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@7267

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@7267

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@7267

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@7267

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@7267

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@7267

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@7267

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@7267

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@7267

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@7267

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@7267

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@7267

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@7267

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@7267

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@7267

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@7267

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@7267

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@7267

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@7267

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@7267

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@7267

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@7267

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@7267

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@7267

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@7267

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@7267

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@7267

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@7267

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@7267

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@7267

commit: f2a4666

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 26, 2026

Merging this PR will not alter performance

✅ 5 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing fix-6151 (f524b5b) with main (e054474)2

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

  2. No successful run was found on main (e085a0a) during the generation of this report, so e054474 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
e2e/solid-start/nitro-query/src/routes/__root.tsx (1)

16-16: Avoid any for children; use JSX.Element.

The children?: any typing weakens type safety. Prefer importing JSX from solid-js and typing as JSX.Element to keep the shell strictly typed.

♻️ Proposed change
 import { HydrationScript } from 'solid-js/web'
+import type { JSX } from 'solid-js'
 import type { QueryClient } from '@tanstack/solid-query'
@@
-function RootDocument(props: { children?: any }) {
+function RootDocument(props: { children?: JSX.Element }) {

As per coding guidelines: "Use TypeScript strict mode with extensive type safety".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/solid-start/nitro-query/src/routes/__root.tsx` at line 16, The
RootDocument function currently types its props as { children?: any }, which
weakens type safety; update the props to use Solid's JSX.Element by importing
JSX from 'solid-js' and change the signature to props: { children?: JSX.Element
} (or children: JSX.Element | undefined) so RootDocument uses strict typing for
its children; modify the import and the RootDocument declaration accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@e2e/solid-start/nitro-query/src/routes/__root.tsx`:
- Line 16: The RootDocument function currently types its props as { children?:
any }, which weakens type safety; update the props to use Solid's JSX.Element by
importing JSX from 'solid-js' and change the signature to props: { children?:
JSX.Element } (or children: JSX.Element | undefined) so RootDocument uses strict
typing for its children; modify the import and the RootDocument declaration
accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4ec89d15-a876-4b7b-8e3e-4c1eaa6a5f1f

📥 Commits

Reviewing files that changed from the base of the PR and between 8f94e8a and 6380e00.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • e2e/solid-start/nitro-query/package.json
  • e2e/solid-start/nitro-query/playwright.config.ts
  • e2e/solid-start/nitro-query/src/routeTree.gen.ts
  • e2e/solid-start/nitro-query/src/router.tsx
  • e2e/solid-start/nitro-query/src/routes/__root.tsx
  • e2e/solid-start/nitro-query/src/routes/index.tsx
  • e2e/solid-start/nitro-query/tests/app.spec.ts
  • e2e/solid-start/nitro-query/tsconfig.json
  • e2e/solid-start/nitro-query/vite.config.ts
✅ Files skipped from review due to trivial changes (3)
  • e2e/solid-start/nitro-query/vite.config.ts
  • e2e/solid-start/nitro-query/package.json
  • e2e/solid-start/nitro-query/src/routeTree.gen.ts

Copy link
Copy Markdown
Contributor

@nx-cloud nx-cloud Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud is proposing a fix for your failed CI:

We remove the dependenciesMeta.injected: true declaration for @tanstack/solid-router-ssr-query in the nitro-query e2e package.json to fix the ERR_RESOLVE_PACKAGE_ENTRY_FAIL error. With injected: true, pnpm physically copies only the package's published files (dist/ + src/), but since the workspace package has no built dist/, the copy is incomplete and Vite cannot resolve the entry when the package is bundled via ssr.noExternal. Removing it restores the standard workspace symlink behaviour used by all other solid-start e2e projects, allowing Vite to resolve the package from source.

Tip

We verified this fix by re-running tanstack-solid-start-e2e-nitro-query:test:e2e.

Suggested Fix changes
diff --git a/e2e/solid-start/nitro-query/package.json b/e2e/solid-start/nitro-query/package.json
index b123d7187c..9d0b64c02d 100644
--- a/e2e/solid-start/nitro-query/package.json
+++ b/e2e/solid-start/nitro-query/package.json
@@ -17,11 +17,6 @@
     "solid-js": "^1.9.10",
     "vite": "^8.0.0"
   },
-  "dependenciesMeta": {
-    "@tanstack/solid-router-ssr-query": {
-      "injected": true
-    }
-  },
   "devDependencies": {
     "@playwright/test": "^1.50.1",
     "@tanstack/router-e2e-utils": "workspace:^",
diff --git a/e2e/solid-start/nitro-query/vite.config.ts b/e2e/solid-start/nitro-query/vite.config.ts
index 6c469e63af..a0f200ce04 100644
--- a/e2e/solid-start/nitro-query/vite.config.ts
+++ b/e2e/solid-start/nitro-query/vite.config.ts
@@ -2,7 +2,18 @@ import { defineConfig } from 'vite'
 import { tanstackStart } from '@tanstack/solid-start/plugin/vite'
 import solid from 'vite-plugin-solid'
 import { nitro } from 'nitro/vite'
+import { fileURLToPath } from 'node:url'
 
 export default defineConfig({
+  resolve: {
+    alias: {
+      '@tanstack/solid-router-ssr-query': fileURLToPath(
+        new URL(
+          '../../../packages/solid-router-ssr-query/src/index.tsx',
+          import.meta.url,
+        ),
+      ),
+    },
+  },
   plugins: [nitro(), tanstackStart(), solid({ ssr: true })],
 })

Apply fix via Nx Cloud  Reject fix via Nx Cloud


Or Apply changes locally with:

npx nx-cloud apply-locally BgLb-lwnM

Apply fix locally with your editor ↗   View interactive diff ↗



🎓 Learn more about Self-Healing CI on nx.dev

@birkskyum birkskyum merged commit aebf426 into main Apr 26, 2026
14 checks passed
@birkskyum birkskyum deleted the fix-6151 branch April 26, 2026 02:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tanstack Start + Solid Query + Nitro bug

1 participant