Skip to content
Open
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
2579c5c
upload assets in a separate request when needed
AbanoubGhadban Jun 30, 2025
a8fcd81
add ndjson end point to accept the rendering request in chunks
AbanoubGhadban Aug 10, 2025
33099d3
Implement Incremental Render Request Manager and Bundle Validation
AbanoubGhadban Aug 11, 2025
f1be9e9
WIP: handle errors happen during incremental rendering
AbanoubGhadban Aug 11, 2025
082c706
handle errors happen at the InrecementalRequestManager
AbanoubGhadban Aug 13, 2025
5bb915d
replace pending operations with content buffer
AbanoubGhadban Aug 13, 2025
735f117
Refactor incremental rendering to use a new function stream handler
AbanoubGhadban Aug 14, 2025
a7bf6c1
Enhance error handling in incremental rendering stream
AbanoubGhadban Aug 14, 2025
f7ca0d0
Refactor incremental render tests for improved readability and mainta…
AbanoubGhadban Aug 14, 2025
7b78507
create a test to test the streaming from server to client
AbanoubGhadban Aug 15, 2025
53960f5
Refactor incremental render tests to use custom waitFor function
AbanoubGhadban Aug 15, 2025
7093abf
Enhance incremental render tests with helper functions for setup and …
AbanoubGhadban Aug 15, 2025
5b943c1
Remove unnecessary console logs from worker and test files
AbanoubGhadban Aug 15, 2025
4ba8ca1
Refactor incremental render tests to use jest mock functions for sink…
AbanoubGhadban Aug 15, 2025
a3d81b3
add echo server test and enhance error reporting in waitFor function
AbanoubGhadban Aug 15, 2025
d511815
Refactor incremental render request handling and improve error manage…
AbanoubGhadban Aug 18, 2025
57ccd28
Refactor request handling by consolidating prechecks
AbanoubGhadban Aug 19, 2025
cb18b79
make asset-exists endpoint check authentication only
AbanoubGhadban Aug 20, 2025
e08182c
linting
AbanoubGhadban Aug 20, 2025
78d4ecf
Enhance asset upload handling to support bundles
AbanoubGhadban Aug 20, 2025
a771923
Enhance tests for asset upload handling
AbanoubGhadban Aug 20, 2025
cbb2c8f
Add test for asset upload with bundles in hash directories
AbanoubGhadban Aug 20, 2025
f35895b
Add incremental render endpoint tests
AbanoubGhadban Aug 21, 2025
2d52b7d
Refactor and enhance incremental render endpoint tests
AbanoubGhadban Aug 21, 2025
ba44313
make buildVM returns the built vm
AbanoubGhadban Sep 5, 2025
9cb5808
Refactor VM handling and introduce ExecutionContext
AbanoubGhadban Sep 5, 2025
c83721a
Fix runOnOtherBundle function parameters and improve global context h…
AbanoubGhadban Sep 9, 2025
a05b20a
Refactor incremental render handling and improve error management
AbanoubGhadban Sep 9, 2025
6a61dce
Enhance incremental render functionality and improve test coverage
AbanoubGhadban Sep 9, 2025
8dc3860
tmp
AbanoubGhadban Oct 22, 2025
0ca0084
Fix incremental render tests (#2032)
AbanoubGhadban Nov 16, 2025
865c415
Add AsyncPropManager to react-on-rails-pro package (#2049)
AbanoubGhadban Nov 19, 2025
ae419f4
Refactor generateRSCPayload from global to parameter (#2061)
AbanoubGhadban Nov 20, 2025
7ba75a2
Refactor authentication and protocol version handling to use request …
AbanoubGhadban Nov 24, 2025
468da50
Add support for incremental rendering at ruby side (#2076)
AbanoubGhadban Nov 24, 2025
3175785
Fix HTTPX streaming compatibility with stream_bidi plugin (#2251)
AbanoubGhadban Dec 28, 2025
253aedc
Enhance incremental rendering with async props management and streami…
AbanoubGhadban Dec 28, 2025
7891091
Add logging for JSON parsing and update chunk processing errors in in…
AbanoubGhadban Dec 28, 2025
1a3fce6
Fix AsyncPropsManager resolved flag and onRequestClosedUpdateChunk type
AbanoubGhadban Dec 29, 2025
002297b
Remove redundant logging in handleIncrementalRenderStream
AbanoubGhadban Dec 29, 2025
bba6006
Improve code quality in vm.ts buildVM function
AbanoubGhadban Dec 29, 2025
efbef62
Consolidate duplicate size limit constants
AbanoubGhadban Dec 29, 2025
b0c9de1
Refactor line size limit constant in handleIncrementalRenderStream tests
AbanoubGhadban Dec 30, 2025
7196322
Add Async Props documentation with SVG diagrams
AbanoubGhadban Dec 30, 2025
a026899
Add animated SVG diagrams for Async Props documentation
AbanoubGhadban Dec 30, 2025
529fe03
Add additional animated SVG diagrams for Async Props documentation
AbanoubGhadban Dec 30, 2025
7d21f03
feat: Implement async props with incremental rendering for React Serv…
AbanoubGhadban Dec 31, 2025
f10b628
Fix async props race conditions (#2297)
AbanoubGhadban Jan 31, 2026
da37b46
Add script to publish built JS packages to dist repo (#2767)
AbanoubGhadban Mar 19, 2026
50762d7
Merge origin/main into jg-codex/conflict-resolve-2265 to keep async p…
justin808 Mar 27, 2026
6551d00
Merge remote-tracking branch 'origin/main' into jg-codex/conflict-res…
justin808 Mar 27, 2026
42b8ad0
Merge upcoming-v16.3.0 into async props branch
justin808 Mar 27, 2026
6e29f81
Fix helper spacing after async props merge
justin808 Mar 27, 2026
ecdde38
Align renderer tests with execution context refactor
justin808 Mar 28, 2026
54164cf
fix: harden release confirmation prompt
justin808 Mar 28, 2026
9192c08
docs: clarify async props and upload protocol
justin808 Mar 28, 2026
e49af10
Fix async-props docs and bundle timestamp validation
justin808 Mar 28, 2026
cee0b02
Exclude flaky GitHub links from lychee
justin808 Mar 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions docs/async-props/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Async Props: Streaming Server-Side Rendering
Copy link
Copy Markdown
Contributor

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 than docs/pro/. This could confuse OSS users who try to use this feature.

Consider either:

  • Moving to docs/pro/async-props/
  • Adding a prominent Pro-only notice at the top: "⚠️ This feature requires React on Rails Pro."


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:

![Traditional SSR vs Streaming SSR](./images/traditional-vs-streaming-ssr.svg)

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:

![Timeline Comparison](./images/timeline-comparison.svg)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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:

![Progressive Loading Sequence](./images/progressive-loading-sequence.svg)

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:

![Architecture Flow](./images/architecture-flow.svg)

### 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(
Comment thread
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
Loading
Loading