Skip to content

Commit 05cb2bc

Browse files
justin808claude
andcommitted
Add Node renderer and fix RSC page rendering
- Add react-on-rails-pro-node-renderer for SSR and RSC payload generation - Configure Pro initializer with NodeRenderer, renderer_url, password - Alias react-dom/server.browser to react-dom/server.node in server webpack config (React 19's browser build requires MessageChannel which isn't available in the Node renderer VM) - Add auto_load_bundle: false to RSC view (server components use registerServerComponent, not ror_components auto-loading) - Add node-renderer to Procfile.dev Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ae420af commit 05cb2bc

7 files changed

Lines changed: 484 additions & 9 deletions

File tree

Procfile.dev

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ wp-client: RAILS_ENV=development NODE_ENV=development bin/shakapacker-dev-server
1414
wp-server: SERVER_BUNDLE_ONLY=yes bin/shakapacker --watch
1515
# RSC Rspack watcher for React Server Components bundle
1616
wp-rsc: RSC_BUNDLE_ONLY=true bin/shakapacker --watch
17+
# React on Rails Pro Node renderer for SSR and RSC payload generation
18+
node-renderer: RENDERER_PASSWORD=devPassword node react-on-rails-pro-node-renderer.js
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<%= append_javascript_pack_tag('rsc-client-components') %>
22
<%= react_component("ServerComponentsPage",
33
prerender: false,
4+
auto_load_bundle: false,
45
trace: true,
56
id: "ServerComponentsPage-react-component-0") %>

config/initializers/react_on_rails_pro.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# frozen_string_literal: true
22

33
ReactOnRailsPro.configure do |config|
4+
# Node renderer for server-side rendering and RSC payload generation
5+
config.server_renderer = "NodeRenderer"
6+
config.renderer_url = ENV["REACT_RENDERER_URL"] || "http://localhost:3800"
7+
config.renderer_password = ENV.fetch("RENDERER_PASSWORD", "devPassword")
8+
49
# Enable React Server Components support
510
config.enable_rsc_support = true
611

config/webpack/serverWebpackConfig.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ const configureServer = () => {
9595
serverWebpackConfig.output = {
9696
filename: 'server-bundle.js',
9797
globalObject: 'this',
98-
// If using the React on Rails Pro node server renderer, uncomment the next line
9998
// libraryTarget: 'commonjs2',
10099
path: path.resolve(__dirname, '../../ssr-generated'),
101100
publicPath: config.publicPath,
@@ -164,10 +163,14 @@ const configureServer = () => {
164163
// The default of cheap-module-source-map is slow and provides poor info.
165164
serverWebpackConfig.devtool = 'eval';
166165

167-
// If using the default 'web', then libraries like Emotion and loadable-components
168-
// break with SSR. The fix is to use a node renderer and change the target.
169-
// If using the React on Rails Pro node server renderer, uncomment the next line
170-
// serverWebpackConfig.target = 'node'
166+
// Alias react-dom/server to the Node.js version for the Pro Node renderer.
167+
// The default browser version uses MessageChannel which isn't available in the Node VM.
168+
serverWebpackConfig.resolve = serverWebpackConfig.resolve || {};
169+
serverWebpackConfig.resolve.alias = {
170+
...serverWebpackConfig.resolve.alias,
171+
'react-dom/server.browser$': 'react-dom/server.node',
172+
'react-dom/server.browser.js$': 'react-dom/server.node.js',
173+
};
171174

172175
// RSC: Generate react-server-client-manifest.json for SSR component resolution
173176
serverWebpackConfig.plugins.push(new RspackRscPlugin({ isServer: true }));

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
"test:client": "yarn jest",
3131
"build:test": "rm -rf public/packs-test && RAILS_ENV=test NODE_ENV=test bin/shakapacker",
3232
"build:dev": "rm -rf public/packs && RAILS_ENV=development NODE_ENV=development bin/shakapacker",
33-
"build:clean": "rm -rf public/packs || true"
33+
"build:clean": "rm -rf public/packs || true",
34+
"node-renderer": "node ./react-on-rails-pro-node-renderer.js"
3435
},
3536
"dependencies": {
3637
"@babel/cli": "^7.21.0",
@@ -81,6 +82,7 @@
8182
"react-dom": "19.0.4",
8283
"react-intl": "^6.4.4",
8384
"react-on-rails-pro": "16.5.1",
85+
"react-on-rails-pro-node-renderer": "16.5.1",
8486
"react-on-rails-rsc": "19.0.5-rc.1",
8587
"react-redux": "^8.1.0",
8688
"react-router": "^6.13.0",
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const path = require('path');
2+
const { reactOnRailsProNodeRenderer } = require('react-on-rails-pro-node-renderer');
3+
4+
const config = {
5+
serverBundleCachePath: path.resolve(__dirname, '.node-renderer-bundles'),
6+
logLevel: process.env.RENDERER_LOG_LEVEL || 'debug',
7+
password: process.env.RENDERER_PASSWORD || 'devPassword',
8+
port: process.env.RENDERER_PORT || 3800,
9+
supportModules: true,
10+
workersCount: Number(process.env.NODE_RENDERER_CONCURRENCY || 3),
11+
};
12+
13+
if (process.env.CI) {
14+
config.workersCount = 2;
15+
}
16+
17+
reactOnRailsProNodeRenderer(config);

0 commit comments

Comments
 (0)