-
-
Notifications
You must be signed in to change notification settings - Fork 635
Add Async Props documentation with animated SVG diagrams #2265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: upcoming-v16.3.0
Are you sure you want to change the base?
Changes from 55 commits
2579c5c
a8fcd81
33099d3
f1be9e9
082c706
5bb915d
735f117
a7bf6c1
f7ca0d0
7b78507
53960f5
7093abf
5b943c1
4ba8ca1
a3d81b3
d511815
57ccd28
cb18b79
e08182c
78d4ecf
a771923
cbb2c8f
f35895b
2d52b7d
ba44313
9cb5808
c83721a
a05b20a
6a61dce
8dc3860
0ca0084
865c415
ae419f4
7ba75a2
468da50
3175785
253aedc
7891091
1a3fce6
002297b
bba6006
efbef62
b0c9de1
7196322
a026899
529fe03
7d21f03
f10b628
da37b46
50762d7
6551d00
42b8ad0
6e29f81
ecdde38
54164cf
9192c08
e49af10
cee0b02
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| # Async Props: Streaming Server-Side Rendering | ||
|
|
||
| Async Props is a React on Rails Pro feature that enables **streaming server-side rendering** with progressive hydration. Instead of waiting for all data to load before sending any HTML to the browser, Async Props streams the page shell immediately while data fetches happen in parallel. | ||
|
|
||
| ## The Problem with Traditional SSR | ||
|
|
||
| In traditional SSR, the entire page must wait for **all** data before anything is sent to the browser: | ||
|
|
||
|  | ||
|
|
||
| This creates a poor user experience: | ||
| - **Long Time to First Byte (TTFB)**: Users stare at a blank screen | ||
| - **Sequential data fetching**: Each data source blocks the next | ||
| - **All-or-nothing rendering**: No content until everything is ready | ||
|
|
||
| ## How Async Props Solves This | ||
|
|
||
| Async Props uses React 18's streaming capabilities to render content progressively: | ||
|
|
||
|  | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The table presents exact millisecond figures ("1800ms → 50ms") as if they are general facts rather than an illustrative example. Readers may interpret these as benchmarks or guarantees. Consider adding a note such as "(example; actual numbers depend on your data fetch latency)" to avoid setting incorrect expectations. |
||
|
|
||
| ### Key Benefits | ||
|
|
||
| | Metric | Traditional SSR | Async Props | | ||
| |--------|-----------------|-------------| | ||
| | Time to First Byte | 1800ms | **50ms** | | ||
| | Time to Interactive | 1800ms | **50ms** | | ||
| | Data Fetching | Sequential | **Parallel** | | ||
| | User Perception | Slow | **Fast** | | ||
|
|
||
| ## Progressive Loading in Action | ||
|
|
||
| Watch how content loads progressively with Async Props: | ||
|
|
||
|  | ||
|
|
||
| 1. **Stage 1 (50ms)**: Shell renders with skeleton loaders - page is already interactive! | ||
| 2. **Stage 2 (500ms)**: First data arrives, Users section hydrates | ||
| 3. **Stage 3 (900ms)**: Remaining data arrives, page fully loaded | ||
|
|
||
| ## Architecture Overview | ||
|
|
||
| Async Props uses NDJSON streaming between Rails and the Node renderer: | ||
|
|
||
|  | ||
|
|
||
| ### How It Works | ||
|
|
||
| 1. **Rails Controller** defines async props using `async_prop` blocks | ||
| 2. **NDJSON Stream** opens between Rails and Node renderer | ||
| 3. **Shell HTML** is sent to browser immediately | ||
| 4. **Data fetches** happen in parallel on the Rails side | ||
| 5. **Resolved props** stream to Node as they complete | ||
| 6. **React hydrates** each section as its data arrives | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ### 1. Define Async Props in Your Controller | ||
|
|
||
| ```ruby | ||
| class DashboardController < ApplicationController | ||
| def show | ||
| render_component( | ||
|
justin808 marked this conversation as resolved.
Outdated
|
||
| "Dashboard", | ||
| props: { | ||
| # Regular prop - available immediately | ||
| title: "My Dashboard", | ||
|
|
||
| # Async prop - streams when ready | ||
| users: async_prop { User.active.limit(10) }, | ||
|
|
||
| # Another async prop - fetches in parallel | ||
| posts: async_prop { Post.recent.limit(5) } | ||
| } | ||
| ) | ||
| end | ||
| end | ||
| ``` | ||
|
|
||
| ### 2. Use Suspense in Your Component | ||
|
|
||
| ```tsx | ||
| import React, { Suspense } from 'react'; | ||
|
|
||
| function Dashboard({ title, users, posts }) { | ||
| return ( | ||
| <div> | ||
| <h1>{title}</h1> | ||
|
|
||
| <Suspense fallback={<UsersSkeleton />}> | ||
| <UsersList users={users} /> | ||
| </Suspense> | ||
|
|
||
| <Suspense fallback={<PostsSkeleton />}> | ||
| <PostsList posts={posts} /> | ||
| </Suspense> | ||
| </div> | ||
| ); | ||
| } | ||
| ``` | ||
|
|
||
| ### 3. That's It! | ||
|
|
||
| The shell with skeleton loaders renders immediately. As each async prop resolves, React hydrates that section automatically. | ||
|
|
||
| ## When to Use Async Props | ||
|
|
||
| **Use Async Props when:** | ||
| - You have slow database queries or API calls | ||
| - Multiple independent data sources | ||
| - Pages with distinct loading sections | ||
| - SEO is important (full SSR, not client-side fetch) | ||
|
|
||
| **Consider alternatives when:** | ||
| - Data fetches are already fast (<100ms) | ||
| - Single data source with no parallelization opportunity | ||
| - Static pages with no dynamic data | ||
|
|
||
| ## Learn More | ||
|
|
||
| - [How Async Props Works](./how-it-works.md) - Deep dive into the streaming architecture | ||
| - [API Reference](./api-reference.md) - Complete configuration options | ||
| - [Advanced Usage](./advanced-usage.md) - Error handling, caching, and optimization | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Async Props is a React on Rails Pro feature requiring the Node renderer, but this documentation lives in
docs/async-props/(alongside OSS docs) rather thandocs/pro/. This could confuse OSS users who try to use this feature.Consider either:
docs/pro/async-props/