Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
7 changes: 2 additions & 5 deletions lib/react_on_rails/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ def self.configuration
components_subdirectory: nil,
make_generated_server_bundle_the_entrypoint: false,
defer_generated_component_packs: false,
# React on Rails Pro (licensed) feature - enables immediate hydration of React components
immediate_hydration: false,
# Maximum time in milliseconds to wait for client-side component registration after page load.
# If exceeded, an error will be thrown for server-side rendered components not registered on the client.
# Set to 0 to disable the timeout and wait indefinitely for component registration.
Expand All @@ -64,7 +62,7 @@ class Configuration
:server_render_method, :random_dom_id, :auto_load_bundle,
:same_bundle_for_client_and_server, :rendering_props_extension,
:make_generated_server_bundle_the_entrypoint,
:generated_component_packs_loading_strategy, :immediate_hydration,
:generated_component_packs_loading_strategy,
:component_registry_timeout,
:server_bundle_output_path, :enforce_private_server_bundles

Expand All @@ -81,7 +79,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
same_bundle_for_client_and_server: nil,
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil, i18n_yml_safe_load_options: nil,
random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil,
components_subdirectory: nil, auto_load_bundle: nil, immediate_hydration: nil,
components_subdirectory: nil, auto_load_bundle: nil,
component_registry_timeout: nil, server_bundle_output_path: nil, enforce_private_server_bundles: nil)
self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
self.generated_assets_dirs = generated_assets_dirs
Expand Down Expand Up @@ -122,7 +120,6 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
self.auto_load_bundle = auto_load_bundle
self.make_generated_server_bundle_the_entrypoint = make_generated_server_bundle_the_entrypoint
self.defer_generated_component_packs = defer_generated_component_packs
self.immediate_hydration = immediate_hydration
self.generated_component_packs_loading_strategy = generated_component_packs_loading_strategy
self.server_bundle_output_path = server_bundle_output_path
self.enforce_private_server_bundles = enforce_private_server_bundles
Expand Down
6 changes: 3 additions & 3 deletions lib/react_on_rails/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ module Controller
# JavaScript code.
# props: Named parameter props which is a Ruby Hash or JSON string which contains the properties
# to pass to the redux store.
# immediate_hydration: React on Rails Pro (licensed) feature. Pass as true if you wish to hydrate this
# store immediately instead of waiting for the page to load.
# immediate_hydration: React on Rails Pro (licensed) feature. When nil (default), Pro users get
# immediate hydration, non-Pro users don't. Can be explicitly overridden.
#
# Be sure to include view helper `redux_store_hydration_data` at the end of your layout or view
# or else there will be no client side hydration of your stores.
def redux_store(store_name, props: {}, immediate_hydration: nil)
immediate_hydration = ReactOnRails.configuration.immediate_hydration if immediate_hydration.nil?
immediate_hydration = ReactOnRails::ProUtils.immediate_hydration_enabled? if immediate_hydration.nil?
redux_store_data = { store_name: store_name,
props: props,
immediate_hydration: immediate_hydration }
Expand Down
10 changes: 2 additions & 8 deletions lib/react_on_rails/doctor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ def analyze_server_rendering_config(content)
end
# rubocop:enable Metrics/AbcSize

# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
# rubocop:disable Metrics/CyclomaticComplexity
def analyze_performance_config(content)
checker.add_info("\n⚡ Performance & Loading:")

Expand Down Expand Up @@ -732,19 +732,13 @@ def analyze_performance_config(content)
auto_load_match = content.match(/config\.auto_load_bundle\s*=\s*([^\s\n,]+)/)
checker.add_info(" auto_load_bundle: #{auto_load_match[1]}") if auto_load_match

# Immediate hydration (Pro feature)
immediate_hydration_match = content.match(/config\.immediate_hydration\s*=\s*([^\s\n,]+)/)
if immediate_hydration_match
checker.add_info(" immediate_hydration: #{immediate_hydration_match[1]} (React on Rails Pro)")
end

# Component registry timeout
timeout_match = content.match(/config\.component_registry_timeout\s*=\s*([^\s\n,]+)/)
return unless timeout_match

checker.add_info(" component_registry_timeout: #{timeout_match[1]}ms")
end
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
# rubocop:enable Metrics/CyclomaticComplexity

# rubocop:disable Metrics/AbcSize
def analyze_development_config(content)
Expand Down
6 changes: 3 additions & 3 deletions lib/react_on_rails/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,10 @@ def react_component_hash(component_name, options = {})
# props: Ruby Hash or JSON string which contains the properties to pass to the redux store.
# Options
# defer: false -- pass as true if you wish to render this below your component.
# immediate_hydration: false -- React on Rails Pro (licensed) feature. Pass as true if you wish to
# hydrate this store immediately instead of waiting for the page to load.
# immediate_hydration: nil -- React on Rails Pro (licensed) feature. When nil (default), Pro users
# get immediate hydration, non-Pro users don't. Can be explicitly overridden.
def redux_store(store_name, props: {}, defer: false, immediate_hydration: nil)
immediate_hydration = ReactOnRails.configuration.immediate_hydration if immediate_hydration.nil?
immediate_hydration = ReactOnRails::ProUtils.immediate_hydration_enabled? if immediate_hydration.nil?

redux_store_data = { store_name: store_name,
props: props,
Expand Down
2 changes: 0 additions & 2 deletions lib/react_on_rails/pro_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ def generate_component_script(render_options)
# Generates the complete store hydration script tag.
# Handles both immediate hydration (Pro feature) and standard cases.
def generate_store_script(redux_store_data)
redux_store_data = ReactOnRails::ProUtils.disable_pro_render_options_if_not_licensed(redux_store_data)

store_hydration_data = content_tag(:script,
json_safe_and_pretty(redux_store_data[:props]).html_safe,
type: "application/json",
Expand Down
25 changes: 5 additions & 20 deletions lib/react_on_rails/pro_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,17 @@

module ReactOnRails
module ProUtils
PRO_ONLY_OPTIONS = %i[immediate_hydration].freeze

# Checks if React on Rails Pro features are available
# @return [Boolean] true if Pro is installed and licensed, false otherwise
def self.support_pro_features?
ReactOnRails::Utils.react_on_rails_pro?
end

def self.disable_pro_render_options_if_not_licensed(raw_options)
return raw_options if support_pro_features?

raw_options_after_disable = raw_options.dup

PRO_ONLY_OPTIONS.each do |option|
# Determine if this option is enabled (either explicitly or via global config)
option_enabled = if raw_options[option].nil?
ReactOnRails.configuration.send(option)
else
raw_options[option]
end

# Silently disable the option if it's enabled but Pro is not available
raw_options_after_disable[option] = false if option_enabled
end

raw_options_after_disable
# Returns whether immediate hydration should be enabled
# Pro users always get immediate hydration, non-Pro users never do
# @return [Boolean] true if Pro is available, false otherwise
def self.immediate_hydration_enabled?
support_pro_features?
end
end
end
6 changes: 4 additions & 2 deletions lib/react_on_rails/react_component/render_options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class RenderOptions
# TODO: remove the required for named params
def initialize(react_component_name: required("react_component_name"), options: required("options"))
@react_component_name = react_component_name.camelize
@options = ReactOnRails::ProUtils.disable_pro_render_options_if_not_licensed(options)
@options = options
end

attr_reader :react_component_name
Expand Down Expand Up @@ -97,7 +97,9 @@ def logging_on_server
end

def immediate_hydration
retrieve_configuration_value_for(:immediate_hydration)
options.fetch(:immediate_hydration) do
ReactOnRails::ProUtils.immediate_hydration_enabled?
end
end

def to_s
Expand Down
1 change: 0 additions & 1 deletion spec/dummy/config/initializers/react_on_rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,5 @@ def self.adjust_props_for_client_side_hydration(component_name, props)
config.rendering_props_extension = RenderingPropsExtension
config.components_subdirectory = "startup"
config.auto_load_bundle = true
config.immediate_hydration = false
config.generated_component_packs_loading_strategy = :defer
end
11 changes: 2 additions & 9 deletions spec/dummy/spec/helpers/react_on_rails_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,8 @@ def self.pro_attribution_comment
stub_const("ReactOnRailsPro", pro_module)
stub_const("ReactOnRailsPro::Utils", utils_module)

# Configure immediate_hydration to true for tests since they expect that behavior
ReactOnRails.configure do |config|
config.immediate_hydration = true
end
end

after do
# Reset to default - avoid validation issues by setting directly
ReactOnRails.configuration.immediate_hydration = false
# Stub immediate_hydration_enabled? to return true for tests since they expect that behavior
allow(ReactOnRails::ProUtils).to receive(:immediate_hydration_enabled?).and_return(true)
end

let(:hash) do
Expand Down
7 changes: 2 additions & 5 deletions spec/dummy/spec/system/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,9 @@ def self.pro_attribution_comment
end
stub_const("ReactOnRailsPro", pro_module)
stub_const("ReactOnRailsPro::Utils", utils_module)
end

around do |example|
ReactOnRails.configure { |config| config.immediate_hydration = true }
example.run
ReactOnRails.configure { |config| config.immediate_hydration = false }
# Stub immediate_hydration_enabled? to return true for tests since they expect that behavior
allow(ReactOnRails::ProUtils).to receive(:immediate_hydration_enabled?).and_return(true)
end
end

Expand Down
Loading