docs/oss/upgrading/release-notes/16.0.0.md
Also see the Changelog for 16.0.0.
Note: Version 15.0.0 has been retracted. Please upgrade directly from v14 to v16.
Experience the future of React with full RSC integration in your Rails apps:
React on Rails now starts hydration even before the full page is loaded! This revolutionary change delivers significant performance improvements across all pages:
async scripts without fear of race conditionsdefer to prevent race conditions has been eliminatedThis optimization is particularly impactful for:
Performance improvement visualization:
The image above demonstrates the dramatic performance improvement:
generated_component_packs_loading_strategy replaces defer_generated_component_packs:async - Loads scripts asynchronously (default for Shakapacker ≥ 8.2.0):defer - Defers script execution until after page load (doesn't work well with Streamed HTML as it will wait for the full page load before hydrating the components):sync - Loads scripts synchronously (default for Shakapacker < 8.2.0) (better to upgrade to Shakapacker 8.2.0 and use :async strategy)The defer_generated_component_packs configuration has been deprecated. Use generated_component_packs_loading_strategy instead.
The generated_component_packs_loading_strategy defaults to :async for Shakapacker ≥ 8.2.0 and :sync for Shakapacker < 8.2.0.
The immediate_hydration configuration now defaults to false. Note: immediate_hydration is a React on Rails Pro (licensed) feature.
When generated_component_packs_loading_strategy: :async and immediate_hydration: true are configured together, they optimize component hydration. Components hydrate as soon as their code and server-rendered HTML are available, without waiting for the full page to load. This parallel processing significantly improves time-to-interactive by eliminating the traditional waterfall of waiting for page load before beginning hydration (It's critical for streamed HTML).
immediate_hydration configuration (React on Rails Pro licensed feature) makes react-on-rails hydrate components immediately as soon as their server-rendered HTML reaches the client, without waiting for the full page load.immediate_hydration: true in your config/initializers/react_on_rails.rb file (requires React on Rails Pro license).
immediate_hydration: true to react_component or stream_react_component.immediate_hydration option (React on Rails Pro licensed feature), which defaults to config.immediate_hydration (and so to false if that isn't set). If true, the Redux store will hydrate immediately as soon as its server-side data reaches the client.
redux_store helper with immediate_hydration: true or immediate_hydration: false, same as react_component.ReactOnRails.reactOnRailsPageLoaded() is now an async function:
If you manually call this function to ensure components are hydrated (e.g., with async script loading), you must now await the promise it returns:
// Before
ReactOnRails.reactOnRailsPageLoaded();
// Code expecting all components to be hydrated
// After
await ReactOnRails.reactOnRailsPageLoaded();
// Code expecting all components to be hydrated
If you call it in a turbolinks:load listener to work around the issue documented in Turbolinks, the listener can be safely removed.
defer_generated_component_packs: true, use generated_component_packs_loading_strategy: :defer insteaddefer_generated_component_packs: false, use generated_component_packs_loading_strategy: :sync insteadgenerated_component_packs_loading_strategy: :asyncThe package is now published as ES Modules instead of CommonJS. In most cases it shouldn't affect your code, as bundlers will be able to handle it. However:
require('react-on-rails'), and can't change to import, upgrade to Node v20.19.0+ or v22.12.0+. They allow require for ESM modules without any flags. Node v20.17.0+ with --experimental-require-module should work as well.TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. TypeScript error, you'll need to upgrade to TypeScript 5.8 and set module to nodenext.Finally, if everything else fails, please contact us and we'll help you upgrade or release a dual ESM-CJS version.
globalThisglobalThis is now used in code.
It should be available in browsers since 2020 and in Node, but in case your environment doesn't support it, you'll need to shim it using globalthis or core-js.
When using Redux stores with multiple components, you need to explicitly declare store dependencies to optimize hydration. Here's how:
If you have deferred Redux stores and components like this:
<% redux_store("SimpleStore", props: @app_props_server_render, defer: true) %>
<%= react_component('ReduxApp', {}, {prerender: true}) %>
<%= react_component('ComponentWithNoStore', {}, {prerender: true}) %>
<%= redux_store_hydration_data %>
By default, React on Rails assumes components depend on all previously created stores. This means:
ReduxApp nor ComponentWithNoStore will hydrate until SimpleStore is hydratedExplicitly declare store dependencies for each component:
<% redux_store("SimpleStore", props: @app_props_server_render, defer: true) %>
<%= react_component('ReduxApp', {}, {
prerender: true
# No need to specify store_dependencies: it automatically depends on SimpleStore
}) %>
<%= react_component('ComponentWithNoStore', {}, {
prerender: true,
# Explicitly declare no store dependencies
store_dependencies: []
}) %>
<%= redux_store_hydration_data %>
This allows ComponentWithNoStore to hydrate immediately without waiting for SimpleStore, improving page performance.