Repository navigation
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. Also export `getServerFunctionMeta`, `decorateHandler` and `decorateMiddleware` from the SPA server entry, so SPA apps that import them build. Closes #2287 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: fd9e80a 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 |
✅ Deploy Preview for solid-start-landing-page ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
commit: |
This was referenced Oct 14, 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.
Closes #2287.
What this adds
A new value for the
ssroption: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. One response carries both the document and its data.How it works
Server.
loadInitialDataruns the router's data-only pass, the same one single-flight mutations use. Withevent.router.dataOnlyset, the router runs the matched routes'preloads without rendering pages, andqueryrecords each call inevent.router.data. SPA builds already keep only thepreloads in the server route tree.The shell then renders with
renderToStreaminstead ofrenderToString. Each query promise is passed tosharedConfig.context.serializeunder a<Hydration>boundary, because Solid skips serialization inside<NoHydration>. This is the same serializer SSR uses for query data:<HydrationScript eventNames={[]}>defines_$HY.r. Nothing hydrates, so it doesn't capture events.Responses from a query.
queryskips its ownResponsehandling in data-only mode, so it's applied here:content-type,content-length,content-encoding).json()response sends its body.Client.
mount()pointssharedConfig.has/sharedConfig.loadat_$HY.rfor the firstrender(), then restores them. The router'squeryalready reads serialized data through those two functions on a cache miss, so no router change is needed. Later client navigations fetch as usual.Limits
mode: "stream"or"async"). Withmode: "sync"nothing is sent and the client fetches as before.windowwhile rendering), the error is logged and the client fetches its data.serialization.plugins, the same as query data in SSR today.clientOnly(() => import("./Page"))plus a routepreloadalready gives the same behavior under SSR.Also fixed
@solidjs/start/serverin SPA mode didn't exportgetServerFunctionMeta,decorateHandlerordecorateMiddleware. Any app importing one of them failed to build withssr: false, for example theexperimentsfixture. They're exported now.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_$HY, no server queriesResponsehandling, rejections, sync render, root failure, client seeding).packages/start: 251 tests, typecheck, build, format check.apps/tests: unit, Playwright default (42), bundled-dev (42) and base (3) all pass.Not fixed here: in SPA mode, the
experimentsfixture still returns 404 for its pages. Its[...404].tsxexports both a page andGET, and SPA builds treated that route as API-only. That's an existing problem, fixed separately in #2354.🤖 Generated with Claude Code