react_on_rails 14.2.1 → 16.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/AI_AGENT_INSTRUCTIONS.md +63 -0
  3. data/CHANGELOG.md +564 -85
  4. data/CLAUDE.md +135 -0
  5. data/CODING_AGENTS.md +313 -0
  6. data/CONTRIBUTING.md +448 -37
  7. data/Gemfile.development_dependencies +6 -1
  8. data/Gemfile.lock +13 -4
  9. data/KUDOS.md +22 -1
  10. data/LICENSE.md +30 -4
  11. data/LICENSES/README.md +14 -0
  12. data/NEWS.md +48 -48
  13. data/PROJECTS.md +45 -40
  14. data/REACT-ON-RAILS-PRO-LICENSE.md +129 -0
  15. data/README.md +113 -42
  16. data/SUMMARY.md +62 -52
  17. data/TODO.md +135 -0
  18. data/bin/lefthook/check-trailing-newlines +38 -0
  19. data/bin/lefthook/get-changed-files +26 -0
  20. data/bin/lefthook/prettier-format +26 -0
  21. data/bin/lefthook/ruby-autofix +26 -0
  22. data/bin/lefthook/ruby-lint +27 -0
  23. data/eslint.config.ts +232 -0
  24. data/knip.ts +40 -6
  25. data/lib/generators/USAGE +4 -5
  26. data/lib/generators/react_on_rails/USAGE +65 -0
  27. data/lib/generators/react_on_rails/base_generator.rb +276 -62
  28. data/lib/generators/react_on_rails/dev_tests_generator.rb +1 -0
  29. data/lib/generators/react_on_rails/generator_helper.rb +35 -1
  30. data/lib/generators/react_on_rails/generator_messages.rb +138 -17
  31. data/lib/generators/react_on_rails/install_generator.rb +474 -26
  32. data/lib/generators/react_on_rails/react_no_redux_generator.rb +19 -6
  33. data/lib/generators/react_on_rails/react_with_redux_generator.rb +110 -18
  34. data/lib/generators/react_on_rails/templates/.eslintrc +1 -1
  35. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +5 -0
  36. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-prod-assets +8 -0
  37. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static-assets +2 -0
  38. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +0 -5
  39. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +2 -2
  40. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js +1 -1
  41. data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js +1 -8
  42. data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx +21 -0
  43. data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.tsx +25 -0
  44. data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.module.css +4 -0
  45. data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.server.jsx +5 -0
  46. data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.server.tsx +5 -0
  47. data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +1 -1
  48. data/lib/generators/react_on_rails/templates/base/base/app/views/layouts/hello_world.html.erb +4 -2
  49. data/lib/generators/react_on_rails/templates/base/base/babel.config.js.tt +5 -2
  50. data/lib/generators/react_on_rails/templates/base/base/bin/dev +34 -0
  51. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt +14 -5
  52. data/lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml +76 -7
  53. data/lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt +1 -1
  54. data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +6 -10
  55. data/lib/generators/react_on_rails/templates/base/base/config/webpack/production.js.tt +2 -2
  56. data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +3 -2
  57. data/lib/generators/react_on_rails/templates/base/base/config/webpack/test.js.tt +2 -2
  58. data/lib/generators/react_on_rails/templates/dev_tests/spec/system/hello_world_spec.rb +0 -2
  59. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/actions/helloWorldActionCreators.ts +18 -0
  60. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +0 -6
  61. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +4 -0
  62. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.tsx +24 -0
  63. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/constants/helloWorldConstants.ts +6 -0
  64. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/containers/HelloWorldContainer.ts +20 -0
  65. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/reducers/helloWorldReducer.js +1 -1
  66. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/reducers/helloWorldReducer.ts +22 -0
  67. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/startup/HelloWorldApp.client.tsx +23 -0
  68. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/startup/HelloWorldApp.server.jsx +5 -0
  69. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/startup/HelloWorldApp.server.tsx +5 -0
  70. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/store/helloWorldStore.ts +18 -0
  71. data/lib/react_on_rails/configuration.rb +141 -57
  72. data/lib/react_on_rails/controller.rb +6 -2
  73. data/lib/react_on_rails/dev/file_manager.rb +78 -0
  74. data/lib/react_on_rails/dev/pack_generator.rb +27 -0
  75. data/lib/react_on_rails/dev/process_manager.rb +61 -0
  76. data/lib/react_on_rails/dev/server_manager.rb +487 -0
  77. data/lib/react_on_rails/dev.rb +20 -0
  78. data/lib/react_on_rails/doctor.rb +1149 -0
  79. data/lib/react_on_rails/engine.rb +6 -0
  80. data/lib/react_on_rails/git_utils.rb +12 -2
  81. data/lib/react_on_rails/helper.rb +176 -74
  82. data/lib/react_on_rails/json_parse_error.rb +6 -1
  83. data/lib/react_on_rails/packer_utils.rb +61 -71
  84. data/lib/react_on_rails/packs_generator.rb +221 -19
  85. data/lib/react_on_rails/prerender_error.rb +4 -0
  86. data/lib/react_on_rails/pro/NOTICE +21 -0
  87. data/lib/react_on_rails/pro/helper.rb +122 -0
  88. data/lib/react_on_rails/pro/utils.rb +53 -0
  89. data/lib/react_on_rails/react_component/render_options.rb +38 -6
  90. data/lib/react_on_rails/server_rendering_js_code.rb +0 -1
  91. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +12 -5
  92. data/lib/react_on_rails/system_checker.rb +659 -0
  93. data/lib/react_on_rails/test_helper/webpack_assets_compiler.rb +1 -1
  94. data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +6 -4
  95. data/lib/react_on_rails/test_helper.rb +2 -3
  96. data/lib/react_on_rails/utils.rb +139 -43
  97. data/lib/react_on_rails/version.rb +1 -1
  98. data/lib/react_on_rails/version_checker.rb +14 -20
  99. data/lib/react_on_rails/version_syntax_converter.rb +1 -1
  100. data/lib/react_on_rails.rb +1 -0
  101. data/lib/tasks/assets.rake +1 -1
  102. data/lib/tasks/doctor.rake +48 -0
  103. data/lib/tasks/generate_packs.rake +158 -1
  104. data/react_on_rails.gemspec +1 -0
  105. data/tsconfig.eslint.json +6 -0
  106. data/tsconfig.json +5 -3
  107. metadata +63 -14
  108. data/REACT-ON-RAILS-PRO-LICENSE +0 -95
  109. data/lib/generators/react_on_rails/adapt_for_older_shakapacker_generator.rb +0 -41
  110. data/lib/generators/react_on_rails/bin/dev +0 -30
  111. data/lib/generators/react_on_rails/bin/dev-static +0 -30
  112. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static.tt +0 -9
  113. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev.tt +0 -5
  114. data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/registration.js.tt +0 -8
  115. /data/lib/generators/react_on_rails/templates/base/base/config/webpack/{webpackConfig.js.tt → generateWebpackConfigs.js.tt} +0 -0
  116. /data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/startup/{HelloWorldApp.jsx → HelloWorldApp.client.jsx} +0 -0
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ # /*
4
+ # * Copyright (c) 2025 Shakacode LLC
5
+ # *
6
+ # * This file is NOT licensed under the MIT (open source) license.
7
+ # * It is part of the React on Rails Pro offering and is licensed separately.
8
+ # *
9
+ # * Unauthorized copying, modification, distribution, or use of this file,
10
+ # * via any medium, is strictly prohibited without a valid license agreement
11
+ # * from Shakacode LLC.
12
+ # *
13
+ # * For licensing terms, please see:
14
+ # * https://github.com/shakacode/react_on_rails/blob/master/REACT-ON-RAILS-PRO-LICENSE.md
15
+ # */
16
+
17
+ module ReactOnRails
18
+ module Pro
19
+ module Helper
20
+ IMMEDIATE_HYDRATION_PRO_WARNING = "[REACT ON RAILS] The 'immediate_hydration' feature requires a " \
21
+ "React on Rails Pro license. " \
22
+ "Please visit https://shakacode.com/react-on-rails-pro to learn more."
23
+
24
+ # Generates the complete component specification script tag.
25
+ # Handles both immediate hydration (Pro feature) and standard cases.
26
+ def generate_component_script(render_options)
27
+ # Setup the page_loaded_js, which is the same regardless of prerendering or not!
28
+ # The reason is that React is smart about not doing extra work if the server rendering did its job.
29
+ component_specification_tag = content_tag(:script,
30
+ json_safe_and_pretty(render_options.client_props).html_safe,
31
+ type: "application/json",
32
+ class: "js-react-on-rails-component",
33
+ id: "js-react-on-rails-component-#{render_options.dom_id}",
34
+ "data-component-name" => render_options.react_component_name,
35
+ "data-trace" => (render_options.trace ? true : nil),
36
+ "data-dom-id" => render_options.dom_id,
37
+ "data-store-dependencies" =>
38
+ render_options.store_dependencies&.to_json,
39
+ "data-immediate-hydration" =>
40
+ (render_options.immediate_hydration ? true : nil))
41
+
42
+ # Add immediate invocation script if immediate hydration is enabled
43
+ spec_tag = if render_options.immediate_hydration
44
+ # Escape dom_id for JavaScript context
45
+ escaped_dom_id = escape_javascript(render_options.dom_id)
46
+ immediate_script = content_tag(:script, %(
47
+ typeof ReactOnRails === 'object' && ReactOnRails.reactOnRailsComponentLoaded('#{escaped_dom_id}');
48
+ ).html_safe)
49
+ "#{component_specification_tag}\n#{immediate_script}"
50
+ else
51
+ component_specification_tag
52
+ end
53
+
54
+ pro_warning_badge = pro_warning_badge_if_needed(render_options.explicitly_disabled_pro_options)
55
+ "#{pro_warning_badge}\n#{spec_tag}".html_safe
56
+ end
57
+
58
+ # Generates the complete store hydration script tag.
59
+ # Handles both immediate hydration (Pro feature) and standard cases.
60
+ def generate_store_script(redux_store_data)
61
+ pro_options_check_result = ReactOnRails::Pro::Utils.disable_pro_render_options_if_not_licensed(redux_store_data)
62
+ redux_store_data = pro_options_check_result[:raw_options]
63
+ explicitly_disabled_pro_options = pro_options_check_result[:explicitly_disabled_pro_options]
64
+
65
+ store_hydration_data = content_tag(:script,
66
+ json_safe_and_pretty(redux_store_data[:props]).html_safe,
67
+ type: "application/json",
68
+ "data-js-react-on-rails-store" => redux_store_data[:store_name].html_safe,
69
+ "data-immediate-hydration" =>
70
+ (redux_store_data[:immediate_hydration] ? true : nil))
71
+
72
+ # Add immediate invocation script if immediate hydration is enabled and Pro license is valid
73
+ store_hydration_scripts = if redux_store_data[:immediate_hydration]
74
+ # Escape store_name for JavaScript context
75
+ escaped_store_name = escape_javascript(redux_store_data[:store_name])
76
+ immediate_script = content_tag(:script, <<~JS.strip_heredoc.html_safe
77
+ typeof ReactOnRails === 'object' && ReactOnRails.reactOnRailsStoreLoaded('#{escaped_store_name}');
78
+ JS
79
+ )
80
+ "#{store_hydration_data}\n#{immediate_script}"
81
+ else
82
+ store_hydration_data
83
+ end
84
+
85
+ pro_warning_badge = pro_warning_badge_if_needed(explicitly_disabled_pro_options)
86
+ "#{pro_warning_badge}\n#{store_hydration_scripts}".html_safe
87
+ end
88
+
89
+ def pro_warning_badge_if_needed(explicitly_disabled_pro_options)
90
+ return "" unless explicitly_disabled_pro_options.any?
91
+
92
+ disabled_features_message = disabled_pro_features_message(explicitly_disabled_pro_options)
93
+ warning_message = "[REACT ON RAILS] #{disabled_features_message}\n" \
94
+ "Please visit https://shakacode.com/react-on-rails-pro to learn more."
95
+ puts warning_message
96
+ Rails.logger.warn warning_message
97
+
98
+ tooltip_text = "#{disabled_features_message} Click to learn more."
99
+
100
+ <<~HTML.strip
101
+ <a href="https://shakacode.com/react-on-rails-pro" target="_blank" rel="noopener noreferrer" title="#{tooltip_text}">
102
+ <div style="position: fixed; top: 0; right: 0; width: 180px; height: 180px; overflow: hidden; z-index: 9999; pointer-events: none;">
103
+ <div style="position: absolute; top: 50px; right: -40px; transform: rotate(45deg); background-color: rgba(220, 53, 69, 0.85); color: white; padding: 7px 40px; text-align: center; font-weight: bold; font-family: sans-serif; font-size: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.3); pointer-events: auto;">
104
+ React On Rails Pro Required
105
+ </div>
106
+ </div>
107
+ </a>
108
+ HTML
109
+ end
110
+
111
+ def disabled_pro_features_message(explicitly_disabled_pro_options)
112
+ return "".html_safe unless explicitly_disabled_pro_options.any?
113
+
114
+ feature_list = explicitly_disabled_pro_options.join(", ")
115
+ feature_word = explicitly_disabled_pro_options.size == 1 ? "feature" : "features"
116
+ "The '#{feature_list}' #{feature_word} " \
117
+ "#{explicitly_disabled_pro_options.size == 1 ? 'requires' : 'require'} a " \
118
+ "React on Rails Pro license. "
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # /*
4
+ # * Copyright (c) 2025 Shakacode LLC
5
+ # *
6
+ # * This file is NOT licensed under the MIT (open source) license.
7
+ # * It is part of the React on Rails Pro offering and is licensed separately.
8
+ # *
9
+ # * Unauthorized copying, modification, distribution, or use of this file,
10
+ # * via any medium, is strictly prohibited without a valid license agreement
11
+ # * from Shakacode LLC.
12
+ # *
13
+ # * For licensing terms, please see:
14
+ # * https://github.com/shakacode/react_on_rails/blob/master/REACT-ON-RAILS-PRO-LICENSE.md
15
+ # */
16
+
17
+ module ReactOnRails
18
+ module Pro
19
+ module Utils
20
+ PRO_ONLY_OPTIONS = %i[immediate_hydration].freeze
21
+
22
+ # Checks if React on Rails Pro features are available
23
+ # @return [Boolean] true if Pro license is valid, false otherwise
24
+ def self.support_pro_features?
25
+ ReactOnRails::Utils.react_on_rails_pro_licence_valid?
26
+ end
27
+
28
+ def self.disable_pro_render_options_if_not_licensed(raw_options)
29
+ if support_pro_features?
30
+ return {
31
+ raw_options: raw_options,
32
+ explicitly_disabled_pro_options: []
33
+ }
34
+ end
35
+
36
+ raw_options_after_disable = raw_options.dup
37
+
38
+ explicitly_disabled_pro_options = PRO_ONLY_OPTIONS.select do |option|
39
+ # Use global configuration if it's not overridden in the options
40
+ next ReactOnRails.configuration.send(option) if raw_options[option].nil?
41
+
42
+ raw_options[option]
43
+ end
44
+ explicitly_disabled_pro_options.each { |option| raw_options_after_disable[option] = false }
45
+
46
+ {
47
+ raw_options: raw_options_after_disable,
48
+ explicitly_disabled_pro_options: explicitly_disabled_pro_options
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "react_on_rails/utils"
4
+ require "react_on_rails/pro/utils"
4
5
 
5
6
  module ReactOnRails
6
7
  module ReactComponent
@@ -14,10 +15,13 @@ module ReactOnRails
14
15
  # TODO: remove the required for named params
15
16
  def initialize(react_component_name: required("react_component_name"), options: required("options"))
16
17
  @react_component_name = react_component_name.camelize
17
- @options = options
18
+
19
+ result = ReactOnRails::Pro::Utils.disable_pro_render_options_if_not_licensed(options)
20
+ @options = result[:raw_options]
21
+ @explicitly_disabled_pro_options = result[:explicitly_disabled_pro_options]
18
22
  end
19
23
 
20
- attr_reader :react_component_name
24
+ attr_reader :react_component_name, :explicitly_disabled_pro_options
21
25
 
22
26
  def throw_js_errors
23
27
  options.fetch(:throw_js_errors, false)
@@ -95,8 +99,8 @@ module ReactOnRails
95
99
  retrieve_configuration_value_for(:logging_on_server)
96
100
  end
97
101
 
98
- def force_load
99
- retrieve_configuration_value_for(:force_load)
102
+ def immediate_hydration
103
+ retrieve_configuration_value_for(:immediate_hydration)
100
104
  end
101
105
 
102
106
  def to_s
@@ -111,8 +115,36 @@ module ReactOnRails
111
115
  options[key] = value
112
116
  end
113
117
 
114
- def stream?
115
- options[:stream?]
118
+ def render_mode
119
+ # Determines the React rendering strategy:
120
+ # - :sync: Synchronous SSR using renderToString (blocking and rendering in one shot)
121
+ # - :html_streaming: Progressive SSR using renderToPipeableStream (non-blocking and rendering incrementally)
122
+ # - :rsc_payload_streaming: Server Components serialized in React flight format
123
+ # (non-blocking and rendering incrementally).
124
+ options.fetch(:render_mode, :sync)
125
+ end
126
+
127
+ def streaming?
128
+ # Returns true if the component should be rendered incrementally
129
+ %i[html_streaming rsc_payload_streaming].include?(render_mode)
130
+ end
131
+
132
+ def rsc_payload_streaming?
133
+ # Returns true if the component should be rendered as a React Server Component
134
+ render_mode == :rsc_payload_streaming
135
+ end
136
+
137
+ def html_streaming?
138
+ # Returns true if the component should be rendered incrementally
139
+ render_mode == :html_streaming
140
+ end
141
+
142
+ def store_dependencies
143
+ options[:store_dependencies]
144
+ end
145
+
146
+ def self.generate_request_id
147
+ SecureRandom.uuid
116
148
  end
117
149
 
118
150
  private
@@ -18,7 +18,6 @@ module ReactOnRails
18
18
  react_component_name: nil,
19
19
  render_options: nil
20
20
  )
21
-
22
21
  config_server_bundle_js = ReactOnRails.configuration.server_bundle_js_file
23
22
 
24
23
  if render_options.prerender == true && config_server_bundle_js.blank?
@@ -19,6 +19,10 @@ module ReactOnRails
19
19
  def reset_pool_if_server_bundle_was_modified
20
20
  return unless ReactOnRails.configuration.development_mode
21
21
 
22
+ # RSC (React Server Components) bundle changes are not monitored here since:
23
+ # 1. RSC is only supported in the Pro version of React on Rails
24
+ # 2. This RubyEmbeddedJavaScript pool is used exclusively in the non-Pro version
25
+ # 3. This pool uses ExecJS for JavaScript evaluation which does not support RSC
22
26
  if ReactOnRails::Utils.server_bundle_path_is_http?
23
27
  return if @server_bundle_url == ReactOnRails::Utils.server_bundle_js_file_path
24
28
 
@@ -56,7 +60,7 @@ module ReactOnRails
56
60
  @file_index += 1
57
61
  end
58
62
  begin
59
- result = if render_options.stream?
63
+ result = if render_options.streaming?
60
64
  js_evaluator.eval_streaming_js(js_code, render_options)
61
65
  else
62
66
  js_evaluator.eval_js(js_code, render_options)
@@ -73,10 +77,11 @@ module ReactOnRails
73
77
  if err.message.include?("ReferenceError: self is not defined")
74
78
  msg << "\nError indicates that you may have code-splitting incorrectly enabled.\n"
75
79
  end
80
+ msg << "\n#{Utils.default_troubleshooting_section}\n"
76
81
  raise ReactOnRails::Error, msg, err.backtrace
77
82
  end
78
83
 
79
- return parse_result_and_replay_console_messages(result, render_options) unless render_options.stream?
84
+ return parse_result_and_replay_console_messages(result, render_options) unless render_options.streaming?
80
85
 
81
86
  # Streamed component is returned as stream of strings.
82
87
  # We need to parse each chunk and replay the console messages.
@@ -118,7 +123,7 @@ module ReactOnRails
118
123
  rescue StandardError => e
119
124
  msg = "You specified server rendering JS file: #{server_js_file}, but it cannot be " \
120
125
  "read. You may set the server_bundle_js_file in your configuration to be \"\" to " \
121
- "avoid this warning.\nError is: #{e}"
126
+ "avoid this warning.\nError is: #{e}\n\n#{Utils.default_troubleshooting_section}"
122
127
  raise ReactOnRails::Error, msg
123
128
  end
124
129
 
@@ -145,7 +150,8 @@ module ReactOnRails
145
150
  msg = "ERROR when compiling base_js_code! " \
146
151
  "See file #{file_name} to " \
147
152
  "correlate line numbers of error. Error is\n\n#{e.message}" \
148
- "\n\n#{e.backtrace.join("\n")}"
153
+ "\n\n#{e.backtrace.join("\n")}" \
154
+ "\n\n#{Utils.default_troubleshooting_section}"
149
155
  Rails.logger.error(msg)
150
156
  trace_js_code_used("Error when compiling JavaScript code for the context.", base_js_code,
151
157
  file_name, force: true)
@@ -210,6 +216,7 @@ module ReactOnRails
210
216
 
211
217
  if defined?(ScoutApm)
212
218
  include ScoutApm::Tracer
219
+
213
220
  instrument_method :exec_server_render_js, type: "ReactOnRails", name: "ExecJs React Server Rendering"
214
221
  end
215
222
 
@@ -222,7 +229,7 @@ module ReactOnRails
222
229
  encoding_type = match[:encoding]
223
230
  response.body.force_encoding(encoding_type)
224
231
  rescue StandardError => e
225
- msg = "file_url_to_string #{url} failed\nError is: #{e}"
232
+ msg = "file_url_to_string #{url} failed\nError is: #{e}\n\n#{Utils.default_troubleshooting_section}"
226
233
  raise ReactOnRails::Error, msg
227
234
  end
228
235