Added
- [Pro] Route-loader RSC payload helper:
react-on-rails-pro/rscPayloadNodenow exportscreateRscPayloadNode(...)so client routers and loaders can consume the Pro RSC payload route as React route data without reaching into privateRSCRouteinternals. The helper defaults to same-origin credentials, exposes a narrow set of fetch controls (credentials,headers, andsignal), and keeps console replay metadata out of inline scripts for CSP-friendly loader usage. RSC payload fetches now URL-encode component names before requesting/rsc_payload/:componentName, which preserves standard Rails path-segment decoding while avoiding invalid path characters in the browser request URL. Fixes Issue 3493. PR 3783 by justin808. - [Pro] RSC registration entry path override: Generated RSC precompile hooks, discovery builds, and client-reference stale checks now honor
REACT_ON_RAILS_RSC_REGISTRATION_ENTRY_PATHso apps that writeserver-component-registration-entry.jsoutside the default generated path can point React on Rails Pro at the exact entry while retaining the existing fallback scan and stale-manifest cleanup. Fixes Issue 3621. PR 3712 by justin808. - [Pro] RSC
unstable_cachewith Redis L2 and tiered caching: Addedunstable_cachefor RSC rendering with deterministic cache-key serialization (React flight protocol encoding with sorted object keys), aRedisCacheHandlerfor cross-worker L2 caching, aTieredCacheHandlerfor L1/L2 composition with configurable L1 TTL caps, and per-worker single-flight render coalescing. Resolves Issue 3702. PR 3705. - [Pro] RSC manifest client reference discovery during precompile: Generated RSC Webpack configs now run
RSCReferenceDiscoveryPluginthrough the Shakapacker precompile hook to emitrsc-client-references.json, use that manifest for RSC client-reference bundling, and warn when the selected manifest is stale. The generator now pinsreact-on-rails-rscto19.0.5-rc.6, the prerelease containing the discovery plugin export and RSC manifest CSS fixes, and the Pro peer range explicitly accepts that prerelease. PR 3556 by ihabadham.
Changed
- [Pro]
<RSCRoute>client-control refetch failures are recoverable in production:refanduseCurrentRSCRoute()refetch failures now keep the last successful route content mounted in production, exposerefetchError,retry(), andclearRefetchError()onRSCRouteHandle, and call the optionalonRefetchErrorprop for parent/sibling reporting. Development still fails loudly throughServerComponentFetchErrorso component context and the original refetch error stay visible. Fixes Issue 3565. PR 3786 by justin808. - [Pro] Updated the RSC rollout pin to
react-on-rails-rsc@19.0.5-rc.7: The generator default, package manifests, lockfile, and Pro RSC install docs now point at19.0.5-rc.7, which fixes the Webpack client manifest CSS collection to exclude runtime-chunk CSS (so shared runtime CSS no longer leaks into every client component's Flight stylesheet hints, while the server manifest still retains runtime-chunk CSS for SSR coverage) and to skip.hot-update.cssHMR files. The temporary exact prerelease pin policy is unchanged until stable19.0.5ships. PR 3857 by justin808. - [Pro] Updated the RSC rollout pin to
react-on-rails-rsc@19.0.5-rc.6: Pro RSC install docs, generator defaults, package metadata, and example guidance now point at19.0.5-rc.6while keeping React on the supported19.0.xrange and documenting the temporary exact prerelease pin.19.0.5-rc.6ships the client-manifest CSS collection fix (record.csssiblings,.mjschunk support, href normalization) upstream, so the temporary local pnpm patch (patches/react-on-rails-rsc@19.0.5-rc.5.patch) has been removed. PR 3577 by justin808. - Generator scaffolds the native
RSCRspackPluginfor Rspack RSC projects:rails generate react_on_rails:install --rscon an Rspack app now wires upreact-on-rails-rsc/RspackPlugin(RSCRspackPlugin) instead of the Webpack-compatRSCWebpackPlugin, which produced valid-looking manifests that still broke under Rspack. Re-running the generator on a legacy Rspack config migrates the oldRSCWebpackPluginimport and invocation to the native plugin. The pinnedreact-on-rails-rscdependency was bumped to19.0.5-rc.6(which still exportsWebpackPlugin, so Webpack projects are unaffected). Resolves Issue 3488. PR 3590 by justin808. - [Pro] Widened the
react-on-rails-rscpeer-dependency range to the full React 19 line:react-on-rails-pronow declaresreact-on-rails-rscas>= 19.0.2 < 20.0.0(previously>= 19.0.2 <= 19.2.3), so futurereact-on-rails-rscpatch and minor releases on the React 19 line no longer trigger a peer-dependency warning. Thereact/react-dompeers stay at>= 16: React 18 support is retained, and the React-19-only RSC path is gated through the optionalreact-on-rails-rscpeer rather than by raising the React baseline. Resolves Issue 3486. PR 3580 by justin808.
Improved
- [Pro] Embedded RSC payloads no longer repeat full serialized props in the page HTML: The embedded RSC payload cache key now uses a compact hash of the component props instead of the full
JSON.stringify(componentProps), so server-rendered pages with RSC components stop repeating large props JSON once per Flight chunk in render-blocking inline scripts (a 1KB props object across 10 chunks previously added ~12KB of repeated JSON; now ~120 bytes). The client-sideRSCProviderin-memory promise cache still keys on full props, so payload deduplication behavior is unchanged. Fixes Issue 3796. PR 3800 by AbanoubGhadban. - Server-bundle load failures are now classified separately from renderer-connection failures: Bundle read/fetch failures raise the new
ReactOnRails::ServerBundleLoadErrorinstead of being grouped with renderer-connectivity errors, keeping the renderer-connection classification (see PR 3614) focused on render-origin connection failures, including wrappedconnect(2)errors found through the exception cause chain. Fixes Issue 3628. PR 3724 by justin808. - Renderer connection failures are no longer misreported as webpack/bundle errors: When server rendering fails because Rails cannot reach the renderer process (for example a Pro Node renderer behind
REACT_RENDERER_URLthat refuses the connection —ECONNREFUSED,EHOSTUNREACH,ETIMEDOUT, or a sandboxedErrno::EPERM/connect(2)failure), React on Rails now raises a renderer-connectivity error that names the host/port it tried to reach and points atREACT_RENDERER_URLand renderer liveness, instead of the misleading "Error evaluating server bundle. Check your webpack configuration." The existing webpack/server-bundle troubleshooting is retained for genuine bundle evaluation errors. Fixes Issue 3604. PR 3614 by justin808.
Fixed
- [Pro] RSC
unstable_cacheno longer caches failed Flight renders: React Flight render errors reported byrenderToPipeableStreamnow skip the cache write, so later requests retry the render instead of replaying a failed RSC payload from cache. React's default error logging behavior is preserved. Fixes Issue 3774. PR 3775 by ihabadham. - [Pro] Prerender cache no longer misses when only the random
domNodeIdchanges: Pro prerender cache digest normalization now stripsdomNodeIdvalues emitted in JSON/double-quote form as well as the older single-quote form, so cached prerender results are reused across requests that differ only by the randomly generated DOM node id, while changed props still produce distinct digests. Fixes Issue 3706. PR 3707 by ihabadham. - Auto-bundled snake_case component names now load their generated packs consistently: Auto-bundled component pack loading is normalized through the same name resolution used for DOM/SSR lookup, so
react_component("component_name")loads thegenerated/ComponentNamepack, and public component names generated for files under the configured auto-bundling components subdirectory are camelized (server-bundle and store filename behavior is preserved, as is generated-pack conflict protection for names differing only by case). Fixes Issue 3809. PR 3818 by justin808. - [Pro] A throwing React root unmount no longer aborts client teardown: The Pro client renderer now guards the modern React root
unmount()path, logging failures atconsole.errorand always clearing the tracked root, so one failing root unmount cannot stop other components from unmounting or block later renders on the same DOM node. Fixes Issue 3618. PR 3716 by justin808. - [Pro] Plain-object component registrations keep their type in the Pro
ComponentRegistry: Pro registry entries are now typed to cover plain object modules used byserver_render_js(matching the core package types from PR 3606),getOrWaitForComponentaligns with the widened entry type, and the Pro client renderer now guards against invoking non-callable renderer entries. Fixes Issue 3677. PR 3719 by justin808. - Server-component wrapper types reject non-component render functions at compile time: The new
ReactComponentRenderFunctiontype models render functions that must return a React component, and the ProwrapServerComponentRendererclient/server inputs are narrowed to it, so registering a teardown-returning renderer function there is now a TypeScript compile-time error instead of relying only on the existing runtime guards (which are unchanged for JavaScript callers). Fixes Issue 3589. PR 3720 by justin808. - [Pro] Incompatible
react-on-rails-rsc/ React versions now fail loudly instead of silently misbehaving: the Pro node renderer checks the installedreact-on-rails-rsc,react, andreact-domversions at boot and throws a clear error whenreact-on-rails-rscis outside the supported19.xmajor or React/React DOM are outside the supported19.0.xpatch range on the RSC path (and warns whenreact-on-rails-rscis older than the recommended minimum). Because the peer dependency is declared*(so coordinated prereleases install cleanly, see PR 3616), this runtime check — not the peer range — is the real compatibility gate. SetREACT_ON_RAILS_PRO_DISABLE_VERSION_CHECK=1to downgrade the hard error to a warning. PR 3831 by justin808. - [Pro] RSC
React.cache()request dedupe now works in generated configs: Generated RSC webpack configs now canonicalizereact,react/jsx-runtime, andreact/jsx-dev-runtimeresolution to one React server package instance, keeping React's RSC cache dispatcher shared between the renderer and app Server Components. This restores request-localReact.cache()memoization for direct Server Component data loaders in generated RoRP RSC apps. Fixes Issue 3812. PR 3813 by ihabadham. - [Pro] Preloaded RSC hydration errors preserve bundle diagnostics: RSC payload injection now threads the server-side
renderingErrormetadata to the browser so preloaded hydration failures can report the original RSC bundle error message and module path, matching the fetch path while avoiding unrelated stream metadata such as serialized props. Addresses the preloaded hydration portion of Issue 3475. PR 3766 by justin808. - Auto-bundled component name conflicts now fail loudly: React on Rails now raises an error when multiple auto-bundled component files resolve to the same public component name, listing the conflicting files instead of silently keeping whichever path overwrote the earlier mapping. Fixes Issue 3708. PR 3709 by ihabadham.
- [Pro] RSC CSS no longer flashes unstyled (FOUC) behind
'use client'boundaries: CSS imported by a'use client'boundary in a true React Server Component tree is now preloaded instead of loading only as a side effect of the JS chunk evaluating. The publishedreact-on-rails-rsc@19.0.5-rc.6package now records each client reference's.csssiblings in the RSC client manifest, and the Pro RSC renderer emits<link rel="stylesheet" precedence="ror-rsc">for them inside the RSC payload so React 19 hoists the stylesheets into<head>and blocks paint until they load — on both server render and client-side navigation. Fixes Issue 3211. PR 3587 by justin808. - [Pro]
react-on-rails-rscprerelease (RC) versions no longer mark the dependency tree invalid: Thereact-on-rails-propeer dependency on the optionalreact-on-rails-rscis now*, so installing any coordinatedreact-on-rails-rscbuild — including prereleases such asreact-on-rails-rsc@19.0.5-rc.6— no longer makesnpm ls react-on-rails-rscfail withELSPROBLEMS. npm's strict semver only lets a prerelease satisfy a comparator that shares its exactmajor.minor.patchtuple, so no bounded range — including the>= 19.0.2 < 20.0.0range introduced in PR 3580 — can admit prereleases across the React 19 line (e.g.19.0.5-rc.6,19.2.x-rc.*) without enumerating every patch tuple.react-on-rails-rscstays an optional peer that Pro resolves only on the React Server Components path; the supported pairing is React on Rails RSC on the React 19 line (currently>= 19.0.2), and a mismatched build is caught by the Pro node renderer's runtime version check rather than relying on the peer-range warning. Fixes Issue 3609. PR 3616 by justin808. - TypeScript source server bundles work with auto-generated packs: React on Rails now resolves the configured server bundle source entrypoint by extension, so apps can keep
config.server_bundle_js_file = "server-bundle.js"as the compiled/runtime bundle name while using a TypeScript source entrypoint such aspacks/server-bundle.ts. Public registration types also now cover plain object modules used byserver_render_js, matching existing runtime behavior. Resolves Issue 1583. PR 3606 by ihabadham. - [Pro] Client teardown failures are no longer hidden at
console.info: whenComponentRenderer.unmount()catches an error fromunmountComponentAtNode(the React 16/17 legacy unmount path), it now logs atconsole.errorinstead ofconsole.info. A caught error there means the component tree did not unmount cleanly — a teardown failure — and most log collectors and default browser-console filters dropinfo, so the failure was effectively silent. Addresses item 2 of Issue 3592. PR 3610 by justin808. - Renderer functions no longer leak their mount on navigation/unmount: Renderer functions (the 3-argument
(props, railsContext, domNodeId) => …registration form) own their own React root, but React on Rails never tracked any cleanup state for them, so every renderer-function mount leaked on Turbo/Turbolinks navigation. Renderer functions may now optionally return a teardown wrapper ({ teardown: () => void | Promise<void> }, sync or async); returning nothing keeps the previous behavior, so existing renderers are unaffected. Both the core and Pro client renderers invoke the teardown on page unload and on same-id node replacement, and cleanup failures on same-id replacement are now logged toconsole.errorinstead of only being visible when tracing is enabled. The renderers differ only in the async race: if a navigation unmounts the mount while an async renderer is still resolving its teardown, Pro still runs the teardown once it resolves, whereas the core renderer is best-effort and may drop a still-pending async teardown while the renderer is awaiting dynamic imports, fetches, or other I/O on a fast navigation; active async renderer failures are logged and then untracked so a later load call can retry. The framework-shipped ProwrapServerComponentRenderernow returns such a teardown wrapper, closing the leak automatically for everyregisterServerComponentuser. TypeScript note: the exportedRendererFunctiontype covers 3-argument renderers that return nothing or an optional teardown wrapper;RenderFunctionkeeps its existing component/server-result return contract, including legacy 3-argument renderers that returned a component only to satisfy the old type. Fixes Issue 3209. PR 3576 by justin808.
Removed
- [Pro] Removed the legacy license key-file migration warning: The elapsed migration notices for the legacy
config/react_on_rails_pro_license.keyfile path (the cleanup notice shown alongside a valid configured license, and the missing-license migration notice) are no longer emitted. The legacy file itself was already unread. Fixes Issue 3624. PR 3715 by justin808.