Skip to content

Commit 4d09e13

Browse files
justin808claude
andcommitted
Add React Server Components with React on Rails Pro
Upgrade from react_on_rails to react_on_rails_pro gem (16.5.1) and corresponding npm packages. Add RSC infrastructure with a demo page at /server-components that showcases: - Server components using Node.js os module and lodash (never shipped to client) - Async data fetching with Suspense streaming (comments from Rails API) - Interactive client components ('use client' TogglePanel) mixed with server-rendered content (donut pattern) - Markdown rendering with marked + sanitize-html on server only Key changes: - Three-bundle build: client, server, and RSC bundles via Rspack - Custom RspackRscPlugin for manifest generation (the standard RSCWebpackPlugin uses webpack internals incompatible with Rspack) - 'use client' directives on all existing client component entry points - Alias react-on-rails to react-on-rails-pro in webpack resolve to handle third-party packages (rescript-react-on-rails) - Dedicated rsc-bundle.js entry with registerServerComponent - RSC payload route and client-side registration Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5cf245f commit 4d09e13

35 files changed

Lines changed: 804 additions & 51 deletions

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
55

66
ruby "3.4.6"
77

8-
gem "react_on_rails", "16.6.0.rc.0"
8+
gem "react_on_rails_pro", "16.5.1"
99
gem "shakapacker", "10.0.0.rc.0"
1010

1111
# Bundle edge Rails instead: gem "rails", github: "rails/rails"

Gemfile.lock

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ GEM
7878
addressable (2.8.7)
7979
public_suffix (>= 2.0.2, < 7.0)
8080
ast (2.4.3)
81+
async (2.38.1)
82+
console (~> 1.29)
83+
fiber-annotation
84+
io-event (~> 1.11)
85+
metrics (~> 0.12)
86+
traces (~> 0.18)
8187
autoprefixer-rails (10.4.16.0)
8288
execjs (~> 2)
8389
awesome_print (1.9.2)
@@ -115,6 +121,10 @@ GEM
115121
coffee-script-source (1.12.2)
116122
concurrent-ruby (1.3.6)
117123
connection_pool (3.0.2)
124+
console (1.34.3)
125+
fiber-annotation
126+
fiber-local (~> 1.1)
127+
json
118128
coveralls_reborn (0.25.0)
119129
simplecov (>= 0.18.1, < 0.22.0)
120130
term-ansicolor (~> 1.6)
@@ -146,16 +156,24 @@ GEM
146156
railties (>= 5.0.0)
147157
ffi (1.17.2-arm64-darwin)
148158
ffi (1.17.2-x86_64-linux-gnu)
159+
fiber-annotation (0.2.0)
160+
fiber-local (1.1.0)
161+
fiber-storage
162+
fiber-storage (1.0.1)
149163
foreman (0.88.1)
150164
generator_spec (0.10.0)
151165
activesupport (>= 3.0.0)
152166
railties (>= 3.0.0)
153167
globalid (1.3.0)
154168
activesupport (>= 6.1)
169+
http-2 (1.1.3)
170+
httpx (1.7.5)
171+
http-2 (>= 1.1.3)
155172
i18n (1.14.8)
156173
concurrent-ruby (~> 1.0)
157174
interception (0.5)
158175
io-console (0.8.2)
176+
io-event (1.14.5)
159177
irb (1.17.0)
160178
pp (>= 0.6.0)
161179
prism (>= 1.3.0)
@@ -165,6 +183,8 @@ GEM
165183
actionview (>= 5.0.0)
166184
activesupport (>= 5.0.0)
167185
json (2.19.1)
186+
jwt (2.10.2)
187+
base64
168188
language_server-protocol (3.17.0.5)
169189
launchy (3.0.1)
170190
addressable (~> 2.8)
@@ -182,6 +202,7 @@ GEM
182202
marcel (1.1.0)
183203
matrix (0.4.2)
184204
method_source (1.1.0)
205+
metrics (0.15.0)
185206
mini_mime (1.1.5)
186207
minitest (6.0.2)
187208
drb (~> 2.0)
@@ -296,13 +317,23 @@ GEM
296317
erb
297318
psych (>= 4.0.0)
298319
tsort
299-
react_on_rails (16.6.0.rc.0)
320+
react_on_rails (16.5.1)
300321
addressable
301322
connection_pool
302323
execjs (~> 2.5)
303324
rails (>= 5.2)
304325
rainbow (~> 3.0)
305326
shakapacker (>= 6.0)
327+
react_on_rails_pro (16.5.1)
328+
addressable
329+
async (>= 2.29)
330+
connection_pool
331+
execjs (~> 2.9)
332+
http-2 (>= 1.1.1)
333+
httpx (~> 1.5)
334+
jwt (~> 2.7)
335+
rainbow
336+
react_on_rails (= 16.5.1)
306337
redcarpet (3.6.0)
307338
redis (5.3.0)
308339
redis-client (>= 0.22.0)
@@ -425,6 +456,7 @@ GEM
425456
tins (1.33.0)
426457
bigdecimal
427458
sync
459+
traces (0.18.2)
428460
tsort (0.2.0)
429461
turbo-rails (2.0.11)
430462
actionpack (>= 6.0.0)
@@ -486,7 +518,7 @@ DEPENDENCIES
486518
rails-html-sanitizer
487519
rails_best_practices
488520
rainbow
489-
react_on_rails (= 16.6.0.rc.0)
521+
react_on_rails_pro (= 16.5.1)
490522
redcarpet
491523
redis (~> 5.0)
492524
rspec-rails (~> 6.0.0)

Procfile.dev

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ rails: bundle exec thrust bin/rails server -p 3000
1212
wp-client: RAILS_ENV=development NODE_ENV=development bin/shakapacker-dev-server
1313
# Server Rspack watcher for SSR bundle
1414
wp-server: SERVER_BUNDLE_ONLY=yes bin/shakapacker --watch
15+
# RSC Rspack watcher for React Server Components bundle
16+
wp-rsc: RSC_BUNDLE_ONLY=true bin/shakapacker --watch

app/controllers/pages_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ def simple; end
3838

3939
def rescript; end
4040

41+
def server_components; end
42+
4143
private
4244

4345
def set_comments
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<%= append_javascript_pack_tag('rsc-client-components') %>
2+
<%= react_component("ServerComponentsPage",
3+
prerender: false,
4+
trace: true,
5+
id: "ServerComponentsPage-react-component-0") %>

client/app/bundles/comments/components/Footer/ror_components/Footer.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use client';
2+
13
import React from 'react';
24
import PropTypes from 'prop-types';
35
import BaseComponent from 'libs/components/BaseComponent';

client/app/bundles/comments/components/NavigationBar/NavigationBar.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ function NavigationBar(props) {
102102
Rescript
103103
</a>
104104
</li>
105+
<li>
106+
<a
107+
className={navItemClassName(pathname === paths.SERVER_COMPONENTS_PATH)}
108+
href={paths.SERVER_COMPONENTS_PATH}
109+
>
110+
RSC Demo
111+
</a>
112+
</li>
105113
<li>
106114
<a
107115
className={navItemClassName(false)}

client/app/bundles/comments/components/SimpleCommentScreen/ror_components/SimpleCommentScreen.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
'use client';
2+
13
// eslint-disable-next-line max-classes-per-file
24
import React from 'react';
35
import request from 'axios';
46
import Immutable from 'immutable';
57
import _ from 'lodash';
6-
import ReactOnRails from 'react-on-rails';
8+
import ReactOnRails from 'react-on-rails-pro';
79
import { IntlProvider, injectIntl } from 'react-intl';
810
import BaseComponent from 'libs/components/BaseComponent';
911
import SelectLanguage from 'libs/i18n/selectLanguage';

client/app/bundles/comments/constants/paths.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export const RESCRIPT_PATH = '/rescript';
55
export const SIMPLE_REACT_PATH = '/simple';
66
export const STIMULUS_PATH = '/stimulus';
77
export const RAILS_PATH = '/comments';
8+
export const SERVER_COMPONENTS_PATH = '/server-components';

client/app/bundles/comments/rescript/ReScriptShow/ror_components/RescriptShow.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use client';
2+
13
// Wrapper for ReScript component to work with react_on_rails auto-registration
24
// react_on_rails looks for components in ror_components/ subdirectories
35

0 commit comments

Comments
 (0)