Skip to content

Latest commit

 

History

History
123 lines (86 loc) · 6.86 KB

File metadata and controls

123 lines (86 loc) · 6.86 KB

Node Renderer

The React on Rails Pro Node Renderer replaces ExecJS with a dedicated Node.js server for server-side rendering. It eliminates the limitations of embedded JavaScript execution and provides significant performance improvements for production applications.

Note

Summary for AI agents: Use this page when the user asks about the Node renderer, ExecJS alternatives, or SSR performance. This is the Pro-level overview; for technical setup, see Node Renderer basics and JS configuration. The Node renderer is required for RSC.

Route map: Start at React on Rails Pro if you're choosing a path. This page is the canonical Node Renderer overview; use the linked install and technical docs below for the deeper implementation details.

Why Use the Node Renderer?

ExecJS embeds a JavaScript runtime (mini_racer/V8) inside the Ruby process. This works for small apps but creates problems at scale:

  • Memory pressure — V8 contexts consume memory inside each Ruby process, competing with Rails for resources
  • No Node tooling — You cannot use standard Node.js profiling, debugging, or memory leak detection tools with ExecJS
  • Process crashes — JavaScript memory leaks can crash your Ruby server
  • Limited concurrency — ExecJS renders synchronously within the Ruby request cycle

The Pro Node Renderer solves all of these by running a standalone Node.js server that handles rendering requests from Rails over HTTP.

Performance Benefits

Metric ExecJS Node Renderer
SSR throughput Baseline 10-100x faster
Memory isolation Shared with Ruby Separate process
Worker concurrency Single-threaded per request Configurable worker pool
Profiling Not available Full Node.js tooling
Memory leak recovery Crashes Ruby Rolling worker restarts

At Popmenu (a ShakaCode client), switching to the Node Renderer contributed to a 73% decrease in average response times and 20-25% lower Heroku costs across tens of millions of daily SSR requests.

How It Works

  1. Rails sends a rendering request (component name, props, and JavaScript bundle reference) to the Node Renderer over HTTP
  2. The Node Renderer evaluates the server bundle in a Node.js worker
  3. The rendered HTML is returned to Rails and inserted into the view
  4. Workers are pooled and can be automatically restarted to mitigate memory leaks

Key Features

  • Worker pool — Configurable number of workers (defaults to CPU count minus 1)
  • Rolling restarts — Automatic worker recycling to prevent memory leak buildup
  • Bundle caching — Server bundles are cached on the Node side for fast re-renders
  • Shared secret authentication — Secure communication between Rails and Node
  • Prerender caching — Combined with prerender caching, rendering results are cached across requests

Getting Started

Quick Setup (Generator)

The fastest way to set up the Node Renderer is with the Pro generator:

bundle exec rails generate react_on_rails:pro

This creates the Node Renderer entry point, configures webpack, and adds the renderer to Procfile.dev.

Manual Setup

For fine-grained control, see the Node Renderer installation section in the installation guide.

Configuration

Configure Rails to use the Node Renderer:

# config/initializers/react_on_rails_pro.rb
ReactOnRailsPro.configure do |config|
  config.server_renderer = "NodeRenderer"
  config.renderer_url = ENV["REACT_RENDERER_URL"] || "http://localhost:3800"
  config.renderer_password = ENV.fetch("RENDERER_PASSWORD", "devPassword")
end

Renderer Password Security

The renderer password secures communication between Rails and the Node Renderer. React on Rails Pro enforces secure defaults by environment:

Environment Password Required? Behavior
development No Optional — no authentication if unset
test No Optional — no authentication if unset
(neither set) Yes Treated as production-like; RENDERER_PASSWORD required
staging Yes Raises error on boot if RENDERER_PASSWORD is missing
production Yes Raises error on boot if RENDERER_PASSWORD is missing
qa, preview, etc. Yes Raises error on boot if RENDERER_PASSWORD is missing

In production-like environments (anything other than development or test), both the Rails app and the Node Renderer will refuse to start without a non-empty password. Set the same RENDERER_PASSWORD for both sides:

# Set for both Rails and Node Renderer
export RENDERER_PASSWORD="your-secure-password"

The Node Renderer reads RENDERER_PASSWORD directly from process.env. On the Ruby side, React on Rails Pro resolves the password in this order:

  1. config.renderer_password (blank values fall through to the next step)
  2. Password embedded in config.renderer_url (for example, https://:password@localhost:3800)
  3. ENV["RENDERER_PASSWORD"]

So setting RENDERER_PASSWORD in the environment is enough unless you intentionally override it in the initializer or URL.

If neither NODE_ENV nor RAILS_ENV is set, the Node Renderer treats the environment as production-like and still requires RENDERER_PASSWORD.

For local development, you can either omit the password entirely (no authentication) or set a convenience default:

config.renderer_password = ENV.fetch("RENDERER_PASSWORD", "devPassword")

Further Reading