fix: await full SSR stream so first-byte HTML contains page content#159
Conversation
renderToReadableStream resolves when only the shell is ready, so the first flush contained just the Suspense skeleton fallback while real content streamed in later chunks. Await stream.allReady before responding so the complete document ships in a single response. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 41 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Problem
On first load, the SSR response only guaranteed the React shell in the first flush. All page components are
lazy()behind a<Suspense>boundary inApp.tsx, so the initial HTML contained thePageFallbackskeleton while real content streamed in later chunks — a skeleton flash on first paint, and crawlers/tools that don't process streamed chunks could see only the skeleton.Fix
Await
stream.allReadybefore returning the response inentry-server.tsx. The complete document now ships in a single response, so page content is present from the first byte.This is the pattern React documents for crawlers and static generation: Waiting for all content to load for crawlers and static generation.
Trade-off
Loses streaming TTFB (fine for docs pages — content is already resolved synchronously on the server). React still emits the Suspense fallback markup with an inline swap script, but since everything arrives at once, the swap happens during HTML parse with no visible skeleton.
Verified
Ran
bun run dev:examples:basicand curled/docs— full rendered content (<h1>Welcome</h1>, body headings) present in the response HTML.🤖 Generated with Claude Code