Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 8 additions & 7 deletions lib/react_on_rails/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ def check_component_registry_timeout
raise ReactOnRails::Error, "component_registry_timeout must be a positive integer"
end

# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
def validate_generated_component_packs_loading_strategy
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity

if defer_generated_component_packs
if %i[async sync].include?(generated_component_packs_loading_strategy)
Expand All @@ -176,11 +176,12 @@ def validate_generated_component_packs_loading_strategy
1. Use :defer or :sync loading strategy instead of :async
2. Upgrade to Shakapacker v8.2.0 or above to enable async script loading
MSG
if generated_component_packs_loading_strategy.nil?
# Use defer as the default to ensure generated component packs load and register
# components before main bundle executes, avoiding race conditions with async loading
self.generated_component_packs_loading_strategy = :defer
elsif generated_component_packs_loading_strategy == :async && !PackerUtils.supports_async_loading?
if PackerUtils.supports_async_loading?
self.generated_component_packs_loading_strategy ||= :async
elsif generated_component_packs_loading_strategy.nil?
Rails.logger.warn("**WARNING** #{msg}")
self.generated_component_packs_loading_strategy = :sync
elsif generated_component_packs_loading_strategy == :async
raise ReactOnRails::Error, "**ERROR** #{msg}"
end

Expand Down
14 changes: 10 additions & 4 deletions spec/dummy/app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@

<%= yield :head %>

<%# Use defer: true to ensure proper script execution order.
When using generated component packs (auto_load_bundle), defer ensures
component registrations complete before React hydration begins. %>
<%= javascript_pack_tag('client-bundle', 'data-turbo-track': 'reload', defer: true) %>
<%# Conditionally use defer: true for pages with Redux shared stores (inline registration).
Modern apps should use async: true for optimal performance. See docs for details:
docs/building-features/streaming-server-rendering.md %>
<% if uses_redux_shared_store? %>
<%# defer: true required for Redux shared stores with inline component registration %>
<%= javascript_pack_tag('client-bundle', 'data-turbo-track': 'reload', defer: true) %>
<% else %>
<%# async: true is the recommended approach for modern apps (Shakapacker >= 8.2.0) %>
<%= javascript_pack_tag('client-bundle', 'data-turbo-track': 'reload', async: true) %>
<% end %>

<%= csrf_meta_tags %>
</head>
Expand Down
3 changes: 1 addition & 2 deletions spec/dummy/config/initializers/react_on_rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,5 @@ def self.adjust_props_for_client_side_hydration(component_name, props)
config.components_subdirectory = "startup"
config.auto_load_bundle = true
config.immediate_hydration = false
# Don't explicitly set generated_component_packs_loading_strategy - let it default to :defer
# which ensures generated component packs load and register components before main bundle executes
config.generated_component_packs_loading_strategy = :defer
end
9 changes: 5 additions & 4 deletions spec/react_on_rails/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,9 @@ module ReactOnRails
.with("8.2.0").and_return(true)
end

it "defaults to :defer" do
it "defaults to :async" do
ReactOnRails.configure {} # rubocop:disable Lint/EmptyBlock
expect(ReactOnRails.configuration.generated_component_packs_loading_strategy).to eq(:defer)
expect(ReactOnRails.configuration.generated_component_packs_loading_strategy).to eq(:async)
end

it "accepts :async value" do
Expand Down Expand Up @@ -332,9 +332,10 @@ module ReactOnRails
allow(Rails.logger).to receive(:warn)
end

it "defaults to :defer" do
it "defaults to :sync and logs a warning" do
ReactOnRails.configure {} # rubocop:disable Lint/EmptyBlock
expect(ReactOnRails.configuration.generated_component_packs_loading_strategy).to eq(:defer)
expect(ReactOnRails.configuration.generated_component_packs_loading_strategy).to eq(:sync)
expect(Rails.logger).to have_received(:warn).with(/does not support async script loading/)
end

it "accepts :defer value" do
Expand Down
Loading