react_on_rails 11.0.0 → 11.0.1
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/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
|