Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ After a release, run `/update-changelog` in Claude Code to analyze commits, writ

### [Unreleased]

#### Changed

- **[Pro]** **Pro generator now creates the Node Renderer at `renderer/node-renderer.js`**: The canonical location for the Node Renderer entry point is now a dedicated top-level `renderer/` directory instead of `client/`, making it straightforward to exclude from production Docker builds that strip JS sources after bundling. Docs and Pro `spec/dummy` now use the new path consistently. Existing apps are unaffected — the generator skips files that already exist (including a legacy `client/node-renderer.js`). Fixes [Issue 3073](https://github.com/shakacode/react_on_rails/issues/3073). [PR 3165](https://github.com/shakacode/react_on_rails/pull/3165) by [justin808](https://github.com/justin808).

#### Fixed

- **Client startup now recovers if initialization begins during `interactive` after `DOMContentLoaded` already fired**: React on Rails now still initializes the page when the client bundle starts in the browser timing window after `DOMContentLoaded` but before the document reaches `complete`. Fixes [Issue 3150](https://github.com/shakacode/react_on_rails/issues/3150). [PR 3151](https://github.com/shakacode/react_on_rails/pull/3151) by [ihabadham](https://github.com/ihabadham).
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/bench-node-renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def read_protocol_version

def read_password_from_config
config_path = File.expand_path(
"../react_on_rails_pro/spec/dummy/client/node-renderer.js",
"../react_on_rails_pro/spec/dummy/renderer/node-renderer.js",
__dir__
)
config_content = File.read(config_path)
Expand Down
4 changes: 2 additions & 2 deletions docs/oss/api-reference/generator-details.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ can pass the redux option if you'd like to have redux setup for you automaticall
Passing the --pro generator option sets up React on Rails Pro with Node
server rendering, fragment caching, and code-splitting support.
Requires the react_on_rails_pro gem (add it to your Gemfile first).
Creates the Pro initializer, node-renderer.js, and adds the Node Renderer
Creates the Pro initializer, renderer/node-renderer.js, and adds the Node Renderer
process to Procfile.dev.

* RSC (React Server Components)
Expand Down Expand Up @@ -215,7 +215,7 @@ rails generate react_on_rails:install --pro
**What gets created:**

- `config/initializers/react_on_rails_pro.rb` - Pro configuration with Node Renderer settings
- `client/node-renderer.js` - Node Renderer bootstrap file
- `renderer/node-renderer.js` - Node Renderer bootstrap file
- Node Renderer process added to `Procfile.dev`
- Pro npm packages (`react-on-rails-pro`, `react-on-rails-pro-node-renderer`)

Expand Down
2 changes: 1 addition & 1 deletion docs/oss/building-features/code-splitting.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ in your webpack configuration. That turns off the polyfills for things like `__d

### Node Renderer

In your `node-renderer.js` file which runs node renderer, you need to specify `supportModules` options as follows:
In your `renderer/node-renderer.js` file which runs node renderer, you need to specify `supportModules` options as follows:

```js
const path = require('path');
Expand Down
8 changes: 4 additions & 4 deletions docs/oss/building-features/node-renderer/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ See the [Memory Leaks guide](../../../pro/js-memory-leaks.md) for common leak pa

**node-renderer** is a standalone Node application to serve React SSR requests from a **Rails** client. You don't need any **Ruby** code to setup and launch it. You can configure with the command line or with a launch file.

> **Generator shortcut:** Running `rails generate react_on_rails:install --pro` (or `rails generate react_on_rails:pro` for existing apps) automatically creates `client/node-renderer.js`, adds the Node Renderer process to `Procfile.dev`, and installs the required npm packages. See [Installation](../../../pro/installation.md) for details. The manual setup below is for apps that need custom configuration.
> **Generator shortcut:** Running `rails generate react_on_rails:install --pro` (or `rails generate react_on_rails:pro` for existing apps) automatically creates `renderer/node-renderer.js`, adds the Node Renderer process to `Procfile.dev`, and installs the required npm packages. See [Installation](../../../pro/installation.md) for details. The manual setup below is for apps that need custom configuration.

## Simple Command Line for node-renderer

Expand Down Expand Up @@ -65,7 +65,7 @@ For the most control over the setup, create a JavaScript file to start the NodeR
# or: yarn add react-on-rails-pro-node-renderer
# or: bun add react-on-rails-pro-node-renderer
```
4. Configure a JavaScript file that will launch the rendering server per the docs in [Node Renderer JavaScript Configuration](./js-configuration.md). For example, create a file `node-renderer.js`. Here is a simple example that uses all the defaults except for serverBundleCachePath:
4. Configure a JavaScript file that will launch the rendering server per the docs in [Node Renderer JavaScript Configuration](./js-configuration.md). For example, create a file `renderer/node-renderer.js`. Here is a simple example that uses all the defaults except for serverBundleCachePath:

```javascript
import path from 'path';
Expand All @@ -78,7 +78,7 @@ For the most control over the setup, create a JavaScript file to start the NodeR
reactOnRailsProNodeRenderer(config);
```

5. Now you can launch your renderer server with `node node-renderer.js`. You will probably add a script to your `package.json`.
5. Now you can launch your renderer server with `node renderer/node-renderer.js`. You will probably add a script to your `package.json`.
6. You can use a command line argument of `-p SOME_PORT` to override any configured or ENV value for the port.

## Setup Rails Application
Expand Down Expand Up @@ -163,7 +163,7 @@ jobs:
steps:
- name: Start Node Renderer
run: |
node client/node-renderer.js &
node renderer/node-renderer.js &
# Wait for the renderer to be ready.
# The renderer uses cleartext HTTP/2 (h2c), so use --http2-prior-knowledge for the probe.
# --max-time 2 prevents hangs if the port is open but the process is stalled.
Expand Down
12 changes: 7 additions & 5 deletions docs/oss/building-features/node-renderer/container-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ end

## Dockerfile Example

> **Why the renderer entry point lives in a dedicated `renderer/` directory:** Production Docker builds commonly strip JavaScript sources after the client bundles are built, since the Rails app no longer needs them at runtime. Keeping the renderer entry point in its own top-level directory (separate from `client/`) makes it trivial to exclude from that cleanup — the Node Renderer process still needs its entry file and dependencies at runtime.

A minimal Dockerfile that bundles Rails and the Node Renderer in a single image:

```dockerfile
Expand Down Expand Up @@ -175,10 +177,10 @@ For the single-container pattern, use a process manager like [overmind](https://
```text
# Procfile
rails: bundle exec rails server -b 0.0.0.0 -p 3000
renderer: node client/node-renderer.js
renderer: node renderer/node-renderer.js
```

> **Tip:** For sidecar containers, use the same image but override the `CMD` — one container runs `bundle exec rails server`, the other runs `node client/node-renderer.js` (or your Node Renderer entry point).
> **Tip:** For sidecar containers, use the same image but override the `CMD` — one container runs `bundle exec rails server`, the other runs `node renderer/node-renderer.js` (or your Node Renderer entry point).

## Docker Compose Example

Expand All @@ -199,7 +201,7 @@ services:

renderer:
build: .
command: node client/node-renderer.js
command: node renderer/node-renderer.js
ports:
- '3800:3800'
environment:
Expand All @@ -220,7 +222,7 @@ services:
By default, the Node Renderer binds to `localhost`. For **sidecar containers** in the same Kubernetes pod, that works because the containers share a network namespace. For **separate workloads** or Docker Compose setups without shared networking, bind to `0.0.0.0`:

```javascript
// node-renderer.js
// renderer/node-renderer.js
import { reactOnRailsProNodeRenderer } from 'react-on-rails-pro-node-renderer';

const config = {
Expand Down Expand Up @@ -488,7 +490,7 @@ spec:

- name: node-renderer
image: your-app:latest # Same image as Rails
command: ['node', 'client/node-renderer.js']
command: ['node', 'renderer/node-renderer.js']
ports:
- containerPort: 3800
env:
Expand Down
2 changes: 1 addition & 1 deletion docs/oss/building-features/node-renderer/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Use Node's built-in flag to write heap snapshots on demand:
```bash
cd react_on_rails_pro/spec/dummy
# Adjust the port if your Rails app points at a different renderer URL.
NODE_OPTIONS="--heapsnapshot-signal=SIGUSR2" RENDERER_PORT=3800 node client/node-renderer.js
NODE_OPTIONS="--heapsnapshot-signal=SIGUSR2" RENDERER_PORT=3800 node renderer/node-renderer.js
```

Then capture snapshots at different times:
Expand Down
2 changes: 1 addition & 1 deletion docs/oss/building-features/node-renderer/heroku.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Define the script in your root `package.json` so Heroku can run it from the app
```json
{
"scripts": {
"node-renderer": "node client/node-renderer.js"
"node-renderer": "node renderer/node-renderer.js"
}
}
```
Expand Down
10 changes: 5 additions & 5 deletions docs/oss/building-features/node-renderer/js-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ Deprecated options:

### Testing example:

[spec/dummy/client/node-renderer.js](https://github.com/shakacode/react_on_rails/blob/main/react_on_rails_pro/spec/dummy/client/node-renderer.js)
[react_on_rails_pro/spec/dummy/renderer/node-renderer.js](../../../../react_on_rails_pro/spec/dummy/renderer/node-renderer.js)
Comment thread
justin808 marked this conversation as resolved.
Comment thread
justin808 marked this conversation as resolved.
Comment thread
justin808 marked this conversation as resolved.
Comment thread
justin808 marked this conversation as resolved.
Comment thread
justin808 marked this conversation as resolved.
Comment thread
justin808 marked this conversation as resolved.

### Simple example:

Create a file `client/node-renderer.js`. The generator uses this filename and CommonJS syntax so
the file runs directly with `node client/node-renderer.js` without extra ESM configuration.
Create a file `renderer/node-renderer.js`. The generator uses this filename and CommonJS syntax so
the file runs directly with `node renderer/node-renderer.js` without extra ESM configuration.

```js
const path = require('path');
Expand Down Expand Up @@ -94,7 +94,7 @@ And add a root-level script to the `scripts` section of your `package.json`

```json
"scripts": {
"node-renderer": "node client/node-renderer.js"
"node-renderer": "node renderer/node-renderer.js"
},
```

Expand All @@ -113,7 +113,7 @@ For advanced use cases, you can customize the Fastify server instance by importi
When running the node-renderer in Docker or Kubernetes, you may need a `/health` endpoint for container health checks:

The advanced examples below use ES modules for readability. If you want this file to keep running
as `node client/node-renderer.js`, either keep using the CommonJS pattern shown in the simple
as `node renderer/node-renderer.js`, either keep using the CommonJS pattern shown in the simple
example above or switch the file to `.mjs` or `"type": "module"`.

```js
Expand Down
2 changes: 1 addition & 1 deletion docs/oss/deployment/docker-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ containers:

- name: node-renderer
image: your-registry/myapp-node-renderer:latest # must include Node.js
command: ['node', 'node-renderer.js']
command: ['node', 'renderer/node-renderer.js']
ports:
- containerPort: 3800
env:
Expand Down
2 changes: 1 addition & 1 deletion docs/oss/migrating/rsc-preparing-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ rails: rails s -p 3000
webpack-dev-server: HMR=true bin/shakapacker-dev-server
rails-server-assets: HMR=true SERVER_BUNDLE_ONLY=true bin/shakapacker --watch
rails-rsc-assets: HMR=true RSC_BUNDLE_ONLY=true bin/shakapacker --watch
node-renderer: node client/node-renderer.js
node-renderer: node renderer/node-renderer.js
```

> **For full webpack configuration details**, including the technical background on how the RSC loader, plugin, and manifests work together, see [How React Server Components Work](../../pro/react-server-components/how-react-server-components-work.md).
Expand Down
2 changes: 1 addition & 1 deletion docs/oss/migrating/rsc-troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ for the current recommendation. See also
**Fix:** Enable `supportModules` in your node renderer configuration to inject common Node.js globals:

```js
// node-renderer.js (or wherever you configure the renderer)
// renderer/node-renderer.js (or wherever you configure the renderer)
module.exports = {
supportModules: true, // Injects: Buffer, TextDecoder, TextEncoder,
// URLSearchParams, ReadableStream, process,
Expand Down
6 changes: 3 additions & 3 deletions docs/pro/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ git commit -m "Prepare app for React on Rails Pro install"
bundle exec rails generate react_on_rails:install --pro
```

This creates the Pro initializer, node-renderer.js, installs npm packages, and adds the Node Renderer to Procfile.dev.
This creates the Pro initializer, `renderer/node-renderer.js`, installs npm packages, and adds the Node Renderer to Procfile.dev.

## Upgrading an Existing App

Expand Down Expand Up @@ -227,7 +227,7 @@ yarn add react-on-rails-pro-node-renderer@<npm_version> --exact

## Node Renderer Setup

Create a JavaScript file to configure and launch the node renderer, for example `react-on-rails-pro-node-renderer.js`:
Create a JavaScript file to configure and launch the node renderer at `renderer/node-renderer.js`:

```js
const path = require('path');
Expand Down Expand Up @@ -276,7 +276,7 @@ Add a script to your `package.json`:
```json
{
"scripts": {
"node-renderer": "node ./react-on-rails-pro-node-renderer.js"
"node-renderer": "node renderer/node-renderer.js"
}
}
```
Expand Down
6 changes: 3 additions & 3 deletions docs/pro/js-memory-leaks.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ done
Node provides a built-in flag that writes heap snapshots on a signal — no custom code required:

```bash
NODE_OPTIONS="--heapsnapshot-signal=SIGUSR2" node node-renderer.js
NODE_OPTIONS="--heapsnapshot-signal=SIGUSR2" node renderer/node-renderer.js
```

Then send `kill -USR2 <worker-pid>` at different times to capture snapshots. Each signal writes a `.heapsnapshot` file to the working directory.
Expand Down Expand Up @@ -186,7 +186,7 @@ To diagnose leaks in a running container:
Start the renderer with the `--inspect` flag to connect Chrome DevTools:

```bash
node --inspect node-renderer.js
node --inspect renderer/node-renderer.js
```

Open `chrome://inspect` in Chrome, take heap snapshots, and use the "Comparison" view to see what objects accumulated between snapshots.
Expand All @@ -200,7 +200,7 @@ Without this flag, V8 reads the container's memory limit and sets a very large h
**Always set this for production:**

```bash
NODE_OPTIONS=--max-old-space-size=1536 node node-renderer.js
NODE_OPTIONS=--max-old-space-size=1536 node renderer/node-renderer.js
```

Size it based on your container memory and worker count. For example, with 4GB container memory and 3 workers: `4096 / 3 ≈ 1365`, round to `1400`.
Expand Down
2 changes: 1 addition & 1 deletion docs/pro/profiling-server-side-rendering-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ installed. On macOS, you can install it with `brew install overmind`.

```bash
cd react_on_rails_pro/spec/dummy
RENDERER_LOG_LEVEL=debug RENDERER_PORT=3800 node --inspect client/node-renderer.js
RENDERER_LOG_LEVEL=debug RENDERER_PORT=3800 node --inspect renderer/node-renderer.js
```

Keep this terminal open while you profile. If your app usually starts the renderer through a
Expand Down
6 changes: 3 additions & 3 deletions packages/react-on-rails-pro-node-renderer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pnpm add react-on-rails-pro-node-renderer

### 1. Create the Node Renderer entry file

Create `node-renderer.js` in your project root:
Create `renderer/node-renderer.js` in your project root:

```js
const path = require('path');
Expand Down Expand Up @@ -72,13 +72,13 @@ libraryTarget: 'commonjs2',
### 4. Start the renderer

```bash
node node-renderer.js
node renderer/node-renderer.js
```

Or add to your `Procfile.dev`:

```text
node-renderer: node node-renderer.js
node-renderer: node renderer/node-renderer.js
```

## Generator (Recommended)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ def home_page_file_hints

if use_pro?
hints << {
path: "client/node-renderer.js",
path: "renderer/node-renderer.js",
description: "Node renderer entrypoint used for Pro SSR and RSC."
}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def hello_server_file_hints
description: "Rails view that calls stream_react_component."
},
{
path: "client/node-renderer.js",
path: "renderer/node-renderer.js",
description: "Node renderer entrypoint used by the Pro SSR and RSC stack."
}
]
Expand Down
2 changes: 1 addition & 1 deletion react_on_rails/lib/generators/react_on_rails/pro/USAGE
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Example:

This will add:
- Pro initializer (config/initializers/react_on_rails_pro.rb)
- Node renderer (client/node-renderer.js)
- Node renderer (renderer/node-renderer.js)
- Node renderer process to Procfile.dev

Modifies:
Expand Down
Loading
Loading