react_on_rails 15.0.0.alpha.1 → 15.0.0.rc.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +479 -81
  3. data/CONTRIBUTING.md +61 -47
  4. data/Gemfile.development_dependencies +1 -1
  5. data/Gemfile.lock +4 -4
  6. data/KUDOS.md +22 -1
  7. data/NEWS.md +48 -48
  8. data/PROJECTS.md +45 -40
  9. data/README.md +24 -16
  10. data/SUMMARY.md +62 -52
  11. data/eslint.config.ts +213 -0
  12. data/knip.ts +100 -0
  13. data/lib/generators/USAGE +1 -1
  14. data/lib/generators/react_on_rails/dev_tests_generator.rb +4 -8
  15. data/lib/generators/react_on_rails/templates/.eslintrc +1 -1
  16. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +2 -2
  17. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js +1 -1
  18. data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/registration.js.tt +1 -1
  19. data/lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml +1 -1
  20. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/reducers/helloWorldReducer.js +1 -1
  21. data/lib/react_on_rails/configuration.rb +81 -12
  22. data/lib/react_on_rails/controller.rb +4 -2
  23. data/lib/react_on_rails/engine.rb +1 -3
  24. data/lib/react_on_rails/helper.rb +184 -56
  25. data/lib/react_on_rails/locales/base.rb +7 -1
  26. data/lib/react_on_rails/packer_utils.rb +23 -3
  27. data/lib/react_on_rails/packs_generator.rb +84 -11
  28. data/lib/react_on_rails/prerender_error.rb +10 -2
  29. data/lib/react_on_rails/react_component/render_options.rb +39 -3
  30. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +6 -2
  31. data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +4 -2
  32. data/lib/react_on_rails/utils.rb +67 -23
  33. data/lib/react_on_rails/version.rb +1 -1
  34. data/lib/react_on_rails/version_checker.rb +34 -23
  35. data/lib/tasks/assets.rake +1 -1
  36. data/react_on_rails.gemspec +2 -2
  37. data/tsconfig.eslint.json +6 -0
  38. data/tsconfig.json +10 -6
  39. metadata +8 -7
@@ -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)
@@ -76,7 +80,7 @@ module ReactOnRails
76
80
  raise ReactOnRails::Error, msg, err.backtrace
77
81
  end
78
82
 
79
- return parse_result_and_replay_console_messages(result, render_options) unless render_options.stream?
83
+ return parse_result_and_replay_console_messages(result, render_options) unless render_options.streaming?
80
84
 
81
85
  # Streamed component is returned as stream of strings.
82
86
  # We need to parse each chunk and replay the console messages.
@@ -50,8 +50,10 @@ module ReactOnRails
50
50
  def all_compiled_assets
51
51
  @all_compiled_assets ||= begin
52
52
  webpack_generated_files = @webpack_generated_files.map do |bundle_name|
53
- if bundle_name == ReactOnRails.configuration.server_bundle_js_file
54
- ReactOnRails::Utils.server_bundle_js_file_path
53
+ if bundle_name == ReactOnRails.configuration.react_client_manifest_file
54
+ ReactOnRails::Utils.react_client_manifest_file_path
55
+ elsif bundle_name == ReactOnRails.configuration.react_server_client_manifest_file
56
+ ReactOnRails::Utils.react_server_client_manifest_file_path
55
57
  else
56
58
  ReactOnRails::Utils.bundle_js_file_path(bundle_name)
57
59
  end
@@ -8,7 +8,9 @@ require "active_support/core_ext/string"
8
8
 
9
9
  module ReactOnRails
10
10
  module Utils
11
- TRUNCATION_FILLER = "\n... TRUNCATED ...\n"
11
+ TRUNCATION_FILLER = "\n... TRUNCATED #{
12
+ Rainbow('To see the full output, set FULL_TEXT_ERRORS=true.').red
13
+ } ...\n".freeze
12
14
 
13
15
  # https://forum.shakacode.com/t/yak-of-the-week-ruby-2-4-pathname-empty-changed-to-look-at-file-size/901
14
16
  # return object if truthy, else return nil
@@ -66,7 +68,7 @@ module ReactOnRails
66
68
  server_bundle_js_file_path =~ %r{https?://}
67
69
  end
68
70
 
69
- def self.server_bundle_js_file_path
71
+ def self.bundle_js_file_path(bundle_name)
70
72
  # Either:
71
73
  # 1. Using same bundle for both server and client, so server bundle will be hashed in manifest
72
74
  # 2. Using a different bundle (different Webpack config), so file is not hashed, and
@@ -76,28 +78,17 @@ module ReactOnRails
76
78
  # a. The webpack manifest plugin would have a race condition where the same manifest.json
77
79
  # is edited by both the webpack-dev-server
78
80
  # b. There is no good reason to hash the server bundle name.
79
- return @server_bundle_path if @server_bundle_path && !Rails.env.development?
80
-
81
- bundle_name = ReactOnRails.configuration.server_bundle_js_file
82
- @server_bundle_path = if ReactOnRails::PackerUtils.using_packer?
83
- begin
84
- bundle_js_file_path(bundle_name)
85
- rescue Object.const_get(
86
- ReactOnRails::PackerUtils.packer_type.capitalize
87
- )::Manifest::MissingEntryError
88
- File.expand_path(
89
- File.join(ReactOnRails::PackerUtils.packer_public_output_path,
90
- bundle_name)
91
- )
92
- end
93
- else
94
- bundle_js_file_path(bundle_name)
95
- end
96
- end
97
-
98
- def self.bundle_js_file_path(bundle_name)
99
81
  if ReactOnRails::PackerUtils.using_packer? && bundle_name != "manifest.json"
100
- ReactOnRails::PackerUtils.bundle_js_uri_from_packer(bundle_name)
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
101
92
  else
102
93
  # Default to the non-hashed name in the specified output directory, which, for legacy
103
94
  # React on Rails, this is the output directory picked up by the asset pipeline.
@@ -106,6 +97,45 @@ module ReactOnRails
106
97
  end
107
98
  end
108
99
 
100
+ def self.server_bundle_js_file_path
101
+ return @server_bundle_path if @server_bundle_path && !Rails.env.development?
102
+
103
+ bundle_name = ReactOnRails.configuration.server_bundle_js_file
104
+ @server_bundle_path = bundle_js_file_path(bundle_name)
105
+ end
106
+
107
+ def self.rsc_bundle_js_file_path
108
+ return @rsc_bundle_path if @rsc_bundle_path && !Rails.env.development?
109
+
110
+ bundle_name = ReactOnRails.configuration.rsc_bundle_js_file
111
+ @rsc_bundle_path = bundle_js_file_path(bundle_name)
112
+ end
113
+
114
+ def self.react_client_manifest_file_path
115
+ return @react_client_manifest_path if @react_client_manifest_path && !Rails.env.development?
116
+
117
+ 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
123
+ end
124
+
125
+ # React Server Manifest is generated by the server bundle.
126
+ # So, it will never be served from the dev server.
127
+ def self.react_server_client_manifest_file_path
128
+ return @react_server_manifest_path if @react_server_manifest_path && !Rails.env.development?
129
+
130
+ asset_name = ReactOnRails.configuration.react_server_client_manifest_file
131
+ if asset_name.nil?
132
+ raise ReactOnRails::Error,
133
+ "react_server_client_manifest_file is nil, ensure it is set in your configuration"
134
+ end
135
+
136
+ @react_server_manifest_path = File.join(generated_assets_full_path, asset_name)
137
+ end
138
+
109
139
  def self.running_on_windows?
110
140
  (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
111
141
  end
@@ -183,9 +213,23 @@ module ReactOnRails
183
213
  end
184
214
  end
185
215
 
216
+ def self.rsc_support_enabled?
217
+ return false unless react_on_rails_pro?
218
+
219
+ return @rsc_support_enabled if defined?(@rsc_support_enabled)
220
+
221
+ rorp_config = ReactOnRailsPro.configuration
222
+ @rsc_support_enabled = rorp_config.respond_to?(:enable_rsc_support) && rorp_config.enable_rsc_support
223
+ end
224
+
225
+ def self.full_text_errors_enabled?
226
+ ENV["FULL_TEXT_ERRORS"] == "true"
227
+ end
228
+
186
229
  def self.smart_trim(str, max_length = 1000)
187
230
  # From https://stackoverflow.com/a/831583/1009332
188
231
  str = str.to_s
232
+ return str if full_text_errors_enabled?
189
233
  return str unless str.present? && max_length >= 1
190
234
  return str if str.length <= max_length
191
235
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactOnRails
4
- VERSION = "15.0.0.alpha.1"
4
+ VERSION = "15.0.0.rc.0"
5
5
  end
@@ -19,8 +19,9 @@ module ReactOnRails
19
19
  # For compatibility, the gem and the node package versions should always match,
20
20
  # unless the user really knows what they're doing. So we will give a
21
21
  # warning if they do not.
22
- def raise_if_gem_and_node_package_versions_differ
23
- return if node_package_version.relative_path?
22
+ def log_if_gem_and_node_package_versions_differ
23
+ return if node_package_version.raw.nil? || node_package_version.local_path_or_url?
24
+ return log_node_semver_version_warning if node_package_version.semver_wildcard?
24
25
 
25
26
  node_major_minor_patch = node_package_version.major_minor_patch
26
27
  gem_major_minor_patch = gem_major_minor_patch_version
@@ -28,9 +29,7 @@ module ReactOnRails
28
29
  node_major_minor_patch[1] == gem_major_minor_patch[1] &&
29
30
  node_major_minor_patch[2] == gem_major_minor_patch[2]
30
31
 
31
- raise_differing_versions_warning unless versions_match
32
-
33
- raise_node_semver_version_warning if node_package_version.semver_wildcard?
32
+ log_differing_versions_warning unless versions_match
34
33
  end
35
34
 
36
35
  private
@@ -46,15 +45,15 @@ module ReactOnRails
46
45
  MSG
47
46
  end
48
47
 
49
- def raise_differing_versions_warning
50
- msg = "**ERROR** ReactOnRails: ReactOnRails gem and node package versions do not match\n#{common_error_msg}"
51
- raise ReactOnRails::Error, msg
48
+ def log_differing_versions_warning
49
+ msg = "**WARNING** ReactOnRails: ReactOnRails gem and node package versions do not match\n#{common_error_msg}"
50
+ Rails.logger.warn(msg)
52
51
  end
53
52
 
54
- def raise_node_semver_version_warning
55
- msg = "**ERROR** ReactOnRails: Your node package version for react-on-rails contains a " \
53
+ def log_node_semver_version_warning
54
+ msg = "**WARNING** ReactOnRails: Your node package version for react-on-rails contains a " \
56
55
  "^ or ~\n#{common_error_msg}"
57
- raise ReactOnRails::Error, msg
56
+ Rails.logger.warn(msg)
58
57
  end
59
58
 
60
59
  def gem_version
@@ -74,7 +73,7 @@ module ReactOnRails
74
73
  end
75
74
 
76
75
  def self.package_json_path
77
- Rails.root.join("client", "package.json")
76
+ Rails.root.join(ReactOnRails.configuration.node_modules_location, "package.json")
78
77
  end
79
78
 
80
79
  def initialize(package_json)
@@ -82,29 +81,41 @@ module ReactOnRails
82
81
  end
83
82
 
84
83
  def raw
85
- parsed_package_contents = JSON.parse(package_json_contents)
86
- if parsed_package_contents.key?("dependencies") &&
87
- parsed_package_contents["dependencies"].key?("react-on-rails")
88
- parsed_package_contents["dependencies"]["react-on-rails"]
89
- else
90
- raise ReactOnRails::Error, "No 'react-on-rails' entry in package.json dependencies"
84
+ return @raw if defined?(@raw)
85
+
86
+ if File.exist?(package_json)
87
+ parsed_package_contents = JSON.parse(package_json_contents)
88
+ if parsed_package_contents.key?("dependencies") &&
89
+ parsed_package_contents["dependencies"].key?("react-on-rails")
90
+ return @raw = parsed_package_contents["dependencies"]["react-on-rails"]
91
+ end
91
92
  end
93
+ msg = "No 'react-on-rails' entry in the dependencies of #{NodePackageVersion.package_json_path}, " \
94
+ "which is the expected location according to ReactOnRails.configuration.node_modules_location"
95
+ Rails.logger.warn(msg)
96
+ @raw = nil
92
97
  end
93
98
 
94
99
  def semver_wildcard?
95
- raw.match(/[~^]/).present?
100
+ # See https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies
101
+ # We want to disallow all expressions other than exact versions
102
+ # and the ones allowed by local_path_or_url?
103
+ raw.blank? || raw.match(/[~^><|*-]/).present?
96
104
  end
97
105
 
98
- def relative_path?
99
- raw.match(%r{(\.\.|\Afile:///)}).present?
106
+ def local_path_or_url?
107
+ # See https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies
108
+ # All path and protocol "version ranges" include / somewhere,
109
+ # but we want to make an exception for npm:@scope/pkg@version.
110
+ !raw.nil? && raw.include?("/") && !raw.start_with?("npm:")
100
111
  end
101
112
 
102
113
  def major_minor_patch
103
- return if relative_path?
114
+ return if local_path_or_url?
104
115
 
105
116
  match = raw.match(MAJOR_MINOR_PATCH_VERSION_REGEX)
106
117
  unless match
107
- raise ReactOnRails::Error, "Cannot parse version number '#{raw}' (wildcard versions are not supported)"
118
+ raise ReactOnRails::Error, "Cannot parse version number '#{raw}' (only exact versions are supported)"
108
119
  end
109
120
 
110
121
  [match[1], match[2], match[3]]
@@ -26,7 +26,7 @@ namespace :react_on_rails do
26
26
  else
27
27
  # Left in this warning message in case this rake task is run directly
28
28
  msg = <<~MSG
29
- React on Rails is aborting webpack compilation from task react_on_rails:assets:webpack
29
+ React on Rails is aborting Webpack compilation from task react_on_rails:assets:webpack
30
30
  because you do not have the `config.build_production_command` defined.
31
31
  MSG
32
32
  puts Rainbow(msg).red
@@ -36,8 +36,8 @@ Gem::Specification.new do |s|
36
36
  s.post_install_message = '
37
37
  --------------------------------------------------------------------------------
38
38
  Checkout https://www.shakacode.com/react-on-rails-pro for information about
39
- "React on Rails Pro" which includes one hour a month of support and a gem for
40
- better performance, via caching helpers, and our node rendering server.
39
+ "React on Rails Pro" which includes a gem for better performance, via caching helpers, and our
40
+ node rendering server, support for React 19, and much more.
41
41
  --------------------------------------------------------------------------------
42
42
  '
43
43
  end
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "allowSyntheticDefaultImports": true
5
+ }
6
+ }
data/tsconfig.json CHANGED
@@ -1,15 +1,19 @@
1
1
  {
2
+ "extends": "@tsconfig/node14",
2
3
  "compilerOptions": {
3
4
  "allowJs": true,
4
- "esModuleInterop": true,
5
- "jsx": "react",
6
- "lib": ["dom", "es2015"],
7
- "module": "CommonJS",
5
+ "esModuleInterop": false,
6
+ // needed for Jest tests even though we don't use .tsx
7
+ "jsx": "react-jsx",
8
+ "lib": ["dom", "es2020"],
8
9
  "noImplicitAny": true,
9
10
  "outDir": "node_package/lib",
11
+ "allowImportingTsExtensions": true,
12
+ "rewriteRelativeImportExtensions": true,
10
13
  "strict": true,
11
14
  "incremental": true,
12
- "target": "es5"
15
+ "target": "es2020",
16
+ "typeRoots": ["./node_modules/@types", "./node_package/types"]
13
17
  },
14
- "include": ["node_package/src/**/*"]
18
+ "include": ["node_package/src/**/*", "node_package/types/**/*"]
15
19
  }
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: react_on_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 15.0.0.alpha.1
4
+ version: 15.0.0.rc.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-11-01 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: addressable
@@ -117,6 +116,8 @@ files:
117
116
  - SUMMARY.md
118
117
  - app/helpers/react_on_rails_helper.rb
119
118
  - docker-compose.yml
119
+ - eslint.config.ts
120
+ - knip.ts
120
121
  - lib/generators/USAGE
121
122
  - lib/generators/react_on_rails/adapt_for_older_shakapacker_generator.rb
122
123
  - lib/generators/react_on_rails/base_generator.rb
@@ -194,6 +195,7 @@ files:
194
195
  - lib/tasks/generate_packs.rake
195
196
  - lib/tasks/locale.rake
196
197
  - react_on_rails.gemspec
198
+ - tsconfig.eslint.json
197
199
  - tsconfig.json
198
200
  homepage: https://github.com/shakacode/react_on_rails
199
201
  licenses:
@@ -203,8 +205,8 @@ post_install_message: |2
203
205
 
204
206
  --------------------------------------------------------------------------------
205
207
  Checkout https://www.shakacode.com/react-on-rails-pro for information about
206
- "React on Rails Pro" which includes one hour a month of support and a gem for
207
- better performance, via caching helpers, and our node rendering server.
208
+ "React on Rails Pro" which includes a gem for better performance, via caching helpers, and our
209
+ node rendering server, support for React 19, and much more.
208
210
  --------------------------------------------------------------------------------
209
211
  rdoc_options: []
210
212
  require_paths:
@@ -220,8 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
222
  - !ruby/object:Gem::Version
221
223
  version: '0'
222
224
  requirements: []
223
- rubygems_version: 3.5.3
224
- signing_key:
225
+ rubygems_version: 3.6.9
225
226
  specification_version: 4
226
227
  summary: Rails with react server rendering with webpack.
227
228
  test_files: []