Repository navigation
feat: add ssr: "data-only" (1.x) - #2353
Merged
Merged
Conversation
The app renders on the client without hydration, as with `ssr: false`, but the server runs the requested page's route preloads and streams their query results with the HTML shell. The client's queries read those results on the first render instead of fetching them again. The server collects the queries with the router's data-only pass, the same one single-flight mutations use, and streams them through Solid's own serializer under a `<Hydration>` boundary. On the client, `mount()` points `sharedConfig.has`/`load` at `_$HY.r` for the first `render()`, which is where `query` already looks for serialized data. Data-only mode doesn't prerender `/` the way `ssr: false` does, because each request needs its own data, and the client is compiled without hydration markers. Also export `getServerFunctionMeta` from the SPA server entry, as the SSR entry does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: ef2391d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
commit: |
2 tasks done
brenelz
approved these changes
Oct 15, 2026
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.
For #2287 on the 1.x line. The same feature for 2.x is in #2352.
What this adds
The app renders on the client with
render(), as withssr: false, so there's no hydration and no app HTML from the server. The server still runs the routepreloads for the requested page and streams their query results with the HTML shell. On the first render, the client's queries take those results instead of fetching them again.How it works
The design is the same as #2352.
Server. The router's data-only pass collects the page's query promises. Single-flight mutations already use this pass in
runtime/server-handler.ts. The SPA shell then renders withrenderToStream, and each promise goes tosharedConfig.context.serializeunder a<Hydration>boundary, which is Solid's own SSR serializer.<HydrationScript eventNames={[]}>defines_$HY.r.Responses from a query.
queryskips its ownResponsehandling in data-only mode, so it's applied here:json()response sends its body.Client.
mount()pointssharedConfig.has/sharedConfig.loadat_$HY.rfor the firstrender(). Router 0.15'squeryreads serialized data through them, the same as router 1.0.Differences from 2.x
ssr: falseprerenders/into a static shell. Data-only mode doesn't, because each request needs its own data.ssr: start.ssr, and the"data-only"string would have turned on hydratable output. It now getsstart.ssr === true.getServerFunctionMeta, as the SSR entry does.decorateHandleranddecorateMiddlewaredon't exist on 1.x.Limits
These are the same as #2352:
mode: "sync".Verification
Production build of the
basicfixture with a route whosepreloadcalls four queries (data,json()withset-cookie, a throw, and a redirect on another route):_$HY.r[...]for each query;Content-Type: text/html;set-cookiefrom thejson()queryDateandMapintact, error shown by theErrorBoundary, 0 server function calls302withlocation: /co-bssr: false.output/public/index.html, no_$HYpackages/start: 106 unit tests (11 new), typecheck and build pass.apps/tests: the unit test passes. Cypress: 18 of 19 pass.server-function.cy.ts› "should reject the promise when the response is a 5xx without an X-Error header". It fails the same way on clean1.x.🤖 Generated with Claude Code