react_on_rails 12.4.0 → 13.0.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +3 -1
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.github/workflows/main.yml +3 -3
  6. data/.gitignore +0 -3
  7. data/.prettierignore +2 -0
  8. data/CHANGELOG.md +39 -2
  9. data/Gemfile.development_dependencies +7 -6
  10. data/REACT-ON-RAILS-PRO-LICENSE +1 -1
  11. data/README.md +20 -13
  12. data/SUMMARY.md +9 -0
  13. data/docs/deployment/heroku-deployment.md +16 -5
  14. data/docs/guides/configuration.md +29 -15
  15. data/docs/guides/hmr-and-hot-reloading-with-the-webpack-dev-server.md +4 -4
  16. data/docs/guides/how-react-on-rails-works.md +1 -2
  17. data/docs/guides/rspec-configuration.md +1 -1
  18. data/docs/guides/tutorial.md +27 -27
  19. data/docs/guides/upgrading-react-on-rails.md +15 -0
  20. data/docs/guides/webpack-configuration.md +1 -1
  21. data/docs/javascript/converting-from-custom-webpack-config-to-rails-webpacker-config.md +2 -2
  22. data/lib/generators/react_on_rails/base_generator.rb +55 -10
  23. data/lib/generators/react_on_rails/generator_helper.rb +4 -0
  24. data/lib/generators/react_on_rails/templates/.eslintrc +3 -1
  25. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +4 -8
  26. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static +9 -0
  27. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
  28. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +4 -0
  29. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js +5 -0
  30. data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js +8 -0
  31. data/lib/generators/react_on_rails/templates/base/base/app/views/layouts/hello_world.html.erb +1 -0
  32. data/lib/generators/react_on_rails/templates/base/base/babel.config.js.tt +32 -0
  33. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +3 -3
  34. data/lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt +17 -0
  35. data/lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt +15 -0
  36. data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +25 -0
  37. data/lib/generators/react_on_rails/templates/base/base/config/webpack/production.js.tt +9 -0
  38. data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +117 -0
  39. data/lib/generators/react_on_rails/templates/base/base/config/webpack/test.js.tt +6 -0
  40. data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpack.config.js.tt +15 -0
  41. data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpackConfig.js.tt +36 -0
  42. data/lib/generators/react_on_rails/templates/base/base/config/webpacker.yml +62 -0
  43. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
  44. data/lib/react_on_rails/configuration.rb +40 -41
  45. data/lib/react_on_rails/helper.rb +18 -17
  46. data/lib/react_on_rails/json_parse_error.rb +1 -1
  47. data/lib/react_on_rails/locales/base.rb +1 -3
  48. data/lib/react_on_rails/prerender_error.rb +5 -2
  49. data/lib/react_on_rails/react_component/render_options.rb +14 -0
  50. data/lib/react_on_rails/server_rendering_js_code.rb +13 -0
  51. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +27 -10
  52. data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +3 -3
  53. data/lib/react_on_rails/test_helper.rb +2 -2
  54. data/lib/react_on_rails/version.rb +1 -1
  55. data/lib/react_on_rails/webpacker_utils.rb +2 -7
  56. data/lib/tasks/assets.rake +5 -47
  57. data/lib/tasks/locale.rake +1 -2
  58. data/package.json +1 -1
  59. data/rakelib/example_type.rb +10 -3
  60. data/rakelib/examples.rake +3 -5
  61. data/rakelib/release.rake +7 -1
  62. data/react_on_rails.gemspec +2 -3
  63. data/yarn.lock +117 -71
  64. metadata +22 -21
  65. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-hmr +0 -26
@@ -0,0 +1,36 @@
1
+ <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/config/webpack/webpackConfig.js") %>
2
+
3
+ const clientWebpackConfig = require('./clientWebpackConfig');
4
+ const serverWebpackConfig = require('./serverWebpackConfig');
5
+
6
+ const webpackConfig = (envSpecific) => {
7
+ const clientConfig = clientWebpackConfig();
8
+ const serverConfig = serverWebpackConfig();
9
+
10
+ if (envSpecific) {
11
+ envSpecific(clientConfig, serverConfig);
12
+ }
13
+
14
+ let result;
15
+ // For HMR, need to separate the the client and server webpack configurations
16
+ if (process.env.WEBPACK_SERVE || process.env.CLIENT_BUNDLE_ONLY) {
17
+ // eslint-disable-next-line no-console
18
+ console.log('[React on Rails] Creating only the client bundles.');
19
+ result = clientConfig;
20
+ } else if (process.env.SERVER_BUNDLE_ONLY) {
21
+ // eslint-disable-next-line no-console
22
+ console.log('[React on Rails] Creating only the server bundle.');
23
+ result = serverConfig;
24
+ } else {
25
+ // default is the standard client and server build
26
+ // eslint-disable-next-line no-console
27
+ console.log('[React on Rails] Creating both client and server bundles.');
28
+ result = [clientConfig, serverConfig];
29
+ }
30
+
31
+ // To debug, uncomment next line and inspect "result"
32
+ // debugger
33
+ return result;
34
+ };
35
+
36
+ module.exports = webpackConfig;
@@ -0,0 +1,62 @@
1
+ # Note: You must restart bin/webpacker-dev-server for changes to take effect
2
+
3
+ default: &default
4
+ source_path: app/javascript
5
+ source_entry_path: packs
6
+ public_root_path: public
7
+ public_output_path: packs
8
+ cache_path: tmp/webpacker
9
+ webpack_compile_output: true
10
+
11
+ # Additional paths webpack should lookup modules
12
+ # ['app/assets', 'engine/foo/app/assets']
13
+ additional_paths: []
14
+
15
+ # Reload manifest.json on all requests so we reload latest compiled packs
16
+ cache_manifest: false
17
+
18
+ development:
19
+ <<: *default
20
+ # This is false since we're running `bin/webpacker -w` in Procfile.dev-setic
21
+ compile: false
22
+
23
+ # Reference: https://webpack.js.org/configuration/dev-server/
24
+ dev_server:
25
+ https: false
26
+ host: localhost
27
+ port: 3035
28
+ # Hot Module Replacement updates modules while the application is running without a full reload
29
+ hmr: true
30
+ client:
31
+ # Should we show a full-screen overlay in the browser when there are compiler errors or warnings?
32
+ overlay: true
33
+ # May also be a string
34
+ # webSocketURL:
35
+ # hostname: "0.0.0.0"
36
+ # pathname: "/ws"
37
+ # port: 8080
38
+ compress: true
39
+ # Note that apps that do not check the host are vulnerable to DNS rebinding attacks
40
+ allowed_hosts: [ 'localhost' ]
41
+ pretty: true
42
+ headers:
43
+ 'Access-Control-Allow-Origin': '*'
44
+ static:
45
+ watch:
46
+ ignored: '**/node_modules/**'
47
+
48
+ test:
49
+ <<: *default
50
+ compile: true
51
+
52
+ # Compile test packs to a separate directory
53
+ public_output_path: packs-test
54
+
55
+ production:
56
+ <<: *default
57
+
58
+ # Production depends on precompilation of packs prior to booting for performance.
59
+ compile: false
60
+
61
+ # Cache manifest.json for performance
62
+ cache_manifest: true
@@ -1,5 +1,6 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
+ import style from './HelloWorld.module.css';
3
4
 
4
5
  const HelloWorld = ({ name, updateName }) => (
5
6
  <div>
@@ -9,7 +10,7 @@ const HelloWorld = ({ name, updateName }) => (
9
10
  </h3>
10
11
  <hr />
11
12
  <form>
12
- <label htmlFor="name">
13
+ <label className={style.bright} htmlFor="name">
13
14
  Say hello to:
14
15
  <input id="name" type="text" value={name} onChange={(e) => updateName(e.target.value)} />
15
16
  </label>
@@ -32,6 +32,7 @@ module ReactOnRails
32
32
  # skip_display_none is deprecated
33
33
  webpack_generated_files: %w[manifest.json],
34
34
  rendering_extension: nil,
35
+ rendering_props_extension: nil,
35
36
  server_render_method: nil,
36
37
  build_test_command: "",
37
38
  build_production_command: "",
@@ -51,7 +52,7 @@ module ReactOnRails
51
52
  :build_production_command,
52
53
  :i18n_dir, :i18n_yml_dir, :i18n_output_format,
53
54
  :server_render_method, :random_dom_id,
54
- :same_bundle_for_client_and_server
55
+ :same_bundle_for_client_and_server, :rendering_props_extension
55
56
 
56
57
  # rubocop:disable Metrics/AbcSize
57
58
  def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
@@ -65,7 +66,7 @@ module ReactOnRails
65
66
  build_production_command: nil,
66
67
  same_bundle_for_client_and_server: nil,
67
68
  i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil,
68
- random_dom_id: nil, server_render_method: nil)
69
+ random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil)
69
70
  self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
70
71
  self.generated_assets_dirs = generated_assets_dirs
71
72
  self.generated_assets_dir = generated_assets_dir
@@ -87,6 +88,7 @@ module ReactOnRails
87
88
  self.trace = trace.nil? ? Rails.env.development? : trace
88
89
  self.raise_on_prerender_error = raise_on_prerender_error
89
90
  self.skip_display_none = skip_display_none
91
+ self.rendering_props_extension = rendering_props_extension
90
92
 
91
93
  # Server rendering:
92
94
  self.server_bundle_js_file = server_bundle_js_file
@@ -111,44 +113,41 @@ module ReactOnRails
111
113
  check_i18n_yml_directory_exists
112
114
  check_server_render_method_is_only_execjs
113
115
  error_if_using_webpacker_and_generated_assets_dir_not_match_public_output_path
114
- check_deprecated_settings
116
+ # check_deprecated_settings
117
+ adjust_precompile_task
115
118
  end
116
119
 
117
120
  private
118
121
 
119
- def check_deprecated_settings
120
- if build_production_command.present? &&
121
- ReactOnRails::WebpackerUtils.webpacker_webpack_production_config_exists?
122
- msg = <<~MSG
123
- Setting ReactOnRails configuration for `build_production_command` is
124
- not necessary if you have config/webpack/production.js. When that file
125
- exists, React on Rails DOES NOT modify the standard assets:precompile.
126
- If you want React on Rails to modify to the standard assets:precompile
127
- to use your config/initializers/react_on_rails.rb config.build_production_command
128
- then delete the config/webpack/production.js.
129
- MSG
130
- Rails.logger.warn(msg)
122
+ def adjust_precompile_task
123
+ skip_react_on_rails_precompile = %w[no false n f].include?(ENV["REACT_ON_RAILS_PRECOMPILE"])
124
+
125
+ return if skip_react_on_rails_precompile || build_production_command.blank?
126
+
127
+ # Ensure that shakacode/shakapacker does not call bin/webpacker if we're providing
128
+ # the build command.
129
+ ENV["WEBPACKER_PRECOMPILE"] = "false"
130
+
131
+ precompile_tasks = lambda {
132
+ Rake::Task["react_on_rails:assets:webpack"].invoke
133
+ puts "Invoking task webpacker:clean from React on Rails"
134
+
135
+ # VERSIONS is per the shakacode/shakapacker clean method definition.
136
+ # We set it very big so that it is not used, and then clean just
137
+ # removes files older than 1 hour.
138
+ versions = 100_000
139
+ Rake::Task["webpacker:clean"].invoke(versions)
140
+ }
141
+
142
+ if Rake::Task.task_defined?("assets:precompile")
143
+ Rake::Task["assets:precompile"].enhance do
144
+ precompile_tasks.call
145
+ end
146
+ else
147
+ Rake::Task.define_task("assets:precompile") do
148
+ precompile_tasks.call
149
+ end
131
150
  end
132
- #
133
- # msg = <<~MSG
134
- # ReactOnRails configuration for `build_production_command` is removed.
135
- # Move this command into `bin/webpack` converting the script to a shell script.
136
- # MSG
137
- # raise ReactOnRails::Error, msg
138
- # Commenting out until v13 when
139
- # https://github.com/rails/webpacker/issues/2640 gets resolved
140
- # if node_modules_location.present?
141
- # Rails.logger.warn("ReactOnRails configuration for `node_modules_location` is deprecated. "\
142
- # "Instead, prepend a `cd client` (or whichever location) before your test command.")
143
- # end
144
- #
145
- # return unless build_production_command.present?
146
- #
147
- # msg = <<~MSG
148
- # ReactOnRails configuration for `build_production_command` is removed.
149
- # Move this command into `bin/webpack` converting the script to a shell script.
150
- # MSG
151
- # raise ReactOnRails::Error, msg
152
151
  end
153
152
 
154
153
  def error_if_using_webpacker_and_generated_assets_dir_not_match_public_output_path
@@ -160,7 +159,7 @@ module ReactOnRails
160
159
 
161
160
  if File.expand_path(generated_assets_dir) == webpacker_public_output_path.to_s
162
161
  Rails.logger.warn("You specified generated_assets_dir in `config/initializers/react_on_rails.rb` "\
163
- "with Webpacker. Remove this line from your configuration file.")
162
+ "with Webpacker. Remove this line from your configuration file.")
164
163
  else
165
164
  msg = <<~MSG
166
165
  Error configuring /config/initializers/react_on_rails.rb: You are using webpacker
@@ -222,19 +221,19 @@ module ReactOnRails
222
221
  if ReactOnRails::WebpackerUtils.using_webpacker?
223
222
  webpacker_public_output_path = ReactOnRails::WebpackerUtils.webpacker_public_output_path
224
223
  Rails.logger.warn "Error configuring config/initializers/react_on_rails. Define neither the "\
225
- "generated_assets_dirs no the generated_assets_dir when using Webpacker. This is defined by "\
226
- "public_output_path specified in webpacker.yml = #{webpacker_public_output_path}."
224
+ "generated_assets_dirs no the generated_assets_dir when using Webpacker. This is defined by "\
225
+ "public_output_path specified in webpacker.yml = #{webpacker_public_output_path}."
227
226
  return
228
227
  end
229
228
 
230
229
  Rails.logger.warn "[DEPRECATION] ReactOnRails: Use config.generated_assets_dir rather than "\
231
- "generated_assets_dirs"
230
+ "generated_assets_dirs"
232
231
  if generated_assets_dir.blank?
233
232
  self.generated_assets_dir = generated_assets_dirs
234
233
  else
235
234
  Rails.logger.warn "[DEPRECATION] ReactOnRails. You have both generated_assets_dirs and "\
236
- "generated_assets_dir defined. Define ONLY generated_assets_dir if NOT using Webpacker"\
237
- " and define neither if using Webpacker"
235
+ "generated_assets_dir defined. Define ONLY generated_assets_dir if NOT using Webpacker"\
236
+ " and define neither if using Webpacker"
238
237
  end
239
238
  end
240
239
 
@@ -154,7 +154,7 @@ module ReactOnRails
154
154
  @registered_stores_defer_render ||= []
155
155
  @registered_stores_defer_render << redux_store_data
156
156
  "YOU SHOULD NOT SEE THIS ON YOUR VIEW -- Uses as a code block, like <% redux_store %> "\
157
- "and not <%= redux store %>"
157
+ "and not <%= redux store %>"
158
158
  else
159
159
  @registered_stores ||= []
160
160
  @registered_stores << redux_store_data
@@ -234,9 +234,9 @@ module ReactOnRails
234
234
  console_log_script = result["consoleLogScript"]
235
235
  raw("#{html}#{render_options.replay_console ? console_log_script : ''}")
236
236
  rescue ExecJS::ProgramError => err
237
- raise ReactOnRails::PrerenderError, component_name: "N/A (server_render_js called)",
238
- err: err,
239
- js_code: js_code
237
+ raise ReactOnRails::PrerenderError.new(component_name: "N/A (server_render_js called)",
238
+ err: err,
239
+ js_code: js_code)
240
240
  end
241
241
 
242
242
  def json_safe_and_pretty(hash_or_string)
@@ -244,7 +244,7 @@ module ReactOnRails
244
244
 
245
245
  unless hash_or_string.is_a?(String) || hash_or_string.is_a?(Hash)
246
246
  raise ReactOnRails::Error, "#{__method__} only accepts String or Hash as argument "\
247
- "(#{hash_or_string.class} given)."
247
+ "(#{hash_or_string.class} given)."
248
248
  end
249
249
 
250
250
  json_value = hash_or_string.is_a?(String) ? hash_or_string : hash_or_string.to_json
@@ -309,6 +309,7 @@ module ReactOnRails
309
309
 
310
310
  @rails_context.merge(serverSide: server_side)
311
311
  end
312
+
312
313
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
313
314
 
314
315
  private
@@ -413,7 +414,7 @@ module ReactOnRails
413
414
  # Setup the page_loaded_js, which is the same regardless of prerendering or not!
414
415
  # The reason is that React is smart about not doing extra work if the server rendering did its job.
415
416
  component_specification_tag = content_tag(:script,
416
- json_safe_and_pretty(render_options.props).html_safe,
417
+ json_safe_and_pretty(render_options.client_props).html_safe,
417
418
  type: "application/json",
418
419
  class: "js-react-on-rails-component",
419
420
  "data-component-name" => render_options.react_component_name,
@@ -483,21 +484,21 @@ module ReactOnRails
483
484
  result = ReactOnRails::ServerRenderingPool.server_render_js_with_console_logging(js_code, render_options)
484
485
  rescue StandardError => err
485
486
  # This error came from the renderer
486
- raise ReactOnRails::PrerenderError, component_name: react_component_name,
487
- # Sanitize as this might be browser logged
488
- props: sanitized_props_string(props),
489
- err: err,
490
- js_code: js_code
487
+ raise ReactOnRails::PrerenderError.new(component_name: react_component_name,
488
+ # Sanitize as this might be browser logged
489
+ props: sanitized_props_string(props),
490
+ err: err,
491
+ js_code: js_code)
491
492
  end
492
493
 
493
494
  if result["hasErrors"] && render_options.raise_on_prerender_error
494
495
  # We caught this exception on our backtrace handler
495
- raise ReactOnRails::PrerenderError, component_name: react_component_name,
496
- # Sanitize as this might be browser logged
497
- props: sanitized_props_string(props),
498
- err: nil,
499
- js_code: js_code,
500
- console_messages: result["consoleReplayScript"]
496
+ raise ReactOnRails::PrerenderError.new(component_name: react_component_name,
497
+ # Sanitize as this might be browser logged
498
+ props: sanitized_props_string(props),
499
+ err: nil,
500
+ js_code: js_code,
501
+ console_messages: result["consoleReplayScript"])
501
502
 
502
503
  end
503
504
  result
@@ -4,7 +4,7 @@ module ReactOnRails
4
4
  class JsonParseError < ::ReactOnRails::Error
5
5
  attr_reader :json
6
6
 
7
- def initialize(parse_error, json)
7
+ def initialize(parse_error:, json:)
8
8
  @json = json
9
9
  @original_error = parse_error
10
10
  super(parse_error.message)
@@ -85,9 +85,7 @@ module ReactOnRails
85
85
 
86
86
  def generate_file(template, path)
87
87
  result = ERB.new(template).result()
88
- File.open(path, "w") do |f|
89
- f.write(result)
90
- end
88
+ File.write(path, result)
91
89
  end
92
90
 
93
91
  def generate_translations
@@ -49,10 +49,13 @@ module ReactOnRails
49
49
  message = +"ERROR in SERVER PRERENDERING\n"
50
50
  if err
51
51
  message << <<~MSG
52
- Encountered error: \"#{err}\"
52
+ Encountered error:
53
+
54
+ #{err}
55
+
53
56
  MSG
54
57
 
55
- backtrace = err.backtrace.join("\n")
58
+ backtrace = err.backtrace.first(15).join("\n")
56
59
  else
57
60
  backtrace = nil
58
61
  end
@@ -27,6 +27,20 @@ module ReactOnRails
27
27
  options.fetch(:props) { NO_PROPS }
28
28
  end
29
29
 
30
+ def client_props
31
+ props_extension = ReactOnRails.configuration.rendering_props_extension
32
+ if props_extension.present?
33
+ if props_extension.respond_to?(:adjust_props_for_client_side_hydration)
34
+ return props_extension.adjust_props_for_client_side_hydration(react_component_name,
35
+ props.clone)
36
+ end
37
+
38
+ raise ReactOnRails::Error, "ReactOnRails: your rendering_props_extension module is missing the "\
39
+ "required adjust_props_for_client_side_hydration method & can not be used"
40
+ end
41
+ props
42
+ end
43
+
30
44
  def random_dom_id
31
45
  retrieve_configuration_value_for(:random_dom_id)
32
46
  end
@@ -18,6 +18,19 @@ module ReactOnRails
18
18
  react_component_name: nil,
19
19
  render_options: nil
20
20
  )
21
+
22
+ config_server_bundle_js = ReactOnRails.configuration.server_bundle_js_file
23
+
24
+ if render_options.prerender == true && config_server_bundle_js.blank?
25
+ msg = <<~MSG
26
+ The `prerender` option to allow Server Side Rendering is marked as true but the ReactOnRails configuration
27
+ for `server_bundle_js_file` is nil or not present in `config/initializers/react_on_rails.rb`.
28
+ Set `config.server_bundle_js_file` to your javascript bundle to allow server side rendering.
29
+ Read more at https://www.shakacode.com/react-on-rails/docs/guides/react-server-rendering/
30
+ MSG
31
+ raise ReactOnRails::Error, msg
32
+ end
33
+
21
34
  js_code_renderer.render(props_string, rails_context, redux_stores, react_component_name, render_options)
22
35
  end
23
36
 
@@ -47,7 +47,7 @@ module ReactOnRails
47
47
  # Note, js_code does not have to be based on React.
48
48
  # js_code MUST RETURN json stringify Object
49
49
  # Calling code will probably call 'html_safe' on return value before rendering to the view.
50
- # rubocop:disable Metrics/CyclomaticComplexity
50
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
51
51
  def exec_server_render_js(js_code, render_options, js_evaluator = nil)
52
52
  js_evaluator ||= self
53
53
  if render_options.trace
@@ -56,12 +56,27 @@ module ReactOnRails
56
56
  "tmp/server-generated-#{@file_index % 10}.js")
57
57
  @file_index += 1
58
58
  end
59
- json_string = js_evaluator.eval_js(js_code, render_options)
59
+ begin
60
+ json_string = js_evaluator.eval_js(js_code, render_options)
61
+ rescue StandardError => err
62
+ msg = <<~MSG
63
+ Error evaluating server bundle. Check your webpack configuration.
64
+ ===============================================================
65
+ Caught error:
66
+ #{err.message}
67
+ ===============================================================
68
+ MSG
69
+
70
+ if err.message.include?("ReferenceError: self is not defined")
71
+ msg << "\nError indicates that you may have code-splitting incorrectly enabled.\n"
72
+ end
73
+ raise ReactOnRails::Error, msg, err.backtrace
74
+ end
60
75
  result = nil
61
76
  begin
62
77
  result = JSON.parse(json_string)
63
78
  rescue JSON::ParserError => e
64
- raise ReactOnRails::JsonParseError.new(e, json_string)
79
+ raise ReactOnRails::JsonParseError.new(parse_error: e, json: json_string)
65
80
  end
66
81
 
67
82
  if render_options.logging_on_server
@@ -76,7 +91,7 @@ module ReactOnRails
76
91
  end
77
92
  result
78
93
  end
79
- # rubocop:enable Metrics/CyclomaticComplexity
94
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
80
95
 
81
96
  def trace_js_code_used(msg, js_code, file_name = "tmp/server-generated.js", force: false)
82
97
  return unless ReactOnRails.configuration.trace || force
@@ -133,15 +148,15 @@ module ReactOnRails
133
148
  if ReactOnRails.configuration.trace
134
149
  Rails.logger.info do
135
150
  "[react_on_rails] Created JavaScript context with file "\
136
- "#{ReactOnRails::Utils.server_bundle_js_file_path}"
151
+ "#{ReactOnRails::Utils.server_bundle_js_file_path}"
137
152
  end
138
153
  end
139
154
  ExecJS.compile(base_js_code)
140
155
  rescue StandardError => e
141
156
  msg = "ERROR when compiling base_js_code! "\
142
- "See file #{file_name} to "\
143
- "correlate line numbers of error. Error is\n\n#{e.message}"\
144
- "\n\n#{e.backtrace.join("\n")}"
157
+ "See file #{file_name} to "\
158
+ "correlate line numbers of error. Error is\n\n#{e.message}"\
159
+ "\n\n#{e.backtrace.join("\n")}"
145
160
  Rails.logger.error(msg)
146
161
  trace_js_code_used("Error when compiling JavaScript code for the context.", base_js_code,
147
162
  file_name, force: true)
@@ -150,7 +165,9 @@ module ReactOnRails
150
165
  end
151
166
 
152
167
  def execjs_timer_polyfills
153
- if ReactOnRails::Utils.react_on_rails_pro? && ReactOnRailsPro.configuration.include_execjs_polyfills == false
168
+ if ReactOnRails::Utils.react_on_rails_pro? &&
169
+ ReactOnRailsPro.configuration.respond_to?(:include_execjs_polyfills) &&
170
+ ReactOnRailsPro.configuration.include_execjs_polyfills == false
154
171
  return ""
155
172
  end
156
173
 
@@ -184,7 +201,7 @@ module ReactOnRails
184
201
  def undefined_for_exec_js_logging(function_name)
185
202
  if ReactOnRails.configuration.trace
186
203
  "console.error('[React on Rails Rendering] #{function_name} is not defined for server rendering.');\n"\
187
- " console.error(getStackTrace().join('\\n'));"
204
+ " console.error(getStackTrace().join('\\n'));"
188
205
  else
189
206
  ""
190
207
  end
@@ -66,10 +66,10 @@ module ReactOnRails
66
66
  file_list = make_file_list(make_globs(generated_assets_full_path)).to_ary
67
67
  puts "V" * 80
68
68
  puts "Please define config.webpack_generated_files (array) so the test helper knows "\
69
- "which files are required. If you are using webpacker, you typically need to only "\
70
- "include 'manifest.json'."
69
+ "which files are required. If you are using webpacker, you typically need to only "\
70
+ "include 'manifest.json'."
71
71
  puts "Detected the possible following files to check for webpack compilation in "\
72
- "#{generated_assets_full_path}"
72
+ "#{generated_assets_full_path}"
73
73
  puts file_list.join("\n")
74
74
  puts "^" * 80
75
75
  file_list
@@ -72,8 +72,8 @@ module ReactOnRails
72
72
  unless @printed_once
73
73
  puts
74
74
  puts "====> React On Rails: Checking files in "\
75
- "#{webpack_assets_status_checker.generated_assets_full_path} for "\
76
- "outdated/missing bundles based on source_path #{source_path}"
75
+ "#{webpack_assets_status_checker.generated_assets_full_path} for "\
76
+ "outdated/missing bundles based on source_path #{source_path}"
77
77
  puts
78
78
  @printed_once = true
79
79
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactOnRails
4
- VERSION = "12.4.0"
4
+ VERSION = "13.0.0"
5
5
  end
@@ -7,13 +7,8 @@ module ReactOnRails
7
7
  def self.using_webpacker?
8
8
  return @using_webpacker if defined?(@using_webpacker)
9
9
 
10
- @using_webpacker = ReactOnRails::Utils.gem_available?("webpacker")
11
- end
12
-
13
- def self.webpacker_webpack_production_config_exists?
14
- webpacker_webpack_config_abs_path = File.join(Rails.root,
15
- "config/webpack/production.js")
16
- File.exist?(webpacker_webpack_config_abs_path)
10
+ @using_webpacker = ReactOnRails::Utils.gem_available?("webpacker") ||
11
+ ReactOnRails::Utils.gem_available?("shakapacker")
17
12
  end
18
13
 
19
14
  def self.dev_server_running?
@@ -1,51 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Important: The default assets:precompile is modified ONLY if the rails/webpacker webpack config
4
- # does not exist!
5
-
6
- require "active_support"
7
-
8
- ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
9
-
10
- skip_react_on_rails_precompile = %w[no false n f].include?(ENV["REACT_ON_RAILS_PRECOMPILE"])
11
-
12
- if !skip_react_on_rails_precompile && !ReactOnRails::WebpackerUtils.webpacker_webpack_production_config_exists?
13
- # Ensure that rails/webpacker does not call bin/webpack if we're providing
14
- # the build command.
15
- ENV["WEBPACKER_PRECOMPILE"] = "false"
16
-
17
- precompile_tasks = lambda {
18
- Rake::Task["react_on_rails:assets:webpack"].invoke
19
- puts "Invoking task webpacker:clean from React on Rails"
20
-
21
- # VERSIONS is per the rails/webpacker clean method definition.
22
- # We set it very big so that it is not used, and then clean just
23
- # removes files older than 1 hour.
24
- versions = 100_000
25
- Rake::Task["webpacker:clean"].invoke(versions)
26
- }
27
-
28
- if Rake::Task.task_defined?("assets:precompile")
29
- Rake::Task["assets:precompile"].enhance do
30
- precompile_tasks.call
31
- end
32
- else
33
- Rake::Task.define_task("assets:precompile") do
34
- precompile_tasks.call
35
- end
36
- end
37
- end
38
-
39
- # Sprockets independent tasks
40
3
  # rubocop:disable Metrics/BlockLength
41
4
  namespace :react_on_rails do
42
5
  namespace :assets do
43
- desc <<-DESC.strip_heredoc
44
- Compile assets with webpack
45
- Uses command defined with ReactOnRails.configuration.build_production_command
46
- sh "#{ReactOnRails::Utils.prepend_cd_node_modules_directory('<ReactOnRails.configuration.build_production_command>')}"
47
- Note: This command is not automatically added to assets:precompile if the rails/webpacker
48
- configuration file config/webpack/production.js exists.
6
+ desc <<~DESC
7
+ If config.build_production_command is defined, this command is automatically
8
+ added to task assets:precompile and the regular webpacker compile will not run.
9
+ The defined command is either a script or a module with a method `call`.
49
10
  DESC
50
11
  task webpack: :locale do
51
12
  build_production_command = ReactOnRails.configuration.build_production_command
@@ -63,13 +24,10 @@ namespace :react_on_rails do
63
24
  exit!(1)
64
25
  end
65
26
  else
27
+ # Left in this warning message in case this rake task is run directly
66
28
  msg = <<~MSG
67
29
  React on Rails is aborting webpack compilation from task react_on_rails:assets:webpack
68
30
  because you do not have the `config.build_production_command` defined.
69
-
70
- Note, this task may have run as part of `assets:precompile`. If file
71
- config/webpack/production.js does not exist, React on Rails will modify
72
- the default `asset:precompile` to run task `react_on_rails:assets:webpack`.
73
31
  MSG
74
32
  puts Rainbow(msg).red
75
33
  exit!(1)
@@ -3,10 +3,9 @@
3
3
  require "react_on_rails/locales/base"
4
4
  require "react_on_rails/locales/to_js"
5
5
  require "react_on_rails/locales/to_json"
6
- require "active_support"
7
6
 
8
7
  namespace :react_on_rails do
9
- desc <<-DESC.strip_heredoc
8
+ desc <<~DESC
10
9
  Generate i18n javascript files
11
10
  This task generates javascript locale files: `translations.js` & `default.js` and places them in
12
11
  the "ReactOnRails.configuration.i18n_dir".
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-on-rails",
3
- "version": "12.4.0",
3
+ "version": "13.0.0",
4
4
  "description": "react-on-rails JavaScript for react_on_rails Ruby gem",
5
5
  "main": "node_package/lib/ReactOnRails.js",
6
6
  "directories": {