Skip to content

v17.0.0.rc.7

Pre-release
Pre-release

Choose a tag to compare

@justin808 justin808 released this 07 Jul 09:28

Breaking Changes

  • [Pro] React Server Components now require the React 19.2.x RSC line: React on Rails Pro 17 raises the optional RSC peer and runtime floor from react-on-rails-rsc 19.0.x to stable 19.2.x with patch >= 19.2.1. Apps using Pro RSC should upgrade react-on-rails-rsc to stable 19.2.x with patch >= 19.2.1 and React/React DOM to 19.2.x with patch >= 19.2.7. The release-candidate peer range accepts 19.2.1-rc.0 so the RC soak path can install before the stable package is published, and the Pro RSC generator now scaffolds the coordinated React 19.2.7 / react-on-rails-rsc 19.2.1-rc.0 pair. This is a breaking change for Pro RSC apps still on the 19.0.x RSC package line; the existing REACT_ON_RAILS_PRO_DISABLE_VERSION_CHECK=1 escape hatch still downgrades the startup error to a warning for emergency rollouts. PR 4490 by justin808.
  • Removed the inert config.server_render_method option: The open-source configuration no longer accepts config.server_render_method. The option never selected a server render method — the open-source gem always renders with ExecJS — and its validator raised ReactOnRails::Error at boot for any value other than blank or "ExecJS". Setting it now raises NoMethodError at boot, so delete any config.server_render_method = ... line from config/initializers/react_on_rails.rb; rake react_on_rails:doctor also flags the stale line. For a standalone Node rendering process, use React on Rails Pro's Node renderer, configured via ReactOnRailsPro.configure. Fixes Issue 4415. PR 4423 by justin808.
  • Removed three deprecated configuration options (config.generated_assets_dirs, config.skip_display_none, config.defer_generated_component_packs): These were deprecated in v16 and are gone in v17. Setting any of them now raises NoMethodError at boot; delete the stale lines from config/initializers/react_on_rails.rb (rake react_on_rails:doctor flags them). Migration: delete config.generated_assets_dirs — public asset paths come from public_output_path in config/shakapacker.yml; delete config.skip_display_none — it had no runtime effect; replace config.defer_generated_component_packs = true with config.generated_component_packs_loading_strategy = :defer, and simply delete config.defer_generated_component_packs = false (the removed option was truthy-gated — only = true set :defer; = false was a no-op that fell through to the default strategy, so it did not mean :sync; set :sync explicitly only if you relied on synchronous loading). The default strategy is :async for Pro or :defer for non-Pro on Shakapacker 8.2.0+, and :sync on older Shakapacker. Fixes Issue 4419. PR 4432 by justin808.
  • Removed the never-wired RenderRequest / JsCodeBuilder / RenderingStrategy rendering layer: The internal strategy-pattern classes ReactOnRails::RenderRequest, ReactOnRails::JsCodeBuilder, ReactOnRails::RenderingStrategy (with ExecJsStrategy), and — in Pro — ReactOnRailsPro::JsCodeBuilder and ReactOnRailsPro::RenderingStrategy::NodeStrategy, plus the undocumented ReactOnRails.rendering_strategy and ReactOnRails.js_code_builder module accessors, are removed. This scaffolding was built for the strategy-pattern refactor in Issue 2905 (closed without wiring it in) and was never invoked on any production server-rendering path — SSR runs through ServerRenderingJsCode and ServerRenderingPool, which never touched this layer. These constants and accessors were internal and undocumented; if you reference them in application code, remove the reference (the layer performed no work). Fixes Issue 4414. PR 4437 by justin808.

Added

  • Generated Rails response TypeScript contracts: Rails apps can now register explicit JSON response
    contracts with ReactOnRails::TypeScriptResponseTypes and run
    rake react_on_rails:generate_response_types to emit importable .d.ts declarations plus a
    RailsResponseTypes lookup map for TanStack Query clients. Fixes
    Issue 4247. PR 4259 by justin808.

  • Typed Rails action callers for TanStack Query mutations: The react-on-rails/railsAction
    subpath now exports createRailsAction, a same-origin JSON caller that attaches Rails CSRF headers and
    lets mutation code type responses with the generated RailsResponseType<'controller.action'> lookup.
    Fixes Issue 4248. PR 4260 by justin808.

  • [Pro] Typed Rails action callers for TanStack Query mutations: The Pro package mirrors the
    createRailsAction helper at react-on-rails-pro/railsAction. PR 4260 by justin808.

  • [Pro] Loader-time RSC prefetch through the provider cache: Client-router loaders can now
    call prefetchServerComponent to warm a bounded page-global prefetch store that RSCProvider
    adopts on the next RSCRoute render. Prefetches no-op when the SSR payload is already embedded,
    support loader abort signals, and resolve without unhandled rejections after fetch/decode failure
    self-eviction. Fixes Issue 4460.
    PR 4489 by
    justin808.

  • bin/dev clean clears generated bundles and caches: The command stops development processes, reads config/shakapacker.yml or SHAKAPACKER_CONFIG, removes configured Shakapacker public/private output and cache paths plus common Rails, JavaScript, and renderer bundle caches, and skips unsafe paths outside the app root. PR 4218 by justin808.

  • [Pro] Buffered RSC rendering for static pages:
    buffered_stream_react_component and cached_buffered_stream_react_component
    now render server components through the Pro streaming/RSC renderer while
    returning complete HTML to Rails, so static or cacheable pages can avoid
    ActionController::Live response commits when progressive streaming is not
    needed. When RSC support is enabled, prerendered Pro fragment cache keys now
    include the RSC bundle digest, or a missing-bundle sentinel until that bundle
    exists, so deploys that update only the RSC bundle invalidate cached RSC output
    consistently. Fixes
    Issue 4263.
    PR 4268 by
    justin808.

  • [Pro] Cached static RSC public-page helper and diagnostics:
    cached_static_rsc_component caches stripped static RSC HTML for public pages
    that intentionally skip the generated page pack, while respecting
    auto_load_bundle: false and preserving explicit sidecar assets. Static RSC
    render diagnostics report cache hit/miss state, redacted cache-key digests,
    HTML and stripped payload bytes, emitted asset bytes, and RSC client-reference
    entries for performance investigations. Fixes
    Issue 4295 and
    Issue 4296.
    PR 4386 by
    justin808.

  • [Pro] Opt-in browser performance marks for streamed RSC observability: Pro streaming can now emit inline browser marks for RSC stream completion, embedded Flight payload chunks, Node-side flushes, hydration start, and first interactive client effects, with byte counts and timing details that avoid serialized props or payload contents. The documented path uses body-delivered marks and a fallback queue instead of HTTP trailers, so apps can measure streamed RSC responses across CDN paths that may strip or hide trailer timing. Fixes Issue 4205, Issue 4206, and Issue 4207. PR 4222 by justin808.

  • [Pro] Server-Timing attribution for streamed RSC responses: When rsc_stream_observability: true, the streamed RSC response now also carries a Server-Timing response header with a ror_stream_shell metric (Rails shell render, including the blocking wait for each component's first renderer chunk), set in the narrow window before ActionController::Live commits headers and appended to any existing Server-Timing entries. The Node renderer additionally emits a ror_renderer_prepare metric (execution-context build plus render start) on its HTTP response. This is the server/renderer-side complement to the browser performance marks above, letting a reviewer attribute the streamed responseEnd tail to a specific phase rather than guessing. Total/stream-complete time stays on the react-on-rails:rsc:stream mark because ActionController::Live does not support HTTP trailers. Closes Issue 4239. PR 4251 by justin808.

  • [Pro] Focused RSC doctor artifact diagnostics: rake react_on_rails:doctor:rsc and
    Doctor.new(only: ...) now run the RSC artifact checks directly, reporting missing,
    stale, invalid, or dev-server-backed RSC bundle and manifest files with rebuild guidance
    while explaining when Pro path resolution is unavailable. Closes
    Issue 4204.
    PR 4223 by
    justin808.

Changed

  • [Pro] Reduced tag-index cache work for streamed cache writes: Multi-tag cache registration now
    batch-reads existing tag indexes when supported, and streamed cache misses defer cache writes and tag
    registration until queued response chunks have drained. Streamed and async cache misses also register tags
    with the same completion-time cache options used for the cache write, keeping TTL snapshots aligned. Fixes
    Issue 4319.
    PR 4443 by
    justin808.

  • Lighter npx create-react-on-rails-app install: The scaffolder now colorizes its terminal output with the zero-dependency picocolors instead of chalk@4, dropping chalk and its transitive tree (ansi-styles, supports-color, color-convert, color-name, has-flag) from the package's runtime dependencies. This trims the weight of every cold npx create-react-on-rails-app install. The TTY color-fallback now also mirrors chalk@4/supports-color's actual signal precedence (recognized CI vendors, TERM, COLORTERM, Windows) instead of coloring any non-dumb TTY, matching the prior colored-output behavior in full. Fixes Issue 4411 and Issue 4455. PR 4444 and PR 4473 by justin808.

  • [Pro] Removed unused addressable/rainbow runtime gem dependencies: react_on_rails_pro.gemspec no longer declares direct runtime dependencies on addressable or rainbow — no Pro Ruby code referenced either gem, and both still arrive transitively through the required react_on_rails gem, so behavior is unchanged. Fixes Issue 4416. PR 4422 by justin808.

  • [Pro] Fail fast for RSC with Rspack v1: When React Server Components are enabled and Shakapacker is
    configured for Rspack, app boot and react_on_rails:doctor now reject @rspack/core v1 or a missing
    @rspack/core package with explicit Rspack v2 upgrade instructions. This guard only runs when RSC is enabled,
    so Rspack v1 remains allowed for non-RSC apps, and bundler detection now honors SHAKAPACKER_ASSETS_BUNDLER
    before config/shakapacker.yml.
    PR 4289 by justin808.

  • Redux is now hidden from the V17 install generator path: The react_on_rails:install --redux option is no longer shown in install generator help or usage text, and recovery guidance no longer recommends --redux for new installs. The hidden legacy path and direct react_on_rails:react_with_redux generator now warn that Redux scaffolding is legacy while keeping runtime Redux APIs available. Closes Issue 4272 and Issue 4273. PR 4277 by justin808.

  • create-react-on-rails-app now defaults to Pro for React 19.2 support: Running
    npx create-react-on-rails-app my-app no longer asks setup questions and generates the recommended
    React on Rails Pro scaffold by default. Automation note: non-TTY environments, including CI and piped
    commands, previously auto-selected Standard mode; they now select Pro. Add --standard to any command
    that intentionally checks or creates an open-source-only scaffold. Use --rsc when you want Pro with the
    generated React Server Components example. The canonical reactonrails.com "Start a new app" AI-agent
    prompt (prompts.yml) was updated to match, so AI assistants following it also default to the Pro path
    and mention the license requirement. PR 4217 and
    PR 4232 by justin808.

  • [Pro] Missing renderer password error now leads with the local-development fix: When the Pro renderer password is unset and both RAILS_ENV and NODE_ENV are unset, the fail-closed error from both the Ruby configuration guard and the Node renderer now includes explicit export RAILS_ENV=development NODE_ENV=development guidance. Password-optional behavior for explicit development/test envs and password-required behavior for production-like or mixed envs are unchanged. Fixes Issue 4201. PR 4211 by justin808.

Fixed

  • hydrate_on: visible no longer leaks a detached root or blocks re-hydrating a replacement node: When a hydrate_on: visible target was detached from the DOM before it became visible, the intersection observer left a stale scheduled root entry that kept the removed node reachable and could stop a replacement node with the same DOM id from scheduling its own hydration. The observer now runs its scheduled callback after disconnecting from a detached target; the callback's existing isConnected guard deletes the stale entry without hydrating the removed node, so a fresh node with the same id schedules cleanly. Fixes Issue 4328. PR 4374 by justin808.

  • [Pro] RSCRoute error recovery now covers synchronous route failures and fire-and-forget retries: Synchronous throws from RSC route fetch/render setup are normalized into rejected fetch promises so they flow through the same RSCRoute error-recovery path (and RSCRouteErrorBoundary) as async fetch failures instead of bypassing it, keeping retry/refetch bookkeeping consistent when a fetch fails synchronously. Fire-and-forget recover-on-error retries also no longer surface as unhandled promise rejections in production: the caller-visible retry promise stays rejected for callers that await or catch it, while an internal no-op handler prevents an unhandled rejection when the retry is not awaited. Fixes Issue 4330 and Issue 4372. PR 4378 and PR 4393 by justin808.

  • [Pro] Node renderer rejects unsafe asset filenames: The Pro Node renderer now rejects path-like,
    drive-relative, alternate-stream, and control-character asset filenames before uploaded assets are copied
    or /asset-exists probes bundle directories, returning a 400 without reporting rejected names to the
    error reporter. PR 4285 by
    ihabadham.

  • [Pro] Streamed RSC responses now append the Node renderer's ror_renderer_prepare
    metric to the browser-visible Server-Timing header while preserving existing
    Rails/application entries, so rsc_stream_observability exposes renderer prepare
    time without relying on HTTP trailers. Closes
    Issue 4479.
    PR 4487 by
    justin808.

  • [Pro] Streaming component caches honor cache_options on reads: cached_stream_react_component
    wrote cached chunks with the user-supplied cache_options but read them back without any options, so
    key-altering options such as namespace: meant the cache never hit and every request re-streamed from
    the renderer (a bare read could even return a stale un-namespaced entry for the same logical key). Reads
    now pass the same normalized options as the deferred write, and the lower-level streaming prerender cache
    (ReactOnRailsPro::StreamCache.fetch_stream) likewise accepts and applies the cache_options its write
    path uses. PR 4452 by
    ihabadham.

  • [Pro] Sync RSC route failures surface as ServerComponentFetchError: Synchronous throws
    in the RSC payload path (payload key creation on BigInt/circular props, sync
    getServerComponent throws, fetchRSC request preparation) previously bypassed
    RSCRouteErrorBoundary, so user error boundaries received raw TypeErrors without component
    metadata. All sync and async failure paths now funnel through the boundary, and a nested route's
    already-wrapped error passes through without re-wrapping. Fixes
    Issue 4372.
    PR 4438 by
    justin808.

  • [Pro] RSC payload streaming flushes complete HTML before incomplete tails: The Pro RSC
    payload injector now streams the complete prefix of each chunk immediately while retaining only
    incomplete UTF-8 sequences, HTML tags, comments, template content, raw-text elements, or
    foreign-content tails for the next chunk. This preserves progressive streaming when a chunk ends
    in partial markup instead of holding the entire flush until the tail completes. Fixes
    Issue 4327.
    PR 4379 by
    justin808.

  • [Pro] Truncated RSC parser streams now warn at EOF: The Pro RSC length-prefixed stream
    parser flushes at stream end so incomplete trailing records emit the existing parser warning,
    while expected request-abort cleanup remains quiet.
    PR 4392 by
    justin808.

  • ReactOnRails.getStore(name, false) no longer throws when no stores are hydrated: With
    throwIfMissing = false, getStore now returns undefined when the hydrated-store registry is
    empty — matching its documented contract and its existing behavior when other stores are hydrated —
    in both the open-source and Pro JS packages. Default strict calls still throw the descriptive
    "There are no stores hydrated" / "Could not find hydrated store" errors.
    PR 4457 by
    ihabadham.

  • [Pro] RSC stylesheet inference retries after transient stats read failures: Pro now caches
    client-chunk stylesheet metadata only after a successful loadable-stats.json read, so a
    deploy-race or temporary parse/read failure does not disable inferred RSC client stylesheets for
    the worker lifetime.
    PR 4401 by
    justin808.

  • [Pro] RSC loadable-stats retry diagnostics stay visible: Malformed or unreadable
    loadable-stats.json warnings are suppressed only for the retry window, and native ESM stack
    paths rewritten through source maps are normalized back to the runtime lib/ directory before
    resolving stats.
    PR 4447 by
    justin808.

  • [Pro] RSC client fetch failures no longer include serialized props in thrown error messages or causes:
    Browser RSC requests still send the real ?props=... payload to the Rails endpoint, but pre-response fetch
    failures now report the query-free component source path with a stable generic message so console logs, error
    boundaries, and error reporters do not capture accidental sensitive values from props. Retry props remain
    directly readable for refetches but are no longer enumerable error fields. Fixes
    Issue 4449.
    PR 4450 by
    ihabadham.

  • [Pro] Node renderer graceful shutdown and scheduled restarts: Worker shutdown now counts
    each active request once across response, abort, and timeout hooks; scheduled restart timeouts use
    documented seconds; draining workers skip only the early master SIGKILL while keeping the hard
    shutdown deadline; and stale scheduled-restart workers no longer break the restart loop. Fixes
    Issue 4365,
    Issue 4366,
    Issue 4367, and
    Issue 4368.
    PR 4400 by
    justin808.

  • [Pro] Response-start send failures are reported during abandoned incremental renders:
    The Pro node renderer now observes and reports rejected response-start/send promises when
    incremental render request handling stops early or errors after a response starts, while still
    propagating those failures on clean stream completion. Fixes
    Issue 4364.
    PR 4389 by
    justin808.

  • [Pro] Async-props prerender stream cache isolation: Pro prerender stream caching now
    bypasses renders that use async props, so per-request async stream output cannot be replayed from
    another request's cached stream. Fixes
    Issue 4359.
    PR 4376 by
    justin808.

  • Preload links stay compatible with older Shakapacker: react_on_rails_preload_links now
    skips SRI attributes when Shakapacker does not expose integrity settings, avoiding a
    NoMethodError while still emitting preload hints. Fixes
    Issue 4369.
    PR 4377 by
    justin808.

  • [Pro] Renderer HTTP transport no longer buffers successful streams or duplicate bundle uploads:
    Pro renderer requests now pass successful streaming response chunks through without retaining them in Ruby
    memory, reuse a persistent async-http client for plain Puma non-streaming requests, reset scheduler-scoped
    clients when the shared renderer connection is reset, and stream/deduplicate same-bundle uploads. Plain Puma
    reuse is per request-handling thread, so total renderer connection capacity can scale with Puma threads times
    renderer_http_pool_size; tune the renderer and any intermediaries accordingly. Fixes
    Issue 4360,
    Issue 4361,
    Issue 4362, and
    Issue 4363.
    PR 4394 by
    justin808.

  • [Pro] Streaming dependency load errors stay visible: Pro streaming cleanup now tolerates dependency
    load failures that happen before stream observability state is captured, so the original LoadError
    remains visible instead of being masked by cleanup. Fixes
    Issue 4324.
    PR 4388 by
    justin808.

  • [Pro] Tag revalidation keeps retry metadata after entry delete failures:
    ReactOnRailsPro.revalidate_tag now restores the tag index before re-raising when tagged
    cache-entry deletion fails, so transient cache-store failures leave retry metadata instead
    of orphaning stale entries until their TTL expires. Fixes
    Issue 4317.
    PR 4375 by
    justin808.

  • hydrate_on: nil falls back to immediate hydration: Passing hydrate_on: nil now behaves
    like the default :immediate mode instead of raising, while invalid explicit values still fail
    fast. Fixes Issue 4342.
    PR 4350 by
    justin808.

  • [Pro] Incremental render setup failures release renderer context:
    The Pro node renderer now releases the execution context and destroys started streams when
    pull-mode incremental render setup fails, preventing orphaned renderer work after response-start
    errors. Fixes Issue 4312.
    PR 4383 by
    justin808.

  • [Pro] Dropped pull-mode prop requests are logged: Streaming SSR now warns when the Node
    renderer sends a propRequest control frame without an emitter or with a missing, empty, or
    oversized propName, making dropped pull-mode requests diagnosable while preserving valid
    enqueue and renderComplete behavior. Fixes
    Issue 4314.
    PR 4352 by
    justin808.

  • [Pro] RSC preload replay survives cache eviction: Preloaded RSC payloads now remain
    replayable after route cache eviction, preventing stale preload state from breaking refetches.
    Fixes Issue 4326.
    PR 4353 by
    justin808.

  • [Pro] Incremental stream timers stay aligned with active chunks: Healthy pull-mode
    incremental streams are no longer closed by stale request or finish timers while chunks keep
    progressing, while abandoned streams remain bounded by an idle watchdog. Fixes
    Issue 4310 and
    Issue 4311.
    PR 4354 by
    justin808.

  • [Pro] RSC Rspack boot validation warns on undetermined versions: Boot now warns and continues when
    the active Rspack version cannot be determined, while strict doctor checks and provable Rspack v1
    failures still fail closed. Fixes Issue 4340.
    PR 4355 by
    justin808.

  • [Pro] Registry cleanup handles page-unload cancellations safely: Pending component and store
    registry waits are now rejected when a page unloads or store generators are cleared, stale registry
    timeouts are cleared, and expected navigation cancellations are ignored during client rendering while
    real registration failures still surface. PR 4282
    by justin808.

  • [Pro] Gemfile loader source encodings are honored under C/POSIX locales:
    The Pro Gemfile now loads its shared dependency fragments in binary mode, applies Ruby
    source-encoding magic comments or a UTF-8 default, and validates content before override-gem
    scanning and evaluation. This affects any environment that evaluates the Pro Gemfile through
    Bundler, including local setup and CI, so Pro apps with non-ASCII dependency comments no longer
    fail under shells where Ruby's default external encoding is US-ASCII. Fixes
    Issue 4276.
    PR 4281 by
    justin808.

  • [Pro] Cached component hits load generated packs consistently:
    Pro cached component helpers now share the ReactOnRailsPro::Cache.fetch_react_component path and
    run the cache-hit pack-loading callback, so cached cached_react_component and
    cached_react_component_hash output preserves generated pack behavior. Fixes
    Issue 4316.
    PR 4384 by
    justin808.

  • Precompile hook no longer forces UTF-8 onto a non-UTF-8 locale:
    The shared Shakapacker precompile hook now widens a spawned bundle exec / shakapacker subprocess
    to UTF-8 only under a bare C/POSIX locale, where the locale-derived encoding is US-ASCII — a
    strict subset of UTF-8, so the widening cannot corrupt genuinely-ASCII content. Under a real
    national locale (for example a Brazilian developer's LANG=pt_BR.ISO8859-1) it now leaves
    LANG/LC_ALL/RUBYOPT untouched and lets the child inherit the working locale, instead of
    force-pinning -EUTF-8 and re-decoding the developer's latin-1/CP1252 source files as UTF-8 (which
    raised invalid byte sequence in UTF-8). The locale gate reads Encoding.find("locale") so it is
    not masked by Rails setting Encoding.default_external to UTF-8 at boot. This removes the
    RUBYOPT-rewriting machinery added in
    PR 4231 while keeping the original
    C/POSIX-locale crash fix from
    PR 4169.
    PR 4244 by
    justin808.

  • [Pro] RSC Rspack doctor no longer false-warns on equivalent lazyCompilation configs:
    react_on_rails:doctor:rsc only recognizes the generated literal
    clientWebpackConfig.lazyCompilation = false assignment. Apps that disable lazy
    compilation an equivalent way (object form, Object.assign, a helper, a ternary,
    or a different config file) now get a warning that says doctor could not confirm
    the setting rather than asserting lazy compilation is still enabled, plus guidance
    to confirm the effective dev-server config and ignore the warning if it is already
    disabled. Follow-up to
    PR 4234.
    PR 4249 by
    justin808.

  • Generated Tailwind apps load Tailwind from the layout. The install generator now declares Tailwind through a layout-owned pack instead of component-owned imports, keeps generated layout head metadata mobile/CSP-ready, and warns safely when custom layouts need manual pack-tag replacement. PR 4182 by ihabadham.

  • [Pro] Rspack RSC dev-server setup is easier to diagnose and customize:
    Generated RSC helper code now verifies client-reference discovery support
    through the sibling rscWebpackConfig.js file instead of assuming
    config/webpack, so Rspack apps keep using config/rspack/rscWebpackConfig.js.
    The RSC doctor also warns existing Rspack apps when normal bin/dev can leave
    the React Client Manifest empty because lazyCompilation is still enabled,
    and the troubleshooting guide documents the lazy-compilation-proxy /
    POST /_rspack/lazy/trigger 404 symptom path. Follow-up to
    PR 4227.
    PR 4234 by
    justin808.

  • Precompile hook UTF-8 hardening now handles conflicting RUBYOPT encoding flags:
    The shared Shakapacker precompile hook strips pre-existing Ruby encoding flags such as
    -EUS-ASCII, --encoding=US-ASCII, --external-encoding=US-ASCII, and
    --internal-encoding=US-ASCII before pinning subprocesses to -EUTF-8:UTF-8, so C/POSIX-locale
    builds do not crash when the parent shell exports a conflicting RUBYOPT. The shipped generated
    bin/shakapacker-precompile-hook template now uses the same UTF-8 subprocess environment for RSC
    client-reference discovery. Follow-up to
    PR 4169.
    PR 4231 by
    justin808.

  • [Pro] Generated RSC + Rspack apps render in normal bin/dev:
    RSC + Rspack generator output now disables Rspack lazy compilation while the
    dev server is running, so discovered client references are compiled before
    the React Client Manifest is read during server rendering. Fresh generated
    apps no longer fail /hello_server with an empty react-client-manifest.json
    in normal HMR mode. Fixes Issue 4226.
    PR 4227 by
    ihabadham.

  • [Pro] RSC doctor now catches stale install and client-manifest setup failures:
    The doctor now validates installed react-on-rails-rsc peer requirements
    against react and react-dom, warns when the installed RSC package is
    behind newer prerelease npm dist-tags, and reports missing, dev-server-backed,
    invalid, or empty RSC client manifests with bin/dev static and clean rebuild
    guidance. Pro RSC render errors that fail to resolve a React Client Manifest
    module now include the same stale/empty/cross-version manifest hint instead of
    leaving the upstream "probably a bug in the RSC bundler" text as the only clue.
    Fixes Issue 4198
    and Issue 4200;
    addresses Issue 4199
    and scopes Issue 4204.
    PR 4213 by
    justin808.

  • Dummy app setup uses native Nokogiri gems on macOS: The dummy app lockfile now includes Darwin platforms so bin/setup installs native Nokogiri gems on Apple Silicon and Intel macOS instead of attempting a source build that can fail with a missing nokogiri_gumbo.h header. PR 4218 by justin808.

  • [Pro] ScoutApm Node renderer instrumentation no longer depends on Gemfile load order: Pro now installs NodeRenderingPool.exec_server_render_js instrumentation from a Rails engine initializer that runs after scout_apm.start, instead of checking defined?(ScoutApm) at class load time. Apps without ScoutApm still boot normally, and apps that load scout_apm after react_on_rails_pro no longer silently skip the Pro Node renderer span. Fixes Issue 4208. PR 4210 by justin808.

  • [Pro] RSCProvider now evicts a rejected getComponent promise so transient failures can retry: When the underlying RSC fetch for getComponent rejected — a transient renderer/network/deploy failure — the rejected promise stayed in the provider's bounded payload cache, so every later same-key getComponent returned that cached rejection and the RSC route/component stayed wedged in its error state even after the backend recovered; only an explicit refetchComponent or a full reload cleared it. getComponent now attaches a rejection handler that re-throws (so React's Suspense machinery still observes the failure) and evicts the cached entry one macrotask later, guarded on promise identity so a newer same-key getComponent/refetchComponent started in that window is never evicted by the stale failure. Pins are preserved so the existing .finally() still owns the matching unpin. Payloads that resolve with an Error value are intentionally left cached — that retryability is a separate getServerComponent contract decision. Fixes Issue 3929. PR 4189 by justin808.

  • [Pro] Clear page-scoped RSC payload globals on client navigation: Pro's client-navigation teardown (unmountAll, fired on page unload) now deletes the page-scoped REACT_ON_RAILS_RSC_PAYLOADS and REACT_ON_RAILS_RSC_ERRORS globals that injected RSC payload <script> tags populate during server-streamed hydration. Previously they were left in place after components and stores unmounted, so they accumulated one entry per embedded RSC component for the life of a long-lived client-navigation (Turbo) session; and with non-random DOM ids (config.random_dom_id = false) a revisited payload key could append the next page's streamed chunks onto the previous page's array. Same-page streaming (the ||= append used while a page is still rendering) is unchanged. This affects only the not-yet-released Pro RSC feature, so no published version is impacted. Closes Issue 3932. PR 4023 by justin808.

  • [Pro] Precompile hook no longer crashes under a non-UTF-8 (C/POSIX) locale: The shared Shakapacker precompile hook now forces a UTF-8 locale on every bundle exec / shakapacker subprocess it spawns — pack generation, the i18n locale generation added in PR 4128, and the RSC client-reference discovery build. Without LANG/LC_ALL set, those children inherited a US-ASCII default external encoding and died parsing Gemfiles containing non-ASCII bytes (e.g. react_on_rails_pro/Gemfile.loader: invalid byte sequence in US-ASCII), aborting the entire precompile. Extends the UTF-8 hardening from PR 3949 from the hook's own file reads to the subprocess boundary. PR 4169 by justin808.

  • OSS renders no longer compute or emit Pro-only generated-stylesheet metadata: Rendering a component
    now skips generated_stylesheet_hrefs_json's stylesheet-href discovery entirely when React on Rails Pro
    is not installed, instead of running that Pro-only work on every open-source render. Fixes
    Issue 4341.
    PR 4395 by
    justin808.

  • create_render_options no longer mutates the caller's options hash: Adding default store
    dependencies and internal stream-observability state now operates on a duplicate of the supplied
    options, so a frozen or reused options hash passed to a helper no longer raises FrozenError or leaks
    observability state into a later render that reuses the same hash. Fixes
    Issue 4343.
    PR 4396 by
    justin808.

  • Locale-file regeneration check no longer reads the whole generated file, and correctly detects a
    legacy import after custom content
    : The obsolete-locale-file check now streams default.js line by
    line, stopping as soon as it finds either the legacy react-intl/defineMessages import (regenerate)
    or the current const defaultLocale = ... marker (up to date), instead of reading and matching the
    entire file from the start. This also fixes a false negative where a legacy import following custom
    file content was not detected. Fixes Issue 4345.
    PR 4398 by
    justin808.

  • [Pro] Static RSC payload script stripping is robust to generated body-shape changes: Pro-generated
    RSC initialization, payload-chunk, and diagnostic <script> tags now carry an explicit
    data-react-on-rails-rsc-payload="true" marker, and static RSC cache stripping
    (cached_static_rsc_component) now prefers that marker over inferring payload scripts from body shape,
    while still falling back to the previous shape-based detection for older generated HTML. Fixes
    Issue 4459.
    PR 4477 by
    justin808.

Removed

  • [Pro] Removed the react-on-rails-pro/rscPayloadNode export and its createRscPayloadNode helper: The duplicate RSC payload route-data API added during the 17.0 RC line (in PR 3783) is gone; RSCRoute is the canonical Pro RSC client-router integration. Client-router loaders return plain route data (componentName, componentProps) and route components render RSCRoute, which keeps React on Rails Pro in control of payload fetching, caching, embedded SSR payload reuse, and retry behavior. This affects only the not-yet-released Pro RSC feature line. Fixes Issue 4439. PR 4440 by ihabadham.