Repository navigation
Adapter 0.9.0: pages stream, as on a Worker - #62
Closed
nicu-chiciuc wants to merge 5 commits into
Closed
nicu-chiciuc wants to merge 5 commits into
nicu-chiciuc wants to merge 5 commits into
Conversation
…wait The same page in both examples. Its loader returns a promise that resolves two seconds later, and the page renders it with Await behind a fallback. On a host that streams, the document goes out at once with the fallback and the value follows in a later chunk, with React's swap script; on a host that sends the document whole, everything arrives after two seconds. The Workers twin under wrangler dev, fetched with a browser user agent: 4.2 kB at 0 ms, the rest 2.0 s later. With curl's own user agent TanStack treats the client as a bot and waits for the whole document first. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ate 2026-08-04 Cloudflare turns nodejs_compat on by default for Workers whose compatibility date is 2026-08-04 or later (changelog 2026-08-04-nodejs-compat-default); the twin's date is 2026-10-01. Checked by building and running the twin without the flag under wrangler dev: the server bundle still imports node:stream and node:async_hooks, and the Worker serves the pages. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codex: a navigation inside the app runs the page's loader in the browser, so the timer ran there on both hosts and the demo never reached the server. The header link now reloads the document. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Preview of examples/tanstack-spa: https://steady-hare-438.convex.site |
|
Preview of examples/tanstack-ssr: https://next-rook-172.convex.site |
commit: |
🚀 Deploying Preview to Cloudflare 🚀Preview URL: https://nicu-adapter-streaming-convex-hosting-tanstack-ssr-workers.pfp.workers.dev (commit 9d41bb0)This URL reflects your latest Preview deploymentPreview Deployments by commit
|
The header read the user with useQuery, which does not run on the server, so a signed-out visitor got an empty header slot and the "Sign in" link appeared only once the browser had hydrated, connected, and asked; the same on both hosts, because the code is the same. The server knows the session from its token: SignedOut and SignedIn from the convex-auth entry render it, so a rendered page carries the right header in its first bytes. The name still comes from the cache the root loader filled for a page rendered as the user. A prerendered page has no token and shows its header once the browser knows, as before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The server entry is TanStack's own stream handler: React's Web Stream renderer, the document sent as it renders, each Suspense boundary and deferred loader value in a later chunk, status and redirects decided before the first byte, the whole document for a client TanStack takes for a bot. The whole-render wait and the progressiveChunkSize override of 0.6.0 are gone with it. The one obstacle was bundling: TanStack's stream renderer and router-core's stream transformer import Node's stream classes at the top of their files for a branch that runs only where React has no Web Stream renderer. Convex has that renderer, so the branch never runs, and Convex's bundler had no node:stream to resolve. convexSsr() now resolves node:stream to a stub whose classes throw if anything calls them. node:async_hooks already bundled, Convex provides AsyncLocalStorage. Measured on the SSR example's dev deployment, /stream with a browser user agent: first byte at 0.5 s with the fallback, last byte at 2.5 s with the value; with curl's user agent, the whole document at 2.2 s. The Workers twin: 0.1 s and 2.1 s. Closes #49. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
nicu-chiciuc
force-pushed
the
nicu-adapter-streaming
branch
from
October 16, 2026 19:19
2e06776 to
9d41bb0
Compare
Contributor
Author
|
Folded into #61: one pull request for the streaming fix and the page that proves it. |
Contributor
Author
|
Reopened: kept as its own pull request after all, stacked on #61. |
Contributor
Author
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 issue 49. Stacked on PR 61, whose
/streampage is the proof.What changes
The adapter's server entry is now TanStack's own stream handler,
createStartHandler(defaultStreamHandler), plus theURLSearchParams.sizegetter Convex lacks. The whole-render wait, therenderSsrHtmlResponsedetour, the doctype trimming, and theprogressiveChunkSizeoverride are gone.The one obstacle was bundling, not the runtime. TanStack's stream renderer and router-core's stream transformer import Node's stream classes at the top of their files, for a branch that runs only where React has no Web Stream renderer. Convex has that renderer, so the branch never runs, and Convex's bundler had no
node:streamto resolve.convexSsr()now resolvesnode:streamto a stub module shipped with the adapter, whose classes throw if anything calls them.node:async_hooksalready bundled, Convex providesAsyncLocalStorage. The example's server bundle after the change importsnode:async_hooksand nothing else from Node.Measured
/streamfrom PR 61, fetched with a browser user agent:With curl's own user agent, TanStack takes the client for a bot and sends the whole document at 2.2 s, on both hosts.
/,/about/,/todos(307 to/signin),/signin, and a 404 answer as before.Research behind it
Every host TanStack documents has Node's stream module: Node, Bun, Deno, Netlify's functions, Vercel through Nitro, and Cloudflare Workers through
nodejs_compat, on by default since compatibility date 2026-08-04. Convex's runtime is the one without it, so nobody upstream has needed the split; the one related PR, TanStack/router#8094 for Solid, has waited since August without review and does not touch the React file. The stub is independent of upstream.Adapter 0.9.0, breaking nothing in apps:
src/server.tskeeps re-exporting the entry.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.