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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +3 -1
- data/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/main.yml +3 -3
- data/.gitignore +0 -3
- data/.prettierignore +2 -0
- data/CHANGELOG.md +39 -2
- data/Gemfile.development_dependencies +7 -6
- data/REACT-ON-RAILS-PRO-LICENSE +1 -1
- data/README.md +20 -13
- data/SUMMARY.md +9 -0
- data/docs/deployment/heroku-deployment.md +16 -5
- data/docs/guides/configuration.md +29 -15
- data/docs/guides/hmr-and-hot-reloading-with-the-webpack-dev-server.md +4 -4
- data/docs/guides/how-react-on-rails-works.md +1 -2
- data/docs/guides/rspec-configuration.md +1 -1
- data/docs/guides/tutorial.md +27 -27
- data/docs/guides/upgrading-react-on-rails.md +15 -0
- data/docs/guides/webpack-configuration.md +1 -1
- data/docs/javascript/converting-from-custom-webpack-config-to-rails-webpacker-config.md +2 -2
- data/lib/generators/react_on_rails/base_generator.rb +55 -10
- data/lib/generators/react_on_rails/generator_helper.rb +4 -0
- data/lib/generators/react_on_rails/templates/.eslintrc +3 -1
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +4 -8
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static +9 -0
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +4 -0
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js +5 -0
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js +8 -0
- data/lib/generators/react_on_rails/templates/base/base/app/views/layouts/hello_world.html.erb +1 -0
- data/lib/generators/react_on_rails/templates/base/base/babel.config.js.tt +32 -0
- data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +3 -3
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt +17 -0
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt +15 -0
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +25 -0
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/production.js.tt +9 -0
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +117 -0
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/test.js.tt +6 -0
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpack.config.js.tt +15 -0
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpackConfig.js.tt +36 -0
- data/lib/generators/react_on_rails/templates/base/base/config/webpacker.yml +62 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
- data/lib/react_on_rails/configuration.rb +40 -41
- data/lib/react_on_rails/helper.rb +18 -17
- data/lib/react_on_rails/json_parse_error.rb +1 -1
- data/lib/react_on_rails/locales/base.rb +1 -3
- data/lib/react_on_rails/prerender_error.rb +5 -2
- data/lib/react_on_rails/react_component/render_options.rb +14 -0
- data/lib/react_on_rails/server_rendering_js_code.rb +13 -0
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +27 -10
- data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +3 -3
- data/lib/react_on_rails/test_helper.rb +2 -2
- data/lib/react_on_rails/version.rb +1 -1
- data/lib/react_on_rails/webpacker_utils.rb +2 -7
- data/lib/tasks/assets.rake +5 -47
- data/lib/tasks/locale.rake +1 -2
- data/package.json +1 -1
- data/rakelib/example_type.rb +10 -3
- data/rakelib/examples.rake +3 -5
- data/rakelib/release.rake +7 -1
- data/react_on_rails.gemspec +2 -3
- data/yarn.lock +117 -71
- metadata +22 -21
- 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
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
Rails
|
|
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
|
-
|
|
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
|
-
|
|
226
|
-
|
|
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
|
-
|
|
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
|
-
|
|
237
|
-
|
|
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
|
-
|
|
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
|
|
238
|
-
|
|
239
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
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
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
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
|
|
@@ -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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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? &&
|
|
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
|
-
|
|
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
|
-
|
|
70
|
-
|
|
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
|
-
|
|
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
|
-
|
|
76
|
-
|
|
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
|
|
|
@@ -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
|
-
|
|
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?
|
data/lib/tasks/assets.rake
CHANGED
|
@@ -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
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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)
|
data/lib/tasks/locale.rake
CHANGED
|
@@ -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
|
|
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".
|