react_on_rails_pro 16.2.0.beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.controlplane/Dockerfile +49 -0
  3. data/.controlplane/controlplane.yml +22 -0
  4. data/.controlplane/gvc.yml +25 -0
  5. data/.controlplane/postgres.yml +33 -0
  6. data/.controlplane/rails.yml +49 -0
  7. data/.controlplane/redis.yml +18 -0
  8. data/.gitignore +77 -0
  9. data/.prettierignore +12 -0
  10. data/.prettierrc +19 -0
  11. data/.rspec +2 -0
  12. data/.rubocop.yml +120 -0
  13. data/.scss-lint.yml +205 -0
  14. data/CHANGELOG.md +570 -0
  15. data/CI_SETUP.md +502 -0
  16. data/CONTRIBUTING.md +376 -0
  17. data/Dockerfile +63 -0
  18. data/Gemfile +8 -0
  19. data/Gemfile.development_dependencies +74 -0
  20. data/Gemfile.loader +32 -0
  21. data/Gemfile.lock +527 -0
  22. data/LICENSE +98 -0
  23. data/LICENSE_SETUP.md +272 -0
  24. data/README.md +577 -0
  25. data/Rakefile +13 -0
  26. data/app/controllers/react_on_rails_pro/rsc_payload_controller.rb +7 -0
  27. data/app/helpers/react_on_rails_pro_helper.rb +360 -0
  28. data/app/views/react_on_rails_pro/rsc_payload.html.erb +1 -0
  29. data/babel.config.js +4 -0
  30. data/docs/bundle-caching.md +205 -0
  31. data/docs/caching.md +234 -0
  32. data/docs/code-splitting-loadable-components.md +313 -0
  33. data/docs/code-splitting.md +349 -0
  34. data/docs/configuration.md +165 -0
  35. data/docs/contributors-info/onboarding-customers.md +6 -0
  36. data/docs/contributors-info/releasing.md +40 -0
  37. data/docs/contributors-info/style.md +33 -0
  38. data/docs/home-pro.md +146 -0
  39. data/docs/installation.md +203 -0
  40. data/docs/js-memory-leaks.md +22 -0
  41. data/docs/node-renderer/basics.md +92 -0
  42. data/docs/node-renderer/debugging.md +38 -0
  43. data/docs/node-renderer/error-reporting-and-tracing.md +160 -0
  44. data/docs/node-renderer/heroku.md +102 -0
  45. data/docs/node-renderer/js-configuration.md +91 -0
  46. data/docs/node-renderer/troubleshooting.md +5 -0
  47. data/docs/profiling-server-side-rendering-code.md +179 -0
  48. data/docs/react-server-components/add-streaming-and-interactivity.md +190 -0
  49. data/docs/react-server-components/create-without-ssr.md +448 -0
  50. data/docs/react-server-components/glossary.md +102 -0
  51. data/docs/react-server-components/how-react-server-components-work.md +243 -0
  52. data/docs/react-server-components/inside-client-components.md +332 -0
  53. data/docs/react-server-components/purpose-and-benefits.md +243 -0
  54. data/docs/react-server-components/rendering-flow.md +86 -0
  55. data/docs/react-server-components/selective-hydration-in-streamed-components.md +75 -0
  56. data/docs/react-server-components/server-side-rendering.md +72 -0
  57. data/docs/react-server-components/tutorial.md +19 -0
  58. data/docs/release-notes/4.0.md +94 -0
  59. data/docs/release-notes/v4-react-server-components.md +66 -0
  60. data/docs/ruby-api.md +11 -0
  61. data/docs/streaming-server-rendering.md +210 -0
  62. data/docs/troubleshooting.md +24 -0
  63. data/docs/updating.md +219 -0
  64. data/eslint.config.mjs +220 -0
  65. data/lib/react_on_rails_pro/assets_precompile.rb +230 -0
  66. data/lib/react_on_rails_pro/cache.rb +88 -0
  67. data/lib/react_on_rails_pro/concerns/rsc_payload_renderer.rb +38 -0
  68. data/lib/react_on_rails_pro/concerns/stream.rb +103 -0
  69. data/lib/react_on_rails_pro/configuration.rb +228 -0
  70. data/lib/react_on_rails_pro/constants.rb +8 -0
  71. data/lib/react_on_rails_pro/engine.rb +24 -0
  72. data/lib/react_on_rails_pro/error.rb +14 -0
  73. data/lib/react_on_rails_pro/license_public_key.rb +30 -0
  74. data/lib/react_on_rails_pro/license_validator.rb +188 -0
  75. data/lib/react_on_rails_pro/prepare_node_renderer_bundles.rb +40 -0
  76. data/lib/react_on_rails_pro/rendering_error.rb +5 -0
  77. data/lib/react_on_rails_pro/request.rb +318 -0
  78. data/lib/react_on_rails_pro/routes.rb +13 -0
  79. data/lib/react_on_rails_pro/server_rendering_js_code.rb +102 -0
  80. data/lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb +133 -0
  81. data/lib/react_on_rails_pro/server_rendering_pool/pro_rendering.rb +117 -0
  82. data/lib/react_on_rails_pro/stream_cache.rb +61 -0
  83. data/lib/react_on_rails_pro/stream_request.rb +170 -0
  84. data/lib/react_on_rails_pro/utils.rb +222 -0
  85. data/lib/react_on_rails_pro/v8_log_processor.rb +50 -0
  86. data/lib/react_on_rails_pro/version.rb +6 -0
  87. data/lib/react_on_rails_pro.rb +23 -0
  88. data/package-scripts.yml +109 -0
  89. data/package.json +159 -0
  90. data/rakelib/dummy_apps.rake +22 -0
  91. data/rakelib/lint.rake +32 -0
  92. data/rakelib/public_key_management.rake +155 -0
  93. data/rakelib/rbs.rake +47 -0
  94. data/rakelib/run_rspec.rake +81 -0
  95. data/rakelib/task_helpers.rb +45 -0
  96. data/rakelib/yard.rake +20 -0
  97. data/react_on_rails_pro.gemspec +47 -0
  98. data/readme-gen-docs.md +1 -0
  99. data/script/bootstrap +33 -0
  100. data/script/preinstall.js +31 -0
  101. data/script/setup +23 -0
  102. data/script/test +38 -0
  103. data/sig/react_on_rails_pro/cache.rbs +13 -0
  104. data/sig/react_on_rails_pro/configuration.rbs +100 -0
  105. data/sig/react_on_rails_pro/error.rbs +4 -0
  106. data/sig/react_on_rails_pro/utils.rbs +7 -0
  107. data/sig/react_on_rails_pro.rbs +5 -0
  108. data/yarn.lock +7599 -0
  109. metadata +319 -0
@@ -0,0 +1,243 @@
1
+ # React Server Components & Streaming in React on Rails Pro
2
+
3
+ ## Why RSC with Streaming?
4
+
5
+ ### Waterfall Loading Pattern Benefits
6
+ React Server Components with streaming is beneficial for most applications, but it's especially powerful for applications with waterfall loading patterns where data dependencies chain together. For example, when you need to load a user profile before loading their posts, or fetch categories before products. Here's why:
7
+
8
+ ### How RSC Fixes Waterfall Server Rendering Issues:
9
+
10
+ When a user visits the page, they'll experience the following sequence:
11
+
12
+ 1. The initial HTML shell is sent immediately, including:
13
+ - The page layout
14
+ - Any static content (like the `<h1>` and footer)
15
+ - Placeholder content for the React component (typically a loading state)
16
+
17
+ 2. Selective Hydration:
18
+ - Client components hydrate independently as their code chunks load
19
+ - Multiple components can hydrate in parallel
20
+ - User interactions automatically prioritize hydration of interacted components
21
+ - No waiting for full page JavaScript or other components to load
22
+ - Each component becomes interactive immediately after its own hydration
23
+
24
+ ### Bundle Size Benefits
25
+
26
+ React Server Components significantly reduce client-side JavaScript by:
27
+
28
+ 1. **Server-Only Code Elimination:**
29
+ - Dependencies used only in server components never ship to the client
30
+ - Database queries, API calls, and their libraries stay server-side
31
+ - Heavy data processing utilities remain on the server
32
+ - Server-only NPM packages don't impact client bundle
33
+
34
+ 2. **Concrete Examples:**
35
+ - Routing logic can stay server-side
36
+ - Data fetching libraries (like React Query) are often unnecessary
37
+ - Large formatting libraries (e.g., date-fns, numeral) can be server-only
38
+ - Image processing utilities stay on server
39
+ - Markdown parsers run server-side only
40
+ - Heavy validation libraries remain server-side
41
+
42
+ For example, a typical dashboard might see:
43
+ ```jsx
44
+ // Before: All code shipped to client
45
+ import { format } from 'date-fns'; // ~30KB
46
+ import { marked } from 'marked'; // ~35KB
47
+ import numeral from 'numeral'; // ~25KB
48
+
49
+ // After: With RSC, these imports stay server-side
50
+ // Client bundle reduced by ~90KB
51
+ ```
52
+
53
+ ### [Selective Hydration](https://github.com/reactwg/react-18/discussions/37) Benefits
54
+
55
+ React's selective hydration is a powerful feature that significantly improves page interactivity by:
56
+
57
+ 1. **Independent Component Hydration**
58
+ - Each client component hydrates independently as soon as its code loads
59
+ - No waiting for the entire page's JavaScript to load and execute
60
+ - Components become interactive progressively rather than all at once
61
+
62
+ 2. **Interaction-Based Prioritization**
63
+ - React automatically prioritizes hydrating components that users try to interact with
64
+ - If a user clicks a button before hydration, that component gets priority
65
+ - Other components continue hydrating in the background
66
+ - Better perceived performance as users can interact sooner
67
+
68
+ 3. **Parallel Processing**
69
+ - Multiple components can hydrate simultaneously
70
+ - Network requests for component code happen in parallel
71
+ - CPU processing for hydration is interleaved efficiently
72
+ - Maximizes browser resources for faster overall interactivity
73
+
74
+ For example, in a typical page layout:
75
+
76
+ ```jsx
77
+ <Layout>
78
+ <Suspense fallback={<NavSkeleton />}>
79
+ <Navigation /> {/* Client component */}
80
+ </Suspense>
81
+ <Suspense fallback={<MainSkeleton />}>
82
+ <MainContent /> {/* Client component */}
83
+ <Comments /> {/* Client component */}
84
+ </Suspense>
85
+ <Suspense fallback={<SidebarSkeleton />}>
86
+ <Sidebar /> {/* Client component */}
87
+ </Suspense>
88
+ </Layout>
89
+ ```
90
+
91
+ With selective hydration:
92
+ - Navigation could become interactive while Comments are still loading
93
+ - If user tries to click a Sidebar button, it gets priority hydration
94
+ - Each component hydrates independently when ready
95
+ - No waiting for all components to load before any become interactive
96
+
97
+ This approach significantly improves the user experience by:
98
+ - Reducing Time to Interactive (TTI) for important components
99
+ - Providing faster response to user interactions
100
+ - Maintaining smooth performance even on slower devices or networks
101
+ - Eliminating the "all or nothing" hydration approach of traditional SSR
102
+
103
+ For a deeper dive into selective hydration, see our [Selective Hydration in Streamed Components](./selective-hydration-in-streamed-components.md) guide.
104
+
105
+
106
+ ### Comparison with Other Approaches:
107
+
108
+ 1. **Full Server Rendering:**
109
+ - ❌ Delays First Byte until entire page is rendered
110
+ - ❌ All-or-nothing approach to hydration
111
+ - ❌ Must wait for all JavaScript before any interactivity
112
+ - ✅ Good SEO
113
+ - ✅ Complete initial HTML
114
+
115
+ 2. **Client-side Lazy Loading:**
116
+ - ❌ Empty initial HTML for lazy components
117
+ - ❌ Must wait for hydration to load
118
+ - ❌ Poor SEO for lazy content
119
+ - ❌ No prioritization of component hydration
120
+ - ❌ Initial page must be loaded and hydrated before loading lazy components
121
+ - ✅ Reduces initial bundle size
122
+
123
+ 3. **RSC with Streaming:**
124
+ - ✅ Immediate First Byte
125
+ - ✅ Progressive HTML streaming
126
+ - ✅ SEO-friendly for all content
127
+ - ✅ No hydration waiting for server components
128
+ - ✅ Selective client hydration
129
+
130
+ ## Migration Guide
131
+
132
+ ### 1. Enable RSC Support
133
+
134
+ Add to your Rails initializer, it makes the magic happen 🪄:
135
+ ```ruby
136
+ # config/initializers/react_on_rails_pro.rb
137
+ ReactOnRailsPro.configure do |config|
138
+ config.enable_rsc_support = true
139
+ end
140
+ ```
141
+
142
+ ### 2. Update Webpack Configuration
143
+
144
+ Create RSC bundle and make it use the RSC loader:
145
+ ```javascript
146
+ // config/webpack/rscWebpackConfig.mjs
147
+ const rscConfig = serverWebpackConfig();
148
+
149
+ // Configure RSC entry point
150
+ rscConfig.entry = {
151
+ 'rsc-bundle': rscConfig.entry['server-bundle']
152
+ };
153
+
154
+ // Add RSC loader
155
+ rules.forEach((rule) => {
156
+ if (Array.isArray(rule.use)) {
157
+ const babelLoader = extractLoader(rule, 'babel-loader');
158
+ if (babelLoader) {
159
+ rule.use.push({
160
+ loader: 'react-on-rails-rsc/WebpackLoader',
161
+ });
162
+ }
163
+ }
164
+ });
165
+ ```
166
+
167
+ ### 3. Gradual Component Migration
168
+
169
+ #### 1. Mark Entry Points as Client Components
170
+
171
+ Adding the `'use client'` directive to entry points maintains existing functionality while allowing for incremental migration of individual components to server components.
172
+ This approach ensures a smooth transition without disrupting the application's current behavior.
173
+
174
+ ```jsx
175
+ // app/components/App.jsx
176
+ 'use client';
177
+
178
+ export default function App() {
179
+ // Your existing component code
180
+ }
181
+ ```
182
+
183
+ #### 2. Identify Server Component Candidates:
184
+ - Data fetching components
185
+ - Non-interactive UI
186
+ - Static content sections
187
+ - Layout components
188
+
189
+ #### 3. Progressive Migration Pattern (Top-Down Approach):
190
+
191
+ Start by converting layout and container components at the top of your component tree to server components, moving any interactive logic down to child components. This "top-down" approach maximizes the benefits of RSC.
192
+
193
+ ```jsx
194
+ // app/components/Layout.jsx
195
+ // Remove 'use client' - This becomes a server component
196
+ // Move any state/effects to child components first
197
+ export default function Layout({ children }) {
198
+ return (
199
+ <div>
200
+ <Header /> {/* Server component */}
201
+ <Sidebar /> {/* Server component */}
202
+ <main>
203
+ {children} {/* Interactive components like InteractiveWidget remain nested inside */}
204
+ </main>
205
+ <Footer /> {/* Server component */}
206
+ </div>
207
+ );
208
+ }
209
+ ```
210
+
211
+ ```jsx
212
+ // app/components/InteractiveWidget.jsx
213
+ 'use client'; // Keep client directive for interactive components
214
+
215
+ export default function InteractiveWidget() {
216
+ const [state, setState] = useState();
217
+ // Interactive component logic
218
+ }
219
+ ```
220
+
221
+ #### 4. Convert Lazy-Loaded Entry Points:
222
+
223
+ ```jsx
224
+ // app/components/LazyLoadedSection.jsx
225
+ // Remove lazy loading wrapper
226
+ // Convert to async server component
227
+ async function LazyLoadedSection() {
228
+ const data = await fetchData();
229
+ return (
230
+ <div>
231
+ <ServerContent data={data} />
232
+ <ClientInteraction /> {/* Keeps 'use client' */}
233
+ </div>
234
+ );
235
+ }
236
+ ```
237
+
238
+ This migration approach allows you to:
239
+ - Maintain existing functionality while migrating
240
+ - Incrementally improve performance
241
+ - Test changes in isolation
242
+ - Keep interactive components working as before
243
+ - Eliminate client-side lazy loading overhead
@@ -0,0 +1,86 @@
1
+ # React Server Components Rendering Flow
2
+
3
+ This document explains the rendering flow of React Server Components (RSC) in React on Rails Pro.
4
+
5
+ ## Types of Bundles
6
+
7
+ In a React Server Components project, there are three distinct types of bundles:
8
+
9
+ ### RSC Bundle (rsc-bundle.js)
10
+ - Contains only server components and references to client components
11
+ - Generated using the RSC Webpack Loader which transforms client components into references
12
+ - Used specifically for generating RSC payloads
13
+ - Configured with `react-server` condition to enable RSC-specific code paths that tell the runtime that this bundle is used for RSC payload generation.
14
+
15
+ ### Server Bundle (server-bundle.js)
16
+ - Contains both server and client components in their full form
17
+ - Used for traditional server-side rendering (SSR)
18
+ - Enables HTML generation of any components
19
+ - Does not transform client components into references
20
+
21
+ ### Client Bundle
22
+ - Split into multiple chunks based on client components
23
+ - Each file with `'use client'` directive becomes an entry point
24
+ - Code splitting occurs automatically for client components
25
+ - Chunks are loaded on-demand during client component hydration
26
+
27
+ ## React Server Component Rendering Flow
28
+
29
+ When a request is made to a page using React Server Components, the following optimized sequence occurs:
30
+
31
+ 1. Initial Request Processing:
32
+ - The `stream_react_component` helper is called in the view
33
+ - Makes a request to the node renderer
34
+ - Server bundle's rendering function calls `generateRSCPayload` with the component name and props
35
+ - This executes the component rendering in the RSC bundle
36
+ - RSC bundle generates the payload containing server component data and client component references
37
+ - The payload is returned to the server bundle
38
+
39
+ 2. Server-Side Rendering with RSC Payload:
40
+ - The server bundle uses the RSC payload to generate HTML for server components using `RSCServerRoot`
41
+ - `RSCServerRoot` splits the RSC payload stream into two parts:
42
+ - One stream for rendering server components as HTML
43
+ - Another stream for embedding the RSC payload in the response
44
+ - `RSCPayloadContainer` component embeds the RSC payload within the HTML response
45
+ - HTML and embedded RSC payload are streamed together to the client
46
+
47
+ 3. Client Hydration:
48
+ - Browser displays HTML immediately
49
+ - React runtime uses the embedded RSC payload for hydration
50
+ - Client components are hydrated progressively without requiring a separate HTTP request
51
+
52
+ This approach offers significant advantages:
53
+ - Eliminates double rendering of server components
54
+ - Reduces HTTP requests by embedding the RSC payload within the initial HTML response
55
+ - Provides faster interactivity through streamlined rendering and hydration
56
+
57
+ ```mermaid
58
+ sequenceDiagram
59
+ participant Browser
60
+ participant RailsView
61
+ participant NodeRenderer
62
+ participant RSCBundle
63
+ participant ServerBundle
64
+
65
+ Note over Browser,ServerBundle: 1. Initial Request
66
+ Browser->>RailsView: Request page
67
+ RailsView->>NodeRenderer: stream_react_component
68
+ NodeRenderer->>ServerBundle: Execute rendering request
69
+ ServerBundle->>RSCBundle: generateRSCPayload(component, props)
70
+ RSCBundle-->>ServerBundle: RSC payload with:<br/>- Server components<br/>- Client component refs
71
+ ServerBundle-->>NodeRenderer: Generate HTML using RSC payload
72
+
73
+ Note over Browser,ServerBundle: 2. Single Response
74
+ NodeRenderer-->>Browser: Stream HTML with embedded RSC payload
75
+
76
+ Note over Browser: 3. Client Hydration
77
+ Browser->>Browser: Process embedded RSC payload
78
+ loop For each client component
79
+ Browser->>Browser: Fetch component chunk
80
+ Browser->>Browser: Hydrate component
81
+ end
82
+ ```
83
+
84
+ ## Next Steps
85
+
86
+ To learn more about how to render React Server Components inside client components, see [React Server Components Inside Client Components](./inside-client-components.md).
@@ -0,0 +1,75 @@
1
+ # Selective Hydration in React Server Components
2
+
3
+ ## Introduction
4
+
5
+ React has introduced a powerful enhancement to server-side rendering through streaming and React Server Components - selective hydration. This feature fundamentally changes how pages become interactive in the browser.
6
+
7
+ Previously, with traditional server-side rendering, the browser had to wait for the entire page to load and all JavaScript to execute before any part could become interactive. This created a noticeable delay in page interactivity, especially for larger applications.
8
+
9
+ With selective hydration, React can now hydrate different parts of the page independently and asynchronously. Key benefits include:
10
+
11
+ - Components can become interactive as soon as their code and data are available, without waiting for the entire page
12
+ - React automatically prioritizes hydrating components that users are trying to interact with
13
+
14
+ This approach significantly improves both perceived and actual performance by making the most relevant parts interactive first.
15
+
16
+ ## Try Selective Hydration with React Server Component Page
17
+
18
+ Let's try selective hydration with the React Server Component Page we created in the [SSR React Server Components](./server-side-rendering.md).
19
+
20
+ Let's add a component that is very slow to load into the page.
21
+
22
+ ```jsx
23
+ const LongWaitingComponent = async () => {
24
+ await new Promise((resolve) => setTimeout(resolve, 5000));
25
+ return <div>Long waiting component</div>;
26
+ };
27
+ ```
28
+
29
+ Add the component to the page.
30
+
31
+ ```jsx
32
+ // app/javascript/packs/components/ReactServerComponentPage.jsx
33
+ const ReactServerComponentPage = () => {
34
+ return (
35
+ <div>
36
+ <ReactServerComponent />
37
+ <Suspense fallback={<div>Loading The Long Waiting Component...</div>}>
38
+ <LongWaitingComponent />
39
+ </Suspense>
40
+ <Suspense fallback={<div>Loading...</div>}>
41
+ <Posts />
42
+ </Suspense>
43
+ </div>
44
+ );
45
+ };
46
+ ```
47
+
48
+ ## Fixing Compatibility Issue that Blocks Hydration
49
+
50
+ When you run the page, you should see "Loading The Long Waiting Component..." in the browser for 5 seconds. Then, the component is rendered and the page becomes interactive.
51
+
52
+ You can notice that the page doesn't become interactive until the Long Waiting Component is rendered, which contradicts what we discussed about selective hydration.
53
+
54
+ This happens because React on Rails by default adds the scripts that hydrate components as `defer` scripts, which only execute after the whole page is loaded. Since the page is being streamed, this means the scripts won't run until all components have been server-side rendered and streamed to the browser.
55
+
56
+ This default behavior was kept for backward compatibility, as there were previously race conditions that could occur when using `async` scripts before the page fully loaded. However, these race conditions have been fixed in the latest React on Rails release.
57
+
58
+ To enable true selective hydration, we need to configure React on Rails to load scripts as `async` scripts by setting `generated_component_packs_loading_strategy: :async` in the initializer:
59
+
60
+ ```ruby
61
+ # config/initializers/react_on_rails.rb
62
+ ReactOnRails.configure do |config|
63
+ config.generated_component_packs_loading_strategy = :async
64
+ end
65
+ ```
66
+
67
+ Now, when you run the page, you can see that while the Long Waiting Component is loading ⏳, the other components are interactive ✨🖱️
68
+
69
+ ## Conclusion
70
+
71
+ Selective hydration is a powerful feature that allows React to become interactive as soon as its code and data are available, without waiting for the entire page to load. This approach significantly improves both perceived and actual performance by making the most relevant parts interactive first.
72
+
73
+ ## Next Steps
74
+
75
+ Now that you understand how to use selective hydration in React Server Components, you can proceed to the next article: [How React Server Components Work](how-react-server-components-work.md) to learn about the technical details and underlying mechanisms of React Server Components.
@@ -0,0 +1,72 @@
1
+ # SSR React Server Components
2
+
3
+ Before reading this document, please read:
4
+ 1. [Create React Server Component without SSR](./create-without-ssr.md)
5
+ 2. [Add Streaming and Interactivity to RSC Page](./add-streaming-and-interactivity.md)
6
+
7
+ These documents provide essential background on React Server Components and how they work without Server Side Rendering (SSR).
8
+
9
+ ## Update the React Server Component Page
10
+
11
+ Let's make React on Rails server-side render the React Server Component Page we created in the previous articles.
12
+
13
+ Update the `react_server_component_without_ssr.html.erb` view to pass `prerender: true` to the `react_component` helper.
14
+
15
+ ```erb
16
+ <%= react_component("ReactServerComponentPage",
17
+ prerender: true,
18
+ trace: true,
19
+ id: "ReactServerComponentPage-react-component-0") %>
20
+ ```
21
+
22
+ Now, when you visit the page, you should see part of the React Server Component page rendered in the browser. Then, we get the error:
23
+
24
+ ```
25
+ The server did not finish this Suspense boundary: The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server
26
+ ```
27
+
28
+ This error occurs because the `react_component` helper uses React's `renderToString` function, which renders the React page synchronously in a single pass. This approach isn't suitable for React Server Components, which can contain asynchronous operations and need progressive streaming of content.
29
+
30
+ Instead, we need to use the streaming capabilities provided by React on Rails Pro, as detailed in the [streaming server rendering documentation](../streaming-server-rendering.md). These helpers internally use React's `renderToPipeableStream` API, which supports:
31
+
32
+ 1. Server-side rendering of async components
33
+ 2. Progressive streaming of HTML chunks to the client as components finish rendering
34
+ 3. Incremental hydration, where each component can be hydrated independently as it loads, rather than waiting for the entire application
35
+
36
+ To enable streaming SSR for React Server Components, we need to:
37
+
38
+ 1. Create a new view called `react_server_component_ssr.html.erb` with the following content:
39
+
40
+ ```erb
41
+ # app/views/pages/react_server_component_ssr.html.erb
42
+ <%= stream_react_component("ReactServerComponentPage",
43
+ id: "ReactServerComponentPage-react-component-0") %>
44
+
45
+ <h1>React Server Component with SSR</h1>
46
+ ```
47
+
48
+ 2. Ensure our controller includes `ReactOnRailsPro::Stream` and use the `stream_view_containing_react_components` helper to render the view:
49
+
50
+ ```ruby
51
+ # app/controllers/pages_controller.rb
52
+ class PagesController < ApplicationController
53
+ include ReactOnRailsPro::Stream
54
+
55
+ def react_server_component_ssr
56
+ stream_view_containing_react_components(template: "pages/react_server_component_ssr")
57
+ end
58
+ end
59
+ ```
60
+
61
+ 3. Add the route to `config/routes.rb`:
62
+
63
+ ```ruby
64
+ # config/routes.rb
65
+ get "/react_server_component_ssr", to: "pages#react_server_component_ssr"
66
+ ```
67
+
68
+ Now, when you visit the page, you should see the entire React Server Component page rendered in the browser. And if you viewed the page source, you should see the HTML being streamed to the browser.
69
+
70
+ ## Next Steps
71
+
72
+ Now that you understand how to enable server-side rendering (SSR) for your React Server Components, you can proceed to the next article: [Selective Hydration in Streamed Components](selective-hydration-in-streamed-components.md) to learn about React's selective hydration feature and how it improves page interactivity.
@@ -0,0 +1,19 @@
1
+ # React Server Components Tutorial
2
+
3
+ This tutorial will guide you through learning [React Server Components (RSC)](https://react.dev/reference/rsc/server-components) with React on Rails Pro, from basic concepts to advanced features. The tutorial is divided into several parts that build upon each other:
4
+
5
+ 1. [Create React Server Component without SSR](create-without-ssr.md) - Learn the fundamentals of React Server Components by creating a basic RSC page without server-side rendering.
6
+
7
+ 2. [Add Streaming and Interactivity to RSC Page](add-streaming-and-interactivity.md) - Enhance your RSC page with streaming capabilities and client-side interactivity using Suspense and client components.
8
+
9
+ 3. [Server-Side Rendering for React Server Components](server-side-rendering.md) - Add SSR to your React Server Components for improved initial page load performance.
10
+
11
+ 4. [Selective Hydration in Streamed Components](selective-hydration-in-streamed-components.md) - Learn about React's selective hydration feature and how it improves page interactivity.
12
+
13
+ 5. [How React Server Components Work](how-react-server-components-work.md) - Dive deep into the technical details and underlying mechanisms of React Server Components.
14
+
15
+ 6. [React Server Components Rendering Flow](rendering-flow.md) - Understand the detailed rendering flow of RSC, including bundle types, current limitations, and future improvements.
16
+
17
+ 7. [React Server Components Inside Client Components](inside-client-components.md) - Learn how to render server components inside client components.
18
+
19
+ Each part of the tutorial builds on the concepts from previous sections, so it's recommended to follow them in order. Let's begin with creating your first React Server Component!
@@ -0,0 +1,94 @@
1
+ # 4.0 Release Notes
2
+
3
+ ## 🚀 Major New Features
4
+
5
+ ### React Server Components (RSC) - Full Production Support
6
+ React on Rails Pro now provides comprehensive support for React Server Components, enabling you to build the next generation of React applications:
7
+
8
+ - **Full RSC Integration**: Seamlessly use React Server Components in your Rails apps with zero configuration
9
+ - **Bundle Optimization**: Automatic client/server code splitting that significantly reduces client-side JavaScript
10
+ - **Server-Side Data Fetching**: Direct access to databases, APIs, and server resources from React components
11
+ - **Progressive Hydration**: Client components hydrate independently for optimal performance
12
+ - **RSC Payload Streaming**: Efficient streaming of component data with embedded payloads
13
+ - **Compatible with React Router**: [Use React Router with RSC](../react-server-components/inside-client-components.md)
14
+
15
+ See our [complete RSC tutorial](../react-server-components-tutorial.md) to get started.
16
+
17
+ ### Advanced Streaming Server Rendering
18
+ Building on React 19's streaming capabilities, React on Rails Pro delivers:
19
+
20
+ - **Progressive HTML Streaming**: Send page content as it becomes available
21
+ - **Suspense Boundary Support**: Handle async components with proper loading states
22
+ - **Selective Hydration**: Components become interactive as soon as they're ready
23
+ - **Error Boundary Handling**: Graceful error handling during streaming with configurable error raising
24
+ - **Async Console Log Replay**: Debug async server-side rendering with client-side console output
25
+
26
+ ### Enhanced Error Reporting & Tracing
27
+ Completely redesigned error reporting system with:
28
+
29
+ - **Custom Integration Support**: Integrate with any error reporting service (Sentry, Honeybadger, or custom)
30
+ - **Sentry SDK v8 Support**: Latest Sentry integration with improved performance
31
+ - **Flexible Configuration**: Configure error reporting according to your preferences
32
+ - **Enhanced Tracing**: Better visibility into rendering performance and issues
33
+
34
+ ## Performance Improvements
35
+
36
+ ### Node Renderer Architecture
37
+ - **Fastify 5 Integration**: Upgraded from Express to Fastify for significantly better performance
38
+ - **HTTP/2 Cleartext Communication**: Rails communicates with Node renderer over HTTP/2 instead of HTTP/1.1
39
+ - **HTTPX Client**: Replaced Net::HTTP with HTTPX for improved connection handling
40
+ - **Pino Logging**: Switched from Winston to Pino for better performance and Fastify compatibility
41
+
42
+ These changes provide:
43
+ - Better performance when Node renderer is deployed on the same machine as Rails
44
+ - Significantly improved performance when deployed in separate workloads
45
+ - Enhanced connection reuse and multiplexing capabilities
46
+ - Better error handling and process management
47
+
48
+
49
+ ### Changes Specific For RSC Rendering Optimization
50
+ - **Cross-Bundle Communication**: Components can now interact seamlessly across different bundles using the new `runOnOtherBundle` function, enabling advanced composition and modularization patterns.
51
+ - **Single-Pass Server Component Rendering**: Server components are rendered just once within the RSC bundle, then efficiently reused for both SSR and client hydration—eliminating redundant work and improving performance.
52
+ - **Reduced HTTP Requests**: RSC payloads are now embedded directly into the initial HTML response. No need to make an additional request to fetch the RSC payload.
53
+ - **Protocol v2.0 – Unified Bundle Management**: The new protocol allows simultaneous upload of both server and RSC bundles in a single request, supporting multiple bundle uploads and providing robust, flexible bundle management for complex applications.
54
+
55
+ ## Breaking Changes
56
+
57
+ ### Configuration Updates
58
+ - **Sentry/Honeybadger**: Remove old configuration options starting with `sentry` or `honeybadger`
59
+ - **Timer Polyfills**: `includeTimerPolyfills` is renamed to `stubTimers`
60
+ - **Environment Variables**: `RENDERER_STUB_TIMERS` instead of `INCLUDE_TIMER_POLYFILLS`
61
+ - **Error Reporting**: Follow the [Error Reporting and Tracing](../node-renderer/error-reporting-and-tracing.md) documentation for new setup
62
+
63
+ ### Dependency Requirements
64
+ - **Ruby 3+**: Dropped support for Ruby 2.7 (EOL)
65
+ - **React on Rails 15+**: Required for RSC and streaming features
66
+ - **Node 20+**: Strongly recommended (older versions require specific package.json resolutions)
67
+
68
+ ### Package.json Resolutions (for Node < 20)
69
+ If using older Node versions, add to your `package.json`:
70
+ ```json
71
+ "resolutions": {
72
+ "@fastify/formbody": "^7.4.0",
73
+ "@fastify/multipart": "^8.3.1",
74
+ "fastify": "^4.29.0"
75
+ }
76
+ ```
77
+
78
+ ## Getting Started
79
+
80
+ - **RSC Tutorial**: [Complete React Server Components Guide](../react-server-components-tutorial.md)
81
+ - **Streaming SSR**: [Streaming Server Rendering Documentation](../streaming-server-rendering.md)
82
+ - **Error Reporting**: [Error Reporting and Tracing Setup](../node-renderer/error-reporting-and-tracing.md)
83
+ - **Performance**: [Caching and Optimization Guide](../caching.md)
84
+
85
+ ## Support & Community
86
+
87
+ - **Documentation**: Comprehensive guides and tutorials available
88
+ - **Examples**: Working examples in the spec/dummy application
89
+ - **GitHub**: Active development and community support
90
+ - **Discussions**: Join the [React on Rails community](https://forum.shakacode.com/) for help and updates
91
+
92
+ ---
93
+
94
+ *React on Rails Pro 4.0 represents a major evolution in server-side React rendering, bringing React Server Components and advanced streaming to the Rails ecosystem with enterprise-grade performance and reliability.*
@@ -0,0 +1,66 @@
1
+ # React on Rails Pro: Introducing React Server Components & SSR Streaming
2
+
3
+ **Subject: 🚀 Revolutionary Performance Boost: React Server Components & SSR Streaming Now Available in React on Rails Pro**
4
+
5
+ ---
6
+
7
+ Dear Valued React on Rails Pro Client,
8
+
9
+ We're thrilled to announce a major update: React on Rails Pro now supports **React Server Components** and **Server‑Side Rendering (SSR) Streaming**. These features have driven significant performance gains in real‑world applications—here’s how they can transform yours.
10
+
11
+ ## 🎯 What This Means for Your Applications
12
+
13
+ * **Faster load times**
14
+ * **Smaller JavaScript bundles**
15
+ * **Better Core Web Vitals**
16
+ * **Improved SEO**
17
+ * **Smoother user interactions**
18
+
19
+ ## 🔥 React Server Components
20
+
21
+ Server Components execute on the server and stream HTML to the client—no extra JavaScript in your bundle. Real‑world results include:
22
+
23
+ * **62% reduction** in client‑side bundle size on productonboarding.com when migrating to RSC [[1]]
24
+ * **63% improvement** in Google Speed Index on the RSC version of the same site [[1]]
25
+ * **52% smaller** JavaScript codebase and Lighthouse scores rising from \~50 to 90+ on GeekyAnts.com [[2]]
26
+
27
+ ## 🌊 SSR Streaming
28
+
29
+ SSR Streaming sends HTML to the browser in chunks as it’s generated, enabling progressive rendering:
30
+
31
+ * **30% faster** full‑page load times at Hulu by combining streaming SSR with Server Components [[3]]
32
+ * Popular libraries like styled‑components v3.1.0 have introduced streaming SSR support as the next generation of React app rendering [[4]]
33
+
34
+ ## 📊 Core Web Vitals & TTI Improvements
35
+
36
+ * **60% faster** Time to Interactive on Meta’s developer portal after adopting RSC (from 3.5 s to \~1.4 s) [[5]]
37
+ * **45% quicker** First Contentful Paint in the same migration [[5]]
38
+ * **50% lower** server response time with Server Components [[5]]
39
+ * **15% improvement** in Core Web Vitals and **23% reduction** in Time to First Byte at Airbnb after RSC migration [[5]]
40
+
41
+ ---
42
+
43
+ Adopting these features in React on Rails Pro will help you deliver faster, leaner, and more SEO‑friendly applications with fewer client‑side resources.
44
+
45
+ **Ready to get started?**
46
+
47
+ 1. Update to the latest React on Rails Pro version
48
+ 2. Follow our [RSC & SSR Streaming migration guide](https://github.com/shakacode/react_on_rails_pro/blob/abanoubghadban/pro465/use-rsc-payload-to-render-server-components-on-server/docs/react-server-components-tutorial.md)
49
+
50
+ Let’s make your apps faster—together.
51
+
52
+ ---
53
+
54
+ ## 📚 References
55
+
56
+ 1. productonboarding.com experiment: 62% bundle reduction, 63% Speed Index gain ([frigade.com][1])
57
+ 2. GeekyAnts.com case study: 52% code reduction, Lighthouse 50→90+ ([geekyants.com][2])
58
+ 3. Hulu—30% faster full‑page loads with streaming SSR + RSC ([questlab.pro][3])
59
+ 4. styled‑components v3.1.0: introduced streaming SSR support as the next generation of React rendering. ([medium.com][4])
60
+ 5. QuestLab: Meta’s RSC migration—30% JS reduction, 60% faster TTI, 45% faster FCP, 50% lower server response ([questlab.pro][5])
61
+
62
+ [1]: https://frigade.com/blog/bundle-size-reduction-with-rsc-and-frigade
63
+ [2]: https://geekyants.com/en-gb/blog/boosting-performance-with-nextjs-and-react-server-components-a-geekyantscom-case-study
64
+ [3]: https://www.compilenrun.com/docs/framework/nextjs/nextjs-ecosystem/nextjs-case-studies/#case-study-3-hulus-streaming-platform
65
+ [4]: https://medium.com/styled-components/v3-1-0-such-perf-wow-many-streams-c45c434dbd03
66
+ [5]: https://questlab.pro/blog-posts/web-development/wd-pl-2024-articleId912i1h212818
data/docs/ruby-api.md ADDED
@@ -0,0 +1,11 @@
1
+ # Ruby API
2
+
3
+ Note: you will need access to our **private** React on Rails Pro repository to open the following links.
4
+
5
+ ## View Helpers
6
+
7
+ See the [app/helpers/react_on_rails_pro_helper.rb](https://github.com/shakacode/react_on_rails_pro/blob/master/app/helpers/react_on_rails_pro_helper.rb) source.
8
+
9
+ ## Utility Methods
10
+
11
+ See the [lib/react_on_rails_pro/utils.rb](https://github.com/shakacode/react_on_rails_pro/blob/master/lib/react_on_rails_pro/utils.rb) source.