react_on_rails 16.0.1.rc.2 → 16.1.0

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.
@@ -9,6 +9,8 @@ module ReactOnRails
9
9
  CONTAINS_CLIENT_OR_SERVER_REGEX = /\.(server|client)($|\.)/
10
10
  COMPONENT_EXTENSIONS = /\.(jsx?|tsx?)$/
11
11
  MINIMUM_SHAKAPACKER_VERSION = "6.5.1"
12
+ # Auto-registration requires nested_entries support which was added in 7.0.0
13
+ MINIMUM_SHAKAPACKER_VERSION_FOR_AUTO_BUNDLING = "7.0.0"
12
14
 
13
15
  def self.instance
14
16
  @instance ||= PacksGenerator.new
@@ -164,6 +166,7 @@ module ReactOnRails
164
166
 
165
167
  def add_generated_pack_to_server_bundle
166
168
  return if ReactOnRails.configuration.make_generated_server_bundle_the_entrypoint
169
+ return if ReactOnRails.configuration.server_bundle_js_file.blank?
167
170
 
168
171
  relative_path_to_generated_server_bundle = relative_path(server_bundle_entrypoint,
169
172
  generated_server_bundle_file_path)
@@ -83,6 +83,10 @@ module ReactOnRails
83
83
  MSG
84
84
 
85
85
  end
86
+
87
+ # Add help and support information
88
+ message << "\n#{Utils.default_troubleshooting_section}\n"
89
+
86
90
  [backtrace, message]
87
91
  end
88
92
  end
@@ -77,6 +77,7 @@ module ReactOnRails
77
77
  if err.message.include?("ReferenceError: self is not defined")
78
78
  msg << "\nError indicates that you may have code-splitting incorrectly enabled.\n"
79
79
  end
80
+ msg << "\n#{Utils.default_troubleshooting_section}\n"
80
81
  raise ReactOnRails::Error, msg, err.backtrace
81
82
  end
82
83
 
@@ -122,7 +123,7 @@ module ReactOnRails
122
123
  rescue StandardError => e
123
124
  msg = "You specified server rendering JS file: #{server_js_file}, but it cannot be " \
124
125
  "read. You may set the server_bundle_js_file in your configuration to be \"\" to " \
125
- "avoid this warning.\nError is: #{e}"
126
+ "avoid this warning.\nError is: #{e}\n\n#{Utils.default_troubleshooting_section}"
126
127
  raise ReactOnRails::Error, msg
127
128
  end
128
129
 
@@ -149,7 +150,8 @@ module ReactOnRails
149
150
  msg = "ERROR when compiling base_js_code! " \
150
151
  "See file #{file_name} to " \
151
152
  "correlate line numbers of error. Error is\n\n#{e.message}" \
152
- "\n\n#{e.backtrace.join("\n")}"
153
+ "\n\n#{e.backtrace.join("\n")}" \
154
+ "\n\n#{Utils.default_troubleshooting_section}"
153
155
  Rails.logger.error(msg)
154
156
  trace_js_code_used("Error when compiling JavaScript code for the context.", base_js_code,
155
157
  file_name, force: true)
@@ -227,7 +229,7 @@ module ReactOnRails
227
229
  encoding_type = match[:encoding]
228
230
  response.body.force_encoding(encoding_type)
229
231
  rescue StandardError => e
230
- 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}"
231
233
  raise ReactOnRails::Error, msg
232
234
  end
233
235
 
@@ -618,14 +618,14 @@ module ReactOnRails
618
618
  version = shakapacker_match[1].strip
619
619
 
620
620
  begin
621
- # Use proper semantic version comparison
622
- version_obj = Gem::Version.new(version)
623
- threshold_version = Gem::Version.new("8.2")
621
+ # Validate version string format
622
+ Gem::Version.new(version)
624
623
 
625
- if version_obj >= threshold_version
626
- add_success("✅ Shakapacker #{version} (supports React on Rails auto-registration)")
624
+ if ReactOnRails::PackerUtils.supports_autobundling?
625
+ add_success("✅ Shakapacker #{version} (supports React on Rails auto-bundling)")
627
626
  else
628
- add_warning("⚠️ Shakapacker #{version} - Version 8.2+ needed for React on Rails auto-registration")
627
+ add_warning("⚠️ Shakapacker #{version} - Version 7.0+ with nested_entries support needed " \
628
+ "for React on Rails auto-bundling")
629
629
  end
630
630
  rescue ArgumentError
631
631
  # Fallback for invalid version strings
@@ -16,7 +16,7 @@ module ReactOnRails
16
16
 
17
17
  React on Rails is aborting your test run
18
18
 
19
- If you wish to use the config/#{ReactOnRails::PackerUtils.packer_type}.yml compile option for tests
19
+ If you wish to use the config/shakapacker.yml compile option for tests
20
20
  them remove your call to the ReactOnRails test helper.
21
21
  MSG
22
22
  puts Rainbow(msg).red
@@ -31,8 +31,7 @@ module ReactOnRails
31
31
  end
32
32
 
33
33
  def stale_generated_files(files)
34
- manifest_needed = ReactOnRails::PackerUtils.using_packer? &&
35
- !ReactOnRails::PackerUtils.manifest_exists?
34
+ manifest_needed = !ReactOnRails::PackerUtils.manifest_exists?
36
35
 
37
36
  return ["manifest.json"] if manifest_needed
38
37
 
@@ -86,10 +86,9 @@ module ReactOnRails
86
86
  puts
87
87
  @printed_once = true
88
88
 
89
- if ReactOnRails::PackerUtils.using_packer? &&
90
- ReactOnRails::Utils.using_packer_source_path_is_not_defined_and_custom_node_modules?
89
+ if ReactOnRails::Utils.using_packer_source_path_is_not_defined_and_custom_node_modules?
91
90
  msg = <<-MSG.strip_heredoc
92
- WARNING: Define config/#{ReactOnRails::PackerUtils.packer_type}.yml to include sourcePath to configure
91
+ WARNING: Define config/shakapacker.yml to include sourcePath to configure
93
92
  the location of your JavaScript source for React on Rails.
94
93
  Default location of #{source_path} is used.
95
94
  MSG
@@ -6,8 +6,9 @@ require "rainbow"
6
6
  require "active_support"
7
7
  require "active_support/core_ext/string"
8
8
 
9
+ # rubocop:disable Metrics/ModuleLength
9
10
  module ReactOnRails
10
- module Utils # rubocop:disable Metrics/ModuleLength
11
+ module Utils
11
12
  TRUNCATION_FILLER = "\n... TRUNCATED #{
12
13
  Rainbow('To see the full output, set FULL_TEXT_ERRORS=true.').red
13
14
  } ...\n".freeze
@@ -57,6 +58,8 @@ module ReactOnRails
57
58
  MSG
58
59
 
59
60
  puts wrap_message(msg)
61
+ puts ""
62
+ puts default_troubleshooting_section
60
63
 
61
64
  # Rspec catches exit without! in the exit callbacks
62
65
  exit!(1)
@@ -69,34 +72,72 @@ module ReactOnRails
69
72
  end
70
73
 
71
74
  def self.bundle_js_file_path(bundle_name)
72
- # Either:
73
- # 1. Using same bundle for both server and client, so server bundle will be hashed in manifest
74
- # 2. Using a different bundle (different Webpack config), so file is not hashed, and
75
- # bundle_js_path will throw so the default path is used without a hash.
76
- # 3. The third option of having the server bundle hashed and a different configuration than
77
- # the client bundle is not supported for 2 reasons:
78
- # a. The webpack manifest plugin would have a race condition where the same manifest.json
79
- # is edited by both the webpack-dev-server
80
- # b. There is no good reason to hash the server bundle name.
81
- if ReactOnRails::PackerUtils.using_packer? && bundle_name != "manifest.json"
82
- begin
83
- ReactOnRails::PackerUtils.bundle_js_uri_from_packer(bundle_name)
84
- rescue Object.const_get(
85
- ReactOnRails::PackerUtils.packer_type.capitalize
86
- )::Manifest::MissingEntryError
87
- File.expand_path(
88
- File.join(ReactOnRails::PackerUtils.packer_public_output_path,
89
- bundle_name)
90
- )
91
- end
92
- else
75
+ # Priority order depends on bundle type:
76
+ # SERVER BUNDLES (normal case): Try private non-public locations first, then manifest, then legacy
77
+ # CLIENT BUNDLES (normal case): Try manifest first, then fallback locations
78
+ if bundle_name == "manifest.json"
93
79
  # Default to the non-hashed name in the specified output directory, which, for legacy
94
80
  # React on Rails, this is the output directory picked up by the asset pipeline.
95
81
  # For Shakapacker, this is the public output path defined in the (shaka/web)packer.yml file.
96
- File.join(generated_assets_full_path, bundle_name)
82
+ File.join(public_bundles_full_path, bundle_name)
83
+ else
84
+ bundle_js_file_path_with_packer(bundle_name)
97
85
  end
98
86
  end
99
87
 
88
+ private_class_method def self.bundle_js_file_path_with_packer(bundle_name)
89
+ is_server_bundle = server_bundle?(bundle_name)
90
+ config = ReactOnRails.configuration
91
+ root_path = Rails.root || "."
92
+
93
+ # If server bundle and server_bundle_output_path is configured, return that path directly
94
+ if is_server_bundle && config.server_bundle_output_path.present?
95
+ private_server_bundle_path = File.expand_path(File.join(root_path, config.server_bundle_output_path,
96
+ bundle_name))
97
+
98
+ # Don't fall back to public directory if enforce_private_server_bundles is enabled
99
+ if config.enforce_private_server_bundles || File.exist?(private_server_bundle_path)
100
+ return private_server_bundle_path
101
+ end
102
+ end
103
+
104
+ # Try manifest lookup for all bundles
105
+ begin
106
+ ReactOnRails::PackerUtils.bundle_js_uri_from_packer(bundle_name)
107
+ rescue Shakapacker::Manifest::MissingEntryError
108
+ handle_missing_manifest_entry(bundle_name, is_server_bundle)
109
+ end
110
+ end
111
+
112
+ private_class_method def self.server_bundle?(bundle_name)
113
+ config = ReactOnRails.configuration
114
+ bundle_name == config.server_bundle_js_file ||
115
+ bundle_name == config.rsc_bundle_js_file
116
+ end
117
+
118
+ private_class_method def self.handle_missing_manifest_entry(bundle_name, is_server_bundle)
119
+ config = ReactOnRails.configuration
120
+ root_path = Rails.root || "."
121
+
122
+ # For server bundles with server_bundle_output_path configured, use that
123
+ if is_server_bundle && config.server_bundle_output_path.present?
124
+ candidate_paths = [File.expand_path(File.join(root_path, config.server_bundle_output_path, bundle_name))]
125
+ unless config.enforce_private_server_bundles
126
+ candidate_paths << File.expand_path(File.join(ReactOnRails::PackerUtils.packer_public_output_path,
127
+ bundle_name))
128
+ end
129
+
130
+ candidate_paths.each do |path|
131
+ return path if File.exist?(path)
132
+ end
133
+ return candidate_paths.first
134
+ end
135
+
136
+ # For client bundles and server bundles without special config, use packer's public path
137
+ # This returns the environment-specific path configured in shakapacker.yml
138
+ File.expand_path(File.join(ReactOnRails::PackerUtils.packer_public_output_path, bundle_name))
139
+ end
140
+
100
141
  def self.server_bundle_js_file_path
101
142
  return @server_bundle_path if @server_bundle_path && !Rails.env.development?
102
143
 
@@ -115,11 +156,7 @@ module ReactOnRails
115
156
  return @react_client_manifest_path if @react_client_manifest_path && !Rails.env.development?
116
157
 
117
158
  file_name = ReactOnRails.configuration.react_client_manifest_file
118
- @react_client_manifest_path = if ReactOnRails::PackerUtils.using_packer?
119
- ReactOnRails::PackerUtils.asset_uri_from_packer(file_name)
120
- else
121
- File.join(generated_assets_full_path, file_name)
122
- end
159
+ @react_client_manifest_path = ReactOnRails::PackerUtils.asset_uri_from_packer(file_name)
123
160
  end
124
161
 
125
162
  # React Server Manifest is generated by the server bundle.
@@ -133,7 +170,7 @@ module ReactOnRails
133
170
  "react_server_client_manifest_file is nil, ensure it is set in your configuration"
134
171
  end
135
172
 
136
- @react_server_manifest_path = File.join(generated_assets_full_path, asset_name)
173
+ @react_server_manifest_path = File.join(public_bundles_full_path, asset_name)
137
174
  end
138
175
 
139
176
  def self.running_on_windows?
@@ -161,26 +198,21 @@ module ReactOnRails
161
198
  end
162
199
 
163
200
  def self.source_path
164
- if ReactOnRails::PackerUtils.using_packer?
165
- ReactOnRails::PackerUtils.packer_source_path
166
- else
167
- ReactOnRails.configuration.node_modules_location
168
- end
201
+ ReactOnRails::PackerUtils.packer_source_path
169
202
  end
170
203
 
171
204
  def self.using_packer_source_path_is_not_defined_and_custom_node_modules?
172
- return false unless ReactOnRails::PackerUtils.using_packer?
173
-
174
205
  !ReactOnRails::PackerUtils.packer_source_path_explicit? &&
175
206
  ReactOnRails.configuration.node_modules_location.present?
176
207
  end
177
208
 
209
+ def self.public_bundles_full_path
210
+ ReactOnRails::PackerUtils.packer_public_output_path
211
+ end
212
+
213
+ # DEPRECATED: Use public_bundles_full_path for clarity about public vs private bundle paths
178
214
  def self.generated_assets_full_path
179
- if ReactOnRails::PackerUtils.using_packer?
180
- ReactOnRails::PackerUtils.packer_public_output_path
181
- else
182
- File.expand_path(ReactOnRails.configuration.generated_assets_dir)
183
- end
215
+ public_bundles_full_path
184
216
  end
185
217
 
186
218
  def self.gem_available?(name)
@@ -278,5 +310,16 @@ module ReactOnRails
278
310
 
279
311
  puts "Prepended\n#{text_to_prepend}to #{file}."
280
312
  end
313
+
314
+ def self.default_troubleshooting_section
315
+ <<~DEFAULT
316
+ 📞 Get Help & Support:
317
+ • 🚀 Professional Support: react_on_rails@shakacode.com (fastest resolution)
318
+ • 💬 React + Rails Slack: https://invite.reactrails.com
319
+ • 🆓 GitHub Issues: https://github.com/shakacode/react_on_rails/issues
320
+ • 📖 Discussions: https://github.com/shakacode/react_on_rails/discussions
321
+ DEFAULT
322
+ end
281
323
  end
282
324
  end
325
+ # rubocop:enable Metrics/ModuleLength
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactOnRails
4
- VERSION = "16.0.1.rc.2"
4
+ VERSION = "16.1.0"
5
5
  end
@@ -83,7 +83,7 @@ namespace :react_on_rails do
83
83
  puts Rainbow(" • Keep only the client/server specific files " \
84
84
  "(Component.client.jsx, Component.server.jsx)").white
85
85
  puts Rainbow(" • See: https://www.shakacode.com/react-on-rails/docs/guides/" \
86
- "file-system-based-automated-bundle-generation.md").cyan
86
+ "auto-bundling-file-system-based-automated-bundle-generation.md").cyan
87
87
 
88
88
  when /Cannot find component/
89
89
  puts Rainbow(" • Check that your component file exists in the expected location").white
@@ -118,11 +118,29 @@ namespace :react_on_rails do
118
118
  puts ""
119
119
  puts Rainbow("📚 DOCUMENTATION:").magenta.bold
120
120
  puts Rainbow(" • File-system based components: https://www.shakacode.com/react-on-rails/docs/" \
121
- "guides/file-system-based-automated-bundle-generation.md").cyan
121
+ "guides/auto-bundling-file-system-based-automated-bundle-generation.md").cyan
122
122
  puts Rainbow(" • Component registration: https://www.shakacode.com/react-on-rails/docs/").cyan
123
123
  puts Rainbow("=" * 80).red
124
124
  end
125
125
 
126
+ def show_help_and_support
127
+ puts ""
128
+ troubleshooting_content = ReactOnRails::Utils.default_troubleshooting_section
129
+ # Display the troubleshooting content with color formatting
130
+ troubleshooting_content.split("\n").each do |line|
131
+ case line
132
+ when /^📞/
133
+ puts Rainbow(line).magenta.bold
134
+ when /^\s*•\s*🚀/
135
+ puts Rainbow(line).yellow
136
+ when /^\s*•/
137
+ puts Rainbow(line).cyan
138
+ else
139
+ puts Rainbow(line).white unless line.strip.empty?
140
+ end
141
+ end
142
+ end
143
+
126
144
  # rubocop:disable Metrics/AbcSize
127
145
  def handle_standard_error(error)
128
146
  puts ""
@@ -142,11 +160,7 @@ namespace :react_on_rails do
142
160
  puts Rainbow(" 2. Check Rails logs: tail -f log/development.log").white
143
161
  puts Rainbow(" 3. Verify all dependencies are installed: bundle install && npm install").white
144
162
  puts Rainbow(" 4. Clear cache: rm -rf tmp/cache").white
145
- puts ""
146
- puts Rainbow("📞 GET HELP:").magenta.bold
147
- puts Rainbow(" • Create an issue: https://github.com/shakacode/react_on_rails/issues").cyan
148
- puts Rainbow(" • Community discussions: https://github.com/shakacode/react_on_rails/discussions").cyan
149
- puts Rainbow(" • Professional support: https://www.shakacode.com/react-on-rails-pro").cyan
163
+ show_help_and_support
150
164
  puts Rainbow("=" * 80).red
151
165
  end
152
166
  # rubocop:enable Metrics/AbcSize
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: react_on_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 16.0.1.rc.2
4
+ version: 16.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
@@ -114,6 +114,7 @@ executables: []
114
114
  extensions: []
115
115
  extra_rdoc_files: []
116
116
  files:
117
+ - AI_AGENT_INSTRUCTIONS.md
117
118
  - CHANGELOG.md
118
119
  - CLAUDE.md
119
120
  - CODING_AGENTS.md
@@ -242,7 +243,6 @@ files:
242
243
  - lib/tasks/doctor.rake
243
244
  - lib/tasks/generate_packs.rake
244
245
  - lib/tasks/locale.rake
245
- - package-lock.json
246
246
  - react_on_rails.gemspec
247
247
  - tsconfig.eslint.json
248
248
  - tsconfig.json