react_on_rails 11.0.0 → 11.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -3
- data/README.md +7 -3
- data/docs/basics/upgrading-react-on-rails.md +1 -1
- data/lib/react_on_rails.rb +1 -1
- data/lib/react_on_rails/configuration.rb +4 -2
- data/lib/react_on_rails/react_component/{options.rb → render_options.rb} +14 -8
- data/lib/react_on_rails/react_on_rails_helper.rb +69 -65
- data/lib/react_on_rails/server_rendering_pool.rb +5 -2
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +52 -49
- data/lib/react_on_rails/utils.rb +1 -1
- data/lib/react_on_rails/version.rb +1 -1
- data/package.json +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5dab379803c8e9755573723bf8f5d13189d61254
|
4
|
+
data.tar.gz: 0c85fc367c83791aaa117a6a07661b6bee147ba7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab6c86b708e00be5bb572740c6a980d814199babe92333327bbcfab731ecba0ff106a42d609e1807ba48ad956382488d2c3f2a36b812cbf3368090c9d6378451
|
7
|
+
data.tar.gz: c8a08183a9463ff35a32c64f284005b9bd044369ae4ec24bef4dec67291176ea033cb1ea9448932c56c12a8d79347c4d030de822d8457cd1c5a8bae0c6cb2519
|
data/CHANGELOG.md
CHANGED
@@ -10,19 +10,29 @@ Changes since last non-beta release.
|
|
10
10
|
|
11
11
|
*Please add entries here for your pull requests that are not yet released.*
|
12
12
|
|
13
|
+
### [11.0.1] - 2018-04-23
|
14
|
+
|
15
|
+
#### Added
|
16
|
+
- `react_component` allows logging_on_server specified at the component level. [PR 1068](https://github.com/shakacode/react_on_rails/pull/1068) by [justin808](https://github.com/justin808).
|
17
|
+
|
18
|
+
#### Fixed
|
19
|
+
- Missing class when throwing some error messages. [PR 1068](https://github.com/shakacode/react_on_rails/pull/1068) by [justin808](https://github.com/justin808).
|
20
|
+
|
21
|
+
### [11.0.0] - 2018-04-21
|
22
|
+
|
13
23
|
## MIGRATION for v11
|
14
24
|
- Unused `server_render_method` was removed from the configuration. If you want to use a custom renderer, contact justin@shakacode.com. We have a custom node rendering solution in production for egghead.io.
|
15
25
|
- Removed ReactOnRails::Utils.server_bundle_file_name and ReactOnRails::Utils.bundle_file_name. These are part of the performance features of "React on Rails Pro".
|
16
26
|
- Removed ENV["TRACE_REACT_ON_RAILS"] usage and replacing it with config.trace.
|
17
27
|
|
18
|
-
####
|
28
|
+
#### Enhancements: Better Error Messages, Support for React on Rails Pro
|
19
29
|
- Tracing (debugging) options are simplified with a single `config.trace` setting that defaults to true for development and false otherwise.
|
20
30
|
- Calls to setTimeout, setInterval, clearTimeout will now always log some message if config.trace is true. Your JavaScript code should not be calling setTimout when server rendering.
|
21
31
|
- Errors raised are of type ReactOnRailsError, so you can see they came from React on Rails for debugging.
|
22
32
|
- Removed ReactOnRails::Utils.server_bundle_file_name and ReactOnRails::Utils.bundle_file_name.
|
23
33
|
- No longer logging the `railsContext` when server logging.
|
24
34
|
- Rails.env is provided in the default railsContext, as suggested in [issue #697](https://github.com/shakacode/react_on_rails/issues/697).
|
25
|
-
[PR
|
35
|
+
[PR 1065](https://github.com/shakacode/react_on_rails/pull/1065) by [justin808](https://github.com/justin808).
|
26
36
|
|
27
37
|
#### Fixes
|
28
38
|
- More exact version checking. We keep the react_on_rails gem and the react-on-rails node package at
|
@@ -724,7 +734,8 @@ Best done with Object destructing:
|
|
724
734
|
##### Fixed
|
725
735
|
- Fix several generator related issues.
|
726
736
|
|
727
|
-
[Unreleased]: https://github.com/shakacode/react_on_rails/compare/
|
737
|
+
[Unreleased]: https://github.com/shakacode/react_on_rails/compare/11.0.0...master
|
738
|
+
[11.0.0]: https://github.com/shakacode/react_on_rails/compare/10.1.4...11.0.0
|
728
739
|
[10.1.4]: https://github.com/shakacode/react_on_rails/compare/10.1.3...10.1.4
|
729
740
|
[10.1.3]: https://github.com/shakacode/react_on_rails/compare/10.1.2...10.1.3
|
730
741
|
[10.1.2]: https://github.com/shakacode/react_on_rails/compare/10.1.1...10.1.2
|
data/README.md
CHANGED
@@ -523,13 +523,17 @@ react_component(component_name,
|
|
523
523
|
```
|
524
524
|
|
525
525
|
+ **component_name:** Can be a React component, created using an ES6 class or a generator function that returns a React component (or, only on the server side, an object with shape { redirectLocation, error, renderedHtml }), or a "renderer function" that manually renders a React component to the dom (client side only).
|
526
|
-
|
526
|
+
All options except `props, id, html_options` will inherit from your `react_on_rails.rb` initializer, as described [here](./docs/basics/configuration.md).
|
527
|
+
|
528
|
+
+ **general options:**
|
527
529
|
+ **props:** Ruby Hash which contains the properties to pass to the react object, or a JSON string. If you pass a string, we'll escape it for you.
|
528
530
|
+ **prerender:** enable server-side rendering of a component. Set to false when debugging!
|
529
531
|
+ **id:** Id for the div, will be used to attach the React component. This will get assigned automatically if you do not provide an id. Must be unique.
|
530
532
|
+ **html_options:** Any other HTML options get placed on the added div for the component. For example, you can set a class (or inline style) on the outer div so that it behaves like a span, with the styling of `display:inline-block`.
|
531
|
-
+ **trace:** set to true to print additional debugging information in the browser. Defaults to true for development, off otherwise.
|
532
|
-
|
533
|
+
+ **trace:** set to true to print additional debugging information in the browser. Defaults to true for development, off otherwise. Only on the **client side** will you will see the `railsContext` and your props.
|
534
|
+
+ **options if prerender (server rendering) is true:**
|
535
|
+
+ **replay_console:** Default is true. False will disable echoing server-rendering logs to the browser. While this can make troubleshooting server rendering difficult, so long as you have the configuration of `logging_on_server` set to true, you'll still see the errors on the server.
|
536
|
+
+ **logging_on_server:** Default is true. True will log JS console messages and errors to the server.
|
533
537
|
+ **raise_on_prerender_error:** Default is false. True will throw an error on the server side rendering. Your controller will have to handle the error.
|
534
538
|
|
535
539
|
### redux_store
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
## Upgrading to version 11
|
4
4
|
* Remove `server_render_method` from config/initializers/react_on_rails.rb. Alternate server rendering methods are part of React on Rails Pro. If you want to use a custom renderer, contact justin@shakacode.com. We have a custom node rendering solution in production for egghead.io.
|
5
|
-
* Remove your usage of ENV["TRACE_REACT_ON_RAILS"] usage. You can get all tracing with either specifying trace at your component or in your config/initializers/react_on_rails.rb file.
|
5
|
+
* Remove your usage of ENV["TRACE_REACT_ON_RAILS"] usage. You can get all tracing with either specifying **`trace`** at your component or in your config/initializers/react_on_rails.rb file.
|
6
6
|
* ReactOnRails::Utils.server_bundle_file_name and ReactOnRails::Utils.bundle_file_name were removed. React on Rails Pro contains upgrades to enable component and other types caching with React on Rails.
|
7
7
|
|
8
8
|
|
data/lib/react_on_rails.rb
CHANGED
@@ -10,7 +10,7 @@ require "react_on_rails/version_checker"
|
|
10
10
|
require "react_on_rails/configuration"
|
11
11
|
require "react_on_rails/server_rendering_pool"
|
12
12
|
require "react_on_rails/engine"
|
13
|
-
require "react_on_rails/react_component/
|
13
|
+
require "react_on_rails/react_component/render_options"
|
14
14
|
require "react_on_rails/version_syntax_converter"
|
15
15
|
require "react_on_rails/test_helper"
|
16
16
|
require "react_on_rails/git_utils"
|
@@ -9,6 +9,8 @@ module ReactOnRails
|
|
9
9
|
end
|
10
10
|
|
11
11
|
DEFAULT_GENERATED_ASSETS_DIR = File.join(%w[public webpack], Rails.env).freeze
|
12
|
+
DEFAULT_SERVER_RENDER_TIMEOUT = 20
|
13
|
+
DEFAULT_POOL_SIZE = 1
|
12
14
|
|
13
15
|
def self.setup_config_values
|
14
16
|
ensure_webpack_generated_files_exists
|
@@ -112,8 +114,8 @@ module ReactOnRails
|
|
112
114
|
raise_on_prerender_error: false,
|
113
115
|
trace: Rails.env.development?,
|
114
116
|
development_mode: Rails.env.development?,
|
115
|
-
server_renderer_pool_size:
|
116
|
-
server_renderer_timeout:
|
117
|
+
server_renderer_pool_size: DEFAULT_POOL_SIZE,
|
118
|
+
server_renderer_timeout: DEFAULT_SERVER_RENDER_TIMEOUT,
|
117
119
|
skip_display_none: nil,
|
118
120
|
# skip_display_none is deprecated
|
119
121
|
webpack_generated_files: %w[manifest.json],
|
@@ -4,24 +4,22 @@ require "react_on_rails/utils"
|
|
4
4
|
|
5
5
|
module ReactOnRails
|
6
6
|
module ReactComponent
|
7
|
-
class
|
7
|
+
class RenderOptions
|
8
8
|
include Utils::Required
|
9
9
|
|
10
10
|
NO_PROPS = {}.freeze
|
11
11
|
|
12
|
-
def initialize(
|
13
|
-
@
|
12
|
+
def initialize(react_component_name: required("react_component_name"), options: required("options"))
|
13
|
+
@react_component_name = react_component_name.camelize
|
14
14
|
@options = options
|
15
15
|
end
|
16
16
|
|
17
|
+
attr_reader :react_component_name
|
18
|
+
|
17
19
|
def props
|
18
20
|
options.fetch(:props) { NO_PROPS }
|
19
21
|
end
|
20
22
|
|
21
|
-
def name
|
22
|
-
@name.camelize
|
23
|
-
end
|
24
|
-
|
25
23
|
def dom_id
|
26
24
|
@dom_id ||= options.fetch(:id) { generate_unique_dom_id }
|
27
25
|
end
|
@@ -46,12 +44,20 @@ module ReactOnRails
|
|
46
44
|
retrieve_key(:raise_on_prerender_error)
|
47
45
|
end
|
48
46
|
|
47
|
+
def logging_on_server
|
48
|
+
retrieve_key(:logging_on_server)
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
"{ react_component_name = #{react_component_name}, options = #{options}"
|
53
|
+
end
|
54
|
+
|
49
55
|
private
|
50
56
|
|
51
57
|
attr_reader :options
|
52
58
|
|
53
59
|
def generate_unique_dom_id
|
54
|
-
"#{
|
60
|
+
"#{react_component_name}-react-component-#{SecureRandom.uuid}"
|
55
61
|
end
|
56
62
|
|
57
63
|
def retrieve_key(key)
|
@@ -98,17 +98,17 @@ module ReactOnRails
|
|
98
98
|
# raise_on_prerender_error: <true/false> Default to false. True will raise exception on server
|
99
99
|
# if the JS code throws
|
100
100
|
# Any other options are passed to the content tag, including the id.
|
101
|
-
def react_component(component_name,
|
102
|
-
internal_result = internal_react_component(component_name,
|
103
|
-
server_rendered_html = internal_result[
|
104
|
-
console_script = internal_result[
|
101
|
+
def react_component(component_name, options = {})
|
102
|
+
internal_result = internal_react_component(component_name, options)
|
103
|
+
server_rendered_html = internal_result[:result]["html"]
|
104
|
+
console_script = internal_result[:result]["consoleReplayScript"]
|
105
105
|
|
106
106
|
if server_rendered_html.is_a?(String)
|
107
107
|
build_react_component_result_for_server_rendered_string(
|
108
108
|
server_rendered_html: server_rendered_html,
|
109
|
-
component_specification_tag: internal_result[
|
109
|
+
component_specification_tag: internal_result[:tag],
|
110
110
|
console_script: console_script,
|
111
|
-
|
111
|
+
render_options: internal_result[:render_options]
|
112
112
|
)
|
113
113
|
elsif server_rendered_html.is_a?(Hash)
|
114
114
|
msg = <<-MSG.strip_heredoc
|
@@ -116,7 +116,7 @@ module ReactOnRails
|
|
116
116
|
https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/client/app/startup/ReactHelmetServerApp.jsx
|
117
117
|
for an example of the necessary javascript configuration."
|
118
118
|
MSG
|
119
|
-
raise
|
119
|
+
raise ReactOnRails::Error, msg
|
120
120
|
|
121
121
|
else
|
122
122
|
msg = <<-MSG.strip_heredoc
|
@@ -126,17 +126,17 @@ module ReactOnRails
|
|
126
126
|
https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/client/app/startup/ReactHelmetServerApp.jsx
|
127
127
|
for an example of the necessary javascript configuration."
|
128
128
|
MSG
|
129
|
-
raise
|
129
|
+
raise ReactOnRails::Error, msg
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
133
|
-
def react_component_hash(component_name,
|
134
|
-
internal_result = internal_react_component(component_name,
|
135
|
-
server_rendered_html = internal_result[
|
136
|
-
console_script = internal_result[
|
133
|
+
def react_component_hash(component_name, options = {})
|
134
|
+
internal_result = internal_react_component(component_name, options)
|
135
|
+
server_rendered_html = internal_result[:result]["html"]
|
136
|
+
console_script = internal_result[:result]["consoleReplayScript"]
|
137
137
|
|
138
|
-
if server_rendered_html.is_a?(String) && internal_result[
|
139
|
-
server_rendered_html = { COMPONENT_HTML_KEY => internal_result[
|
138
|
+
if server_rendered_html.is_a?(String) && internal_result[:result]["hasErrors"]
|
139
|
+
server_rendered_html = { COMPONENT_HTML_KEY => internal_result[:result]["html"] }
|
140
140
|
end
|
141
141
|
|
142
142
|
if server_rendered_html.is_a?(Hash)
|
@@ -144,7 +144,7 @@ module ReactOnRails
|
|
144
144
|
server_rendered_html: server_rendered_html,
|
145
145
|
component_specification_tag: internal_result["tag"],
|
146
146
|
console_script: console_script,
|
147
|
-
|
147
|
+
render_options: internal_result[:render_options]
|
148
148
|
)
|
149
149
|
else
|
150
150
|
msg = <<-MSG.strip_heredoc
|
@@ -152,7 +152,7 @@ module ReactOnRails
|
|
152
152
|
https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/client/app/startup/ReactHelmetServerApp.jsx
|
153
153
|
for an example of the necessary javascript configuration.
|
154
154
|
MSG
|
155
|
-
raise
|
155
|
+
raise ReactOnRails::Error, msg
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
@@ -199,8 +199,12 @@ module ReactOnRails
|
|
199
199
|
# Helper method to take javascript expression and returns the output from evaluating it.
|
200
200
|
# If you have more than one line that needs to be executed, wrap it in an IIFE.
|
201
201
|
# JS exceptions are caught and console messages are handled properly.
|
202
|
+
# Options include:{ prerender:, trace:, raise_on_prerender_error: }
|
202
203
|
def server_render_js(js_expression, options = {})
|
203
|
-
|
204
|
+
render_options = ReactOnRails::ReactComponent::RenderOptions
|
205
|
+
.new(react_component_name: "generic-js", options: options)
|
206
|
+
|
207
|
+
js_code = <<-JS.strip_heredoc
|
204
208
|
(function() {
|
205
209
|
var htmlResult = '';
|
206
210
|
var consoleReplayScript = '';
|
@@ -228,15 +232,16 @@ module ReactOnRails
|
|
228
232
|
})()
|
229
233
|
JS
|
230
234
|
|
231
|
-
result = ReactOnRails::ServerRenderingPool
|
235
|
+
result = ReactOnRails::ServerRenderingPool
|
236
|
+
.server_render_js_with_console_logging(js_code, render_options)
|
232
237
|
|
233
238
|
html = result["html"]
|
234
239
|
console_log_script = result["consoleLogScript"]
|
235
|
-
raw("#{html}#{
|
240
|
+
raw("#{html}#{render_options.replay_console ? console_log_script : ''}")
|
236
241
|
rescue ExecJS::ProgramError => err
|
237
242
|
raise ReactOnRails::PrerenderError, component_name: "N/A (server_render_js called)",
|
238
243
|
err: err,
|
239
|
-
js_code:
|
244
|
+
js_code: js_code
|
240
245
|
end
|
241
246
|
|
242
247
|
def json_safe_and_pretty(hash_or_string)
|
@@ -257,16 +262,16 @@ module ReactOnRails
|
|
257
262
|
server_rendered_html: required("server_rendered_html"),
|
258
263
|
component_specification_tag: required("component_specification_tag"),
|
259
264
|
console_script: required("console_script"),
|
260
|
-
|
265
|
+
render_options: required("render_options")
|
261
266
|
)
|
262
|
-
content_tag_options =
|
263
|
-
content_tag_options[:id] =
|
267
|
+
content_tag_options = render_options.html_options
|
268
|
+
content_tag_options[:id] = render_options.dom_id
|
264
269
|
|
265
270
|
rendered_output = content_tag(:div,
|
266
271
|
server_rendered_html.html_safe,
|
267
272
|
content_tag_options)
|
268
273
|
|
269
|
-
result_console_script =
|
274
|
+
result_console_script = render_options.replay_console ? console_script : ""
|
270
275
|
result = compose_react_component_html_with_spec_and_console(
|
271
276
|
component_specification_tag, rendered_output, result_console_script
|
272
277
|
)
|
@@ -278,20 +283,20 @@ module ReactOnRails
|
|
278
283
|
server_rendered_html: required("server_rendered_html"),
|
279
284
|
component_specification_tag: required("component_specification_tag"),
|
280
285
|
console_script: required("console_script"),
|
281
|
-
|
286
|
+
render_options: required("render_options")
|
282
287
|
)
|
283
|
-
content_tag_options =
|
284
|
-
content_tag_options[:id] =
|
288
|
+
content_tag_options = render_options.html_options
|
289
|
+
content_tag_options[:id] = render_options.dom_id
|
285
290
|
|
286
291
|
unless server_rendered_html[COMPONENT_HTML_KEY]
|
287
|
-
raise
|
292
|
+
raise ReactOnRails::Error, "server_rendered_html hash expected to contain \"#{COMPONENT_HTML_KEY}\" key."
|
288
293
|
end
|
289
294
|
|
290
295
|
rendered_output = content_tag(:div,
|
291
296
|
server_rendered_html[COMPONENT_HTML_KEY].html_safe,
|
292
297
|
content_tag_options)
|
293
298
|
|
294
|
-
result_console_script =
|
299
|
+
result_console_script = render_options.replay_console ? console_script : ""
|
295
300
|
result = compose_react_component_html_with_spec_and_console(
|
296
301
|
component_specification_tag, rendered_output, result_console_script
|
297
302
|
)
|
@@ -335,7 +340,7 @@ module ReactOnRails
|
|
335
340
|
"#{rails_context_content}\n#{render_value}".html_safe
|
336
341
|
end
|
337
342
|
|
338
|
-
def internal_react_component(
|
343
|
+
def internal_react_component(react_component_name, options = {})
|
339
344
|
# Create the JavaScript and HTML to allow either client or server rendering of the
|
340
345
|
# react_component.
|
341
346
|
#
|
@@ -343,27 +348,27 @@ module ReactOnRails
|
|
343
348
|
# (re-hydrate the data). This enables react rendered on the client to see that the
|
344
349
|
# server has already rendered the HTML.
|
345
350
|
|
346
|
-
|
351
|
+
render_options = ReactOnRails::ReactComponent::RenderOptions.new(react_component_name: react_component_name,
|
352
|
+
options: options)
|
347
353
|
|
348
354
|
# Setup the page_loaded_js, which is the same regardless of prerendering or not!
|
349
355
|
# The reason is that React is smart about not doing extra work if the server rendering did its job.
|
350
356
|
component_specification_tag = content_tag(:script,
|
351
|
-
json_safe_and_pretty(
|
357
|
+
json_safe_and_pretty(render_options.props).html_safe,
|
352
358
|
type: "application/json",
|
353
359
|
class: "js-react-on-rails-component",
|
354
|
-
"data-component-name" =>
|
355
|
-
"data-trace" => (
|
356
|
-
"data-dom-id" =>
|
360
|
+
"data-component-name" => render_options.react_component_name,
|
361
|
+
"data-trace" => (render_options.trace ? true : nil),
|
362
|
+
"data-dom-id" => render_options.dom_id)
|
357
363
|
|
358
364
|
# Create the HTML rendering part
|
359
|
-
result =
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
{ "options" => options, "tag" => component_specification_tag, "result" => result }
|
365
|
+
result = server_rendered_react_component(render_options)
|
366
|
+
|
367
|
+
{
|
368
|
+
render_options: render_options,
|
369
|
+
tag: component_specification_tag,
|
370
|
+
result: result
|
371
|
+
}
|
367
372
|
end
|
368
373
|
|
369
374
|
def render_redux_store_data(redux_store_data)
|
@@ -379,15 +384,12 @@ module ReactOnRails
|
|
379
384
|
props.is_a?(String) ? props : props.to_json
|
380
385
|
end
|
381
386
|
|
382
|
-
# Returns
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
raise_on_prerender_error: required("raise_on_prerender_error")
|
389
|
-
)
|
390
|
-
return { "html" => "", "consoleReplayScript" => "" } unless prerender
|
387
|
+
# Returns object with values that are NOT html_safe!
|
388
|
+
def server_rendered_react_component(render_options)
|
389
|
+
return { "html" => "", "consoleReplayScript" => "" } unless render_options.prerender
|
390
|
+
|
391
|
+
react_component_name = render_options.react_component_name
|
392
|
+
props = render_options.props
|
391
393
|
|
392
394
|
# On server `location` option is added (`location = request.fullpath`)
|
393
395
|
# React Router needs this to match the current route
|
@@ -411,42 +413,44 @@ module ReactOnRails
|
|
411
413
|
# Read more here: http://timelessrepo.com/json-isnt-a-javascript-subset
|
412
414
|
|
413
415
|
# rubocop:disable Layout/IndentHeredoc
|
414
|
-
|
416
|
+
js_code = <<-JS
|
415
417
|
(function() {
|
416
418
|
var railsContext = #{rails_context(server_side: true).to_json};
|
417
419
|
#{initialize_redux_stores}
|
418
420
|
var props = #{props_string(props).gsub("\u2028", '\u2028').gsub("\u2029", '\u2029')};
|
419
421
|
return ReactOnRails.serverRenderReactComponent({
|
420
422
|
name: '#{react_component_name}',
|
421
|
-
domNodeId: '#{dom_id}',
|
423
|
+
domNodeId: '#{render_options.dom_id}',
|
422
424
|
props: props,
|
423
|
-
trace: #{trace},
|
425
|
+
trace: #{render_options.trace},
|
424
426
|
railsContext: railsContext
|
425
427
|
});
|
426
428
|
})()
|
427
429
|
JS
|
428
430
|
# rubocop:enable Layout/IndentHeredoc
|
429
431
|
|
430
|
-
|
432
|
+
begin
|
433
|
+
result = ReactOnRails::ServerRenderingPool.server_render_js_with_console_logging(js_code, render_options)
|
434
|
+
rescue StandardError => err
|
435
|
+
# This error came from the renderer
|
436
|
+
raise ReactOnRails::PrerenderError, component_name: react_component_name,
|
437
|
+
# Sanitize as this might be browser logged
|
438
|
+
props: sanitized_props_string(props),
|
439
|
+
err: err,
|
440
|
+
js_code: js_code
|
441
|
+
end
|
431
442
|
|
432
|
-
if result["hasErrors"] && raise_on_prerender_error
|
443
|
+
if result["hasErrors"] && render_options.raise_on_prerender_error
|
433
444
|
# We caught this exception on our backtrace handler
|
434
445
|
raise ReactOnRails::PrerenderError, component_name: react_component_name,
|
435
446
|
# Sanitize as this might be browser logged
|
436
447
|
props: sanitized_props_string(props),
|
437
448
|
err: nil,
|
438
|
-
js_code:
|
449
|
+
js_code: js_code,
|
439
450
|
console_messages: result["consoleReplayScript"]
|
440
451
|
|
441
452
|
end
|
442
453
|
result
|
443
|
-
rescue ExecJS::ProgramError => err
|
444
|
-
# This error came from execJs
|
445
|
-
raise ReactOnRails::PrerenderError, component_name: react_component_name,
|
446
|
-
# Sanitize as this might be browser logged
|
447
|
-
props: sanitized_props_string(props),
|
448
|
-
err: err,
|
449
|
-
js_code: wrapper_js
|
450
454
|
end
|
451
455
|
|
452
456
|
def initialize_redux_stores
|
@@ -21,8 +21,11 @@ module ReactOnRails
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
delegate :
|
25
|
-
|
24
|
+
delegate :reset_pool_if_server_bundle_was_modified, :reset_pool, to: :pool
|
25
|
+
|
26
|
+
def server_render_js_with_console_logging(js_code, render_options)
|
27
|
+
@pool.exec_server_render_js(js_code, render_options)
|
28
|
+
end
|
26
29
|
|
27
30
|
private
|
28
31
|
|
@@ -5,61 +5,65 @@ require "open-uri"
|
|
5
5
|
module ReactOnRails
|
6
6
|
module ServerRenderingPool
|
7
7
|
class RubyEmbeddedJavaScript
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
def self.reset_pool_if_server_bundle_was_modified
|
17
|
-
return unless ReactOnRails.configuration.development_mode
|
8
|
+
class << self
|
9
|
+
def reset_pool
|
10
|
+
options = {
|
11
|
+
size: ReactOnRails.configuration.server_renderer_pool_size,
|
12
|
+
timeout: ReactOnRails.configuration.server_renderer_timeout
|
13
|
+
}
|
14
|
+
@js_context_pool = ConnectionPool.new(options) { create_js_context }
|
15
|
+
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
return if @server_bundle_timestamp == file_mtime
|
17
|
+
def reset_pool_if_server_bundle_was_modified
|
18
|
+
return unless ReactOnRails.configuration.development_mode
|
22
19
|
|
23
|
-
|
20
|
+
file_mtime = File.mtime(ReactOnRails::Utils.server_bundle_js_file_path)
|
21
|
+
@server_bundle_timestamp ||= file_mtime
|
22
|
+
return if @server_bundle_timestamp == file_mtime
|
24
23
|
|
25
|
-
|
26
|
-
end
|
24
|
+
@server_bundle_timestamp = file_mtime
|
27
25
|
|
28
|
-
|
29
|
-
# Returns a Hash:
|
30
|
-
# html: string of HTML for direct insertion on the page by evaluating js_code
|
31
|
-
# consoleReplayScript: script for replaying console
|
32
|
-
# hasErrors: true if server rendering errors
|
33
|
-
# Note, js_code does not have to be based on React.
|
34
|
-
# js_code MUST RETURN json stringify Object
|
35
|
-
# Calling code will probably call 'html_safe' on return value before rendering to the view.
|
36
|
-
def self.server_render_js_with_console_logging(js_code)
|
37
|
-
if ReactOnRails.configuration.trace
|
38
|
-
@file_index ||= 1
|
39
|
-
trace_js_code_used("Evaluating code to server render.", js_code,
|
40
|
-
"tmp/server-generated-#{@file_index % 10}.js")
|
41
|
-
@file_index += 1
|
26
|
+
ReactOnRails::ServerRenderingPool.reset_pool
|
42
27
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
28
|
+
|
29
|
+
# js_code: JavaScript expression that returns a string.
|
30
|
+
# render_options: lib/react_on_rails/react_component/render_options.rb
|
31
|
+
# Using these options:
|
32
|
+
# trace: saves the executed JS to a file, used in development
|
33
|
+
# logging_on_server: put on server logs, not just in browser console
|
34
|
+
#
|
35
|
+
# Returns a Hash:
|
36
|
+
# html: string of HTML for direct insertion on the page by evaluating js_code
|
37
|
+
# consoleReplayScript: script for replaying console
|
38
|
+
# hasErrors: true if server rendering errors
|
39
|
+
# Note, js_code does not have to be based on React.
|
40
|
+
# js_code MUST RETURN json stringify Object
|
41
|
+
# Calling code will probably call 'html_safe' on return value before rendering to the view.
|
42
|
+
def exec_server_render_js(js_code, render_options, js_evaluator = nil)
|
43
|
+
js_evaluator ||= self
|
44
|
+
if render_options.trace
|
45
|
+
@file_index ||= 1
|
46
|
+
trace_js_code_used("Evaluating code to server render.", js_code,
|
47
|
+
"tmp/server-generated-#{@file_index % 10}.js")
|
48
|
+
@file_index += 1
|
49
|
+
end
|
50
|
+
json_string = js_evaluator.eval_js(js_code)
|
51
|
+
result = JSON.parse(json_string)
|
52
|
+
|
53
|
+
if render_options.logging_on_server
|
54
|
+
console_script = result["consoleReplayScript"]
|
55
|
+
console_script_lines = console_script.split("\n")
|
56
|
+
console_script_lines = console_script_lines[2..-2]
|
57
|
+
re = /console\.(log|error)\.apply\(console, \["\[SERVER\] (?<msg>.*)"\]\);/
|
58
|
+
if console_script_lines
|
59
|
+
console_script_lines.each do |line|
|
60
|
+
match = re.match(line)
|
61
|
+
Rails.logger.info { "[react_on_rails] #{match[:msg]}" } if match
|
62
|
+
end
|
55
63
|
end
|
56
64
|
end
|
65
|
+
result
|
57
66
|
end
|
58
|
-
result
|
59
|
-
end
|
60
|
-
|
61
|
-
class << self
|
62
|
-
private
|
63
67
|
|
64
68
|
def trace_js_code_used(msg, js_code, file_name = "tmp/server-generated.js", force: false)
|
65
69
|
return unless ReactOnRails.configuration.trace || force
|
@@ -156,8 +160,7 @@ function clearTimeout() {
|
|
156
160
|
|
157
161
|
def undefined_for_exec_js_logging(function_name)
|
158
162
|
if ReactOnRails.configuration.trace
|
159
|
-
"console.error('[React on Rails Rendering] #{function_name} is not defined for
|
160
|
-
"https://github.com/sstephenson/execjs#faq. Note babel-polyfill may call this.');\n"\
|
163
|
+
"console.error('[React on Rails Rendering] #{function_name} is not defined for server rendering.');\n"\
|
161
164
|
" console.error(getStackTrace().join('\\n'));"
|
162
165
|
else
|
163
166
|
""
|
data/lib/react_on_rails/utils.rb
CHANGED
data/package.json
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: react_on_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 11.0.
|
4
|
+
version: 11.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Gordon
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -438,7 +438,7 @@ files:
|
|
438
438
|
- lib/react_on_rails/json_output.rb
|
439
439
|
- lib/react_on_rails/locales_to_js.rb
|
440
440
|
- lib/react_on_rails/prerender_error.rb
|
441
|
-
- lib/react_on_rails/react_component/
|
441
|
+
- lib/react_on_rails/react_component/render_options.rb
|
442
442
|
- lib/react_on_rails/react_on_rails_helper.rb
|
443
443
|
- lib/react_on_rails/server_rendering_pool.rb
|
444
444
|
- lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb
|