react_on_rails 14.0.4 → 15.0.0.alpha.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 +23 -2
- data/Gemfile.development_dependencies +2 -0
- data/Gemfile.lock +6 -1
- data/README.md +1 -0
- data/SUMMARY.md +1 -0
- data/lib/react_on_rails/configuration.rb +7 -3
- data/lib/react_on_rails/helper.rb +144 -18
- data/lib/react_on_rails/react_component/render_options.rb +20 -0
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +34 -20
- data/lib/react_on_rails/version.rb +1 -1
- data/tsconfig.json +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7d60051000fbd817b3499b1de6f13c9abeaf5627bee250c50bf0d748ce3532a5
|
|
4
|
+
data.tar.gz: 4eccfe81e12b647503fa6e690c514d4d14d6704ab1e5c7f64282cafa7709d6e2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 99004f6792fe209d21474c7b5b311ac8a02cce27740b69164e44079983a5852895aa99ed12530043ba64ad6920d189cb6b19ce3957aca83b6bab06f75bf702ee
|
|
7
|
+
data.tar.gz: 2be5eb3178a913c90c7b4e640812bccc479245d0052d95751317f543c80e7bf9429f9fd61cbc1c5edb917aafbead33502c75fb63fd8ab183480aaa44124f3dc5
|
data/CHANGELOG.md
CHANGED
|
@@ -18,6 +18,26 @@ Please follow the recommendations outlined at [keepachangelog.com](http://keepac
|
|
|
18
18
|
### [Unreleased]
|
|
19
19
|
Changes since the last non-beta release.
|
|
20
20
|
|
|
21
|
+
#### Added(https://github.com/AbanoubGhadban).
|
|
22
|
+
- Added streaming server rendering support:
|
|
23
|
+
- [PR #1633](https://github.com/shakacode/react_on_rails/pull/1633) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
|
|
24
|
+
- New `stream_react_component` helper for adding streamed components to views
|
|
25
|
+
- New `streamServerRenderedReactComponent` function in the react-on-rails package that uses React 18's `renderToPipeableStream` API
|
|
26
|
+
- Enables progressive page loading and improved performance for server-rendered React components
|
|
27
|
+
- Added support for replaying console logs that occur during server rendering of streamed React components. This enables debugging of server-side rendering issues by capturing and displaying console output on the client and on the server output. [PR #1647](https://github.com/shakacode/react_on_rails/pull/1647) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
|
|
28
|
+
- Added support for handling errors happening during server rendering of streamed React components. It handles errors that happen during the initial render and errors that happen inside suspense boundaries. [PR #1648](https://github.com/shakacode/react_on_rails/pull/1648) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
|
|
29
|
+
|
|
30
|
+
#### Changed
|
|
31
|
+
- Console replay script generation now awaits the render request promise before generating, allowing it to capture console logs from asynchronous operations. This requires using a version of the Node renderer that supports replaying async console logs. [PR #1649](https://github.com/shakacode/react_on_rails/pull/1649) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
|
|
32
|
+
|
|
33
|
+
#### Fixed
|
|
34
|
+
- Incorrect type and confusing name for `ReactOnRails.registerStore`, use `registerStoreGenerators` instead. [PR 1651](https://github.com/shakacode/react_on_rails/pull/1651) by [alexeyr-ci](https://github.com/alexeyr-ci).
|
|
35
|
+
|
|
36
|
+
### [14.0.5] - 2024-08-20
|
|
37
|
+
#### Fixed
|
|
38
|
+
- Should force load react-components which send over turbo-stream [PR #1620](https://github.com/shakacode/react_on_rails/pull/1620) by [theforestvn88](https://github.com/theforestvn88).
|
|
39
|
+
|
|
40
|
+
### [14.0.4] - 2024-07-02
|
|
21
41
|
|
|
22
42
|
#### Improved
|
|
23
43
|
- Improved dependency management by integrating package_json. [PR 1639](https://github.com/shakacode/react_on_rails/pull/1639) by [vaukalak](https://github.com/vaukalak).
|
|
@@ -25,7 +45,6 @@ Changes since the last non-beta release.
|
|
|
25
45
|
#### Changed
|
|
26
46
|
- Update outdated GitHub Actions to use Node.js 20.0 versions instead [PR 1623](https://github.com/shakacode/react_on_rails/pull/1623) by [adriangohjw](https://github.com/adriangohjw).
|
|
27
47
|
|
|
28
|
-
|
|
29
48
|
### [14.0.3] - 2024-06-28
|
|
30
49
|
|
|
31
50
|
#### Fixed
|
|
@@ -1148,7 +1167,9 @@ Best done with Object destructing:
|
|
|
1148
1167
|
##### Fixed
|
|
1149
1168
|
- Fix several generator-related issues.
|
|
1150
1169
|
|
|
1151
|
-
[Unreleased]: https://github.com/shakacode/react_on_rails/compare/14.0.
|
|
1170
|
+
[Unreleased]: https://github.com/shakacode/react_on_rails/compare/14.0.5...master
|
|
1171
|
+
[14.0.5]: https://github.com/shakacode/react_on_rails/compare/14.0.4...14.0.5
|
|
1172
|
+
[14.0.4]: https://github.com/shakacode/react_on_rails/compare/14.0.3...14.0.4
|
|
1152
1173
|
[14.0.3]: https://github.com/shakacode/react_on_rails/compare/14.0.2...14.0.3
|
|
1153
1174
|
[14.0.2]: https://github.com/shakacode/react_on_rails/compare/14.0.1...14.0.2
|
|
1154
1175
|
[14.0.1]: https://github.com/shakacode/react_on_rails/compare/14.0.0...14.0.1
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
react_on_rails (14.0.
|
|
4
|
+
react_on_rails (14.0.5)
|
|
5
5
|
addressable
|
|
6
6
|
connection_pool
|
|
7
7
|
execjs (~> 2.5)
|
|
@@ -369,6 +369,10 @@ GEM
|
|
|
369
369
|
tins (1.33.0)
|
|
370
370
|
bigdecimal
|
|
371
371
|
sync
|
|
372
|
+
turbo-rails (2.0.6)
|
|
373
|
+
actionpack (>= 6.0.0)
|
|
374
|
+
activejob (>= 6.0.0)
|
|
375
|
+
railties (>= 6.0.0)
|
|
372
376
|
turbolinks (5.2.1)
|
|
373
377
|
turbolinks-source (~> 5.2)
|
|
374
378
|
turbolinks-source (5.2.0)
|
|
@@ -431,6 +435,7 @@ DEPENDENCIES
|
|
|
431
435
|
spring (~> 4.0)
|
|
432
436
|
sprockets (~> 4.0)
|
|
433
437
|
sqlite3 (~> 1.6)
|
|
438
|
+
turbo-rails
|
|
434
439
|
turbolinks
|
|
435
440
|
uglifier
|
|
436
441
|
webdrivers (= 5.3.0)
|
data/README.md
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
[](https://github.com/shakacode/react_on_rails/actions/workflows/lint-js-and-ruby.yml)
|
|
18
18
|
|
|
19
19
|
# News
|
|
20
|
+
* [React on Rails Pro](https://www.shakacode.com/react-on-rails-pro/) supports the latest features of React 18, including [React Server Components](https://react.dev/reference/rsc/server-components) and [streaming](https://react.dev/reference/react-dom/server/renderToPipeableStream). Contact [Justin Gordon](mailto:justin@shakacode.com) for more information.
|
|
20
21
|
* ShakaCode now maintains the official successor to `rails/webpacker`, [`shakapacker`](https://github.com/shakacode/shakapacker).
|
|
21
22
|
* Project is updated to support Rails 7 and Shakapacker v6+!
|
|
22
23
|
|
data/SUMMARY.md
CHANGED
|
@@ -17,6 +17,7 @@ Here is the new link:
|
|
|
17
17
|
+ [How React on Rails Works](docs/outdated/how-react-on-rails-works.md)
|
|
18
18
|
+ [Client vs. Server Rendering](./docs/guides/client-vs-server-rendering.md)
|
|
19
19
|
+ [React Server Rendering](./docs/guides/react-server-rendering.md)
|
|
20
|
+
+ [🚀 Next-Gen Server Rendering: Streaming with React 18's Latest APIs](./docs/guides/streaming-server-rendering.md)
|
|
20
21
|
+ [Render-Functions and the RailsContext](docs/guides/render-functions-and-railscontext.md)
|
|
21
22
|
+ [Caching and Performance: React on Rails Pro](https://github.com/shakacode/react_on_rails/wiki).
|
|
22
23
|
+ [Deployment](docs/guides/deployment.md).
|
|
@@ -39,7 +39,9 @@ module ReactOnRails
|
|
|
39
39
|
i18n_output_format: nil,
|
|
40
40
|
components_subdirectory: nil,
|
|
41
41
|
make_generated_server_bundle_the_entrypoint: false,
|
|
42
|
-
defer_generated_component_packs: true
|
|
42
|
+
defer_generated_component_packs: true,
|
|
43
|
+
# forces the loading of React components
|
|
44
|
+
force_load: false
|
|
43
45
|
)
|
|
44
46
|
end
|
|
45
47
|
|
|
@@ -53,7 +55,8 @@ module ReactOnRails
|
|
|
53
55
|
:server_render_method, :random_dom_id, :auto_load_bundle,
|
|
54
56
|
:same_bundle_for_client_and_server, :rendering_props_extension,
|
|
55
57
|
:make_generated_server_bundle_the_entrypoint,
|
|
56
|
-
:defer_generated_component_packs
|
|
58
|
+
:defer_generated_component_packs,
|
|
59
|
+
:force_load
|
|
57
60
|
|
|
58
61
|
# rubocop:disable Metrics/AbcSize
|
|
59
62
|
def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
|
|
@@ -68,7 +71,7 @@ module ReactOnRails
|
|
|
68
71
|
same_bundle_for_client_and_server: nil,
|
|
69
72
|
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil,
|
|
70
73
|
random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil,
|
|
71
|
-
components_subdirectory: nil, auto_load_bundle: nil)
|
|
74
|
+
components_subdirectory: nil, auto_load_bundle: nil, force_load: nil)
|
|
72
75
|
self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
|
|
73
76
|
self.generated_assets_dirs = generated_assets_dirs
|
|
74
77
|
self.generated_assets_dir = generated_assets_dir
|
|
@@ -106,6 +109,7 @@ module ReactOnRails
|
|
|
106
109
|
self.auto_load_bundle = auto_load_bundle
|
|
107
110
|
self.make_generated_server_bundle_the_entrypoint = make_generated_server_bundle_the_entrypoint
|
|
108
111
|
self.defer_generated_component_packs = defer_generated_component_packs
|
|
112
|
+
self.force_load = force_load
|
|
109
113
|
end
|
|
110
114
|
# rubocop:enable Metrics/AbcSize
|
|
111
115
|
|
|
@@ -91,6 +91,64 @@ module ReactOnRails
|
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
+
# Streams a server-side rendered React component using React's `renderToPipeableStream`.
|
|
95
|
+
# Supports React 18 features like Suspense, concurrent rendering, and selective hydration.
|
|
96
|
+
# Enables progressive rendering and improved performance for large components.
|
|
97
|
+
#
|
|
98
|
+
# Note: This function can only be used with React on Rails Pro.
|
|
99
|
+
# The view that uses this function must be rendered using the
|
|
100
|
+
# `stream_view_containing_react_components` method from the React on Rails Pro gem.
|
|
101
|
+
#
|
|
102
|
+
# Example of an async React component that can benefit from streaming:
|
|
103
|
+
#
|
|
104
|
+
# const AsyncComponent = async () => {
|
|
105
|
+
# const data = await fetchData();
|
|
106
|
+
# return <div>{data}</div>;
|
|
107
|
+
# };
|
|
108
|
+
#
|
|
109
|
+
# function App() {
|
|
110
|
+
# return (
|
|
111
|
+
# <Suspense fallback={<div>Loading...</div>}>
|
|
112
|
+
# <AsyncComponent />
|
|
113
|
+
# </Suspense>
|
|
114
|
+
# );
|
|
115
|
+
# }
|
|
116
|
+
#
|
|
117
|
+
# @param [String] component_name Name of your registered component
|
|
118
|
+
# @param [Hash] options Options for rendering
|
|
119
|
+
# @option options [Hash] :props Props to pass to the react component
|
|
120
|
+
# @option options [String] :dom_id DOM ID of the component container
|
|
121
|
+
# @option options [Hash] :html_options Options passed to content_tag
|
|
122
|
+
# @option options [Boolean] :prerender Set to false to disable server-side rendering
|
|
123
|
+
# @option options [Boolean] :trace Set to true to add extra debugging information to the HTML
|
|
124
|
+
# @option options [Boolean] :raise_on_prerender_error Set to true to raise exceptions during server-side rendering
|
|
125
|
+
# Any other options are passed to the content tag, including the id.
|
|
126
|
+
def stream_react_component(component_name, options = {})
|
|
127
|
+
unless ReactOnRails::Utils.react_on_rails_pro?
|
|
128
|
+
raise ReactOnRails::Error,
|
|
129
|
+
"You must use React on Rails Pro to use the stream_react_component method."
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
if @rorp_rendering_fibers.nil?
|
|
133
|
+
raise ReactOnRails::Error,
|
|
134
|
+
"You must call stream_view_containing_react_components to render the view containing the react component"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
rendering_fiber = Fiber.new do
|
|
138
|
+
stream = internal_stream_react_component(component_name, options)
|
|
139
|
+
stream.each_chunk do |chunk|
|
|
140
|
+
Fiber.yield chunk
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
@rorp_rendering_fibers << rendering_fiber
|
|
145
|
+
|
|
146
|
+
# return the first chunk of the fiber
|
|
147
|
+
# It contains the initial html of the component
|
|
148
|
+
# all updates will be appended to the stream sent to browser
|
|
149
|
+
rendering_fiber.resume
|
|
150
|
+
end
|
|
151
|
+
|
|
94
152
|
# react_component_hash is used to return multiple HTML strings for server rendering, such as for
|
|
95
153
|
# adding meta-tags to a page.
|
|
96
154
|
# It is exactly like react_component except for the following:
|
|
@@ -330,6 +388,16 @@ module ReactOnRails
|
|
|
330
388
|
|
|
331
389
|
private
|
|
332
390
|
|
|
391
|
+
def internal_stream_react_component(component_name, options = {})
|
|
392
|
+
options = options.merge(stream?: true)
|
|
393
|
+
result = internal_react_component(component_name, options)
|
|
394
|
+
build_react_component_result_for_server_streamed_content(
|
|
395
|
+
rendered_html_stream: result[:result],
|
|
396
|
+
component_specification_tag: result[:tag],
|
|
397
|
+
render_options: result[:render_options]
|
|
398
|
+
)
|
|
399
|
+
end
|
|
400
|
+
|
|
333
401
|
def generated_components_pack_path(component_name)
|
|
334
402
|
"#{ReactOnRails::PackerUtils.packer_source_entry_path}/generated/#{component_name}.js"
|
|
335
403
|
end
|
|
@@ -361,6 +429,32 @@ module ReactOnRails
|
|
|
361
429
|
prepend_render_rails_context(result)
|
|
362
430
|
end
|
|
363
431
|
|
|
432
|
+
def build_react_component_result_for_server_streamed_content(
|
|
433
|
+
rendered_html_stream:,
|
|
434
|
+
component_specification_tag:,
|
|
435
|
+
render_options:
|
|
436
|
+
)
|
|
437
|
+
is_first_chunk = true
|
|
438
|
+
rendered_html_stream.transform do |chunk_json_result|
|
|
439
|
+
if is_first_chunk
|
|
440
|
+
is_first_chunk = false
|
|
441
|
+
build_react_component_result_for_server_rendered_string(
|
|
442
|
+
server_rendered_html: chunk_json_result["html"],
|
|
443
|
+
component_specification_tag: component_specification_tag,
|
|
444
|
+
console_script: chunk_json_result["consoleReplayScript"],
|
|
445
|
+
render_options: render_options
|
|
446
|
+
)
|
|
447
|
+
else
|
|
448
|
+
result_console_script = render_options.replay_console ? chunk_json_result["consoleReplayScript"] : ""
|
|
449
|
+
# No need to prepend component_specification_tag or add rails context again
|
|
450
|
+
# as they're already included in the first chunk
|
|
451
|
+
compose_react_component_html_with_spec_and_console(
|
|
452
|
+
"", chunk_json_result["html"], result_console_script
|
|
453
|
+
)
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
364
458
|
def build_react_component_result_for_server_rendered_hash(
|
|
365
459
|
server_rendered_html: required("server_rendered_html"),
|
|
366
460
|
component_specification_tag: required("component_specification_tag"),
|
|
@@ -397,27 +491,30 @@ module ReactOnRails
|
|
|
397
491
|
|
|
398
492
|
def compose_react_component_html_with_spec_and_console(component_specification_tag, rendered_output, console_script)
|
|
399
493
|
# IMPORTANT: Ensure that we mark string as html_safe to avoid escaping.
|
|
400
|
-
<<~HTML
|
|
494
|
+
html_content = <<~HTML
|
|
401
495
|
#{rendered_output}
|
|
402
496
|
#{component_specification_tag}
|
|
403
497
|
#{console_script}
|
|
404
498
|
HTML
|
|
499
|
+
html_content.strip.html_safe
|
|
405
500
|
end
|
|
406
501
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
return render_value if @rendered_rails_context
|
|
502
|
+
def rails_context_if_not_already_rendered
|
|
503
|
+
return "" if @rendered_rails_context
|
|
410
504
|
|
|
411
505
|
data = rails_context(server_side: false)
|
|
412
506
|
|
|
413
507
|
@rendered_rails_context = true
|
|
414
508
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
509
|
+
content_tag(:script,
|
|
510
|
+
json_safe_and_pretty(data).html_safe,
|
|
511
|
+
type: "application/json",
|
|
512
|
+
id: "js-react-on-rails-context")
|
|
513
|
+
end
|
|
419
514
|
|
|
420
|
-
|
|
515
|
+
# prepend the rails_context if not yet applied
|
|
516
|
+
def prepend_render_rails_context(render_value)
|
|
517
|
+
"#{rails_context_if_not_already_rendered}\n#{render_value}".strip.html_safe
|
|
421
518
|
end
|
|
422
519
|
|
|
423
520
|
def internal_react_component(react_component_name, options = {})
|
|
@@ -441,6 +538,14 @@ module ReactOnRails
|
|
|
441
538
|
"data-trace" => (render_options.trace ? true : nil),
|
|
442
539
|
"data-dom-id" => render_options.dom_id)
|
|
443
540
|
|
|
541
|
+
if render_options.force_load
|
|
542
|
+
component_specification_tag.concat(
|
|
543
|
+
content_tag(:script, %(
|
|
544
|
+
ReactOnRails.reactOnRailsComponentLoaded('#{render_options.dom_id}');
|
|
545
|
+
).html_safe)
|
|
546
|
+
)
|
|
547
|
+
end
|
|
548
|
+
|
|
444
549
|
load_pack_for_generated_component(react_component_name, render_options)
|
|
445
550
|
# Create the HTML rendering part
|
|
446
551
|
result = server_rendered_react_component(render_options)
|
|
@@ -465,6 +570,25 @@ module ReactOnRails
|
|
|
465
570
|
props.is_a?(String) ? props : props.to_json
|
|
466
571
|
end
|
|
467
572
|
|
|
573
|
+
def raise_prerender_error(json_result, react_component_name, props, js_code)
|
|
574
|
+
raise ReactOnRails::PrerenderError.new(
|
|
575
|
+
component_name: react_component_name,
|
|
576
|
+
props: sanitized_props_string(props),
|
|
577
|
+
err: nil,
|
|
578
|
+
js_code: js_code,
|
|
579
|
+
console_messages: json_result["consoleReplayScript"]
|
|
580
|
+
)
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
def should_raise_streaming_prerender_error?(chunk_json_result, render_options)
|
|
584
|
+
chunk_json_result["hasErrors"] &&
|
|
585
|
+
(if chunk_json_result["isShellReady"]
|
|
586
|
+
render_options.raise_non_shell_server_rendering_errors
|
|
587
|
+
else
|
|
588
|
+
render_options.raise_on_prerender_error
|
|
589
|
+
end)
|
|
590
|
+
end
|
|
591
|
+
|
|
468
592
|
# Returns object with values that are NOT html_safe!
|
|
469
593
|
def server_rendered_react_component(render_options)
|
|
470
594
|
return { "html" => "", "consoleReplayScript" => "" } unless render_options.prerender
|
|
@@ -512,16 +636,18 @@ module ReactOnRails
|
|
|
512
636
|
js_code: js_code)
|
|
513
637
|
end
|
|
514
638
|
|
|
515
|
-
if
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
639
|
+
if render_options.stream?
|
|
640
|
+
result.transform do |chunk_json_result|
|
|
641
|
+
if should_raise_streaming_prerender_error?(chunk_json_result, render_options)
|
|
642
|
+
raise_prerender_error(chunk_json_result, react_component_name, props, js_code)
|
|
643
|
+
end
|
|
644
|
+
# It doesn't make any transformation, it listens and raises error if a chunk has errors
|
|
645
|
+
chunk_json_result
|
|
646
|
+
end
|
|
647
|
+
elsif result["hasErrors"] && render_options.raise_on_prerender_error
|
|
648
|
+
raise_prerender_error(result, react_component_name, props, js_code)
|
|
524
649
|
end
|
|
650
|
+
|
|
525
651
|
result
|
|
526
652
|
end
|
|
527
653
|
|
|
@@ -87,10 +87,18 @@ module ReactOnRails
|
|
|
87
87
|
retrieve_configuration_value_for(:raise_on_prerender_error)
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
+
def raise_non_shell_server_rendering_errors
|
|
91
|
+
retrieve_react_on_rails_pro_config_value_for(:raise_non_shell_server_rendering_errors)
|
|
92
|
+
end
|
|
93
|
+
|
|
90
94
|
def logging_on_server
|
|
91
95
|
retrieve_configuration_value_for(:logging_on_server)
|
|
92
96
|
end
|
|
93
97
|
|
|
98
|
+
def force_load
|
|
99
|
+
retrieve_configuration_value_for(:force_load)
|
|
100
|
+
end
|
|
101
|
+
|
|
94
102
|
def to_s
|
|
95
103
|
"{ react_component_name = #{react_component_name}, options = #{options}, request_digest = #{request_digest}"
|
|
96
104
|
end
|
|
@@ -103,6 +111,10 @@ module ReactOnRails
|
|
|
103
111
|
options[key] = value
|
|
104
112
|
end
|
|
105
113
|
|
|
114
|
+
def stream?
|
|
115
|
+
options[:stream?]
|
|
116
|
+
end
|
|
117
|
+
|
|
106
118
|
private
|
|
107
119
|
|
|
108
120
|
attr_reader :options
|
|
@@ -120,6 +132,14 @@ module ReactOnRails
|
|
|
120
132
|
ReactOnRails.configuration.public_send(key)
|
|
121
133
|
end
|
|
122
134
|
end
|
|
135
|
+
|
|
136
|
+
def retrieve_react_on_rails_pro_config_value_for(key)
|
|
137
|
+
options.fetch(key) do
|
|
138
|
+
return nil unless ReactOnRails::Utils.react_on_rails_pro?
|
|
139
|
+
|
|
140
|
+
ReactOnRailsPro.configuration.public_send(key)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
123
143
|
end
|
|
124
144
|
end
|
|
125
145
|
end
|
|
@@ -46,7 +46,7 @@ module ReactOnRails
|
|
|
46
46
|
# Note, js_code does not have to be based on React.
|
|
47
47
|
# js_code MUST RETURN json stringify Object
|
|
48
48
|
# Calling code will probably call 'html_safe' on return value before rendering to the view.
|
|
49
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
49
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
50
50
|
def exec_server_render_js(js_code, render_options, js_evaluator = nil)
|
|
51
51
|
js_evaluator ||= self
|
|
52
52
|
if render_options.trace
|
|
@@ -56,7 +56,11 @@ module ReactOnRails
|
|
|
56
56
|
@file_index += 1
|
|
57
57
|
end
|
|
58
58
|
begin
|
|
59
|
-
|
|
59
|
+
result = if render_options.stream?
|
|
60
|
+
js_evaluator.eval_streaming_js(js_code, render_options)
|
|
61
|
+
else
|
|
62
|
+
js_evaluator.eval_js(js_code, render_options)
|
|
63
|
+
end
|
|
60
64
|
rescue StandardError => err
|
|
61
65
|
msg = <<~MSG
|
|
62
66
|
Error evaluating server bundle. Check your webpack configuration.
|
|
@@ -71,26 +75,14 @@ module ReactOnRails
|
|
|
71
75
|
end
|
|
72
76
|
raise ReactOnRails::Error, msg, err.backtrace
|
|
73
77
|
end
|
|
74
|
-
result = nil
|
|
75
|
-
begin
|
|
76
|
-
result = JSON.parse(json_string)
|
|
77
|
-
rescue JSON::ParserError => e
|
|
78
|
-
raise ReactOnRails::JsonParseError.new(parse_error: e, json: json_string)
|
|
79
|
-
end
|
|
80
78
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
console_script_lines&.each do |line|
|
|
87
|
-
match = re.match(line)
|
|
88
|
-
Rails.logger.info { "[react_on_rails] #{match[:msg]}" } if match
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
result
|
|
79
|
+
return parse_result_and_replay_console_messages(result, render_options) unless render_options.stream?
|
|
80
|
+
|
|
81
|
+
# Streamed component is returned as stream of strings.
|
|
82
|
+
# We need to parse each chunk and replay the console messages.
|
|
83
|
+
result.transform { |chunk| parse_result_and_replay_console_messages(chunk, render_options) }
|
|
92
84
|
end
|
|
93
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
85
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
94
86
|
|
|
95
87
|
def trace_js_code_used(msg, js_code, file_name = "tmp/server-generated.js", force: false)
|
|
96
88
|
return unless ReactOnRails.configuration.trace || force
|
|
@@ -233,6 +225,28 @@ module ReactOnRails
|
|
|
233
225
|
msg = "file_url_to_string #{url} failed\nError is: #{e}"
|
|
234
226
|
raise ReactOnRails::Error, msg
|
|
235
227
|
end
|
|
228
|
+
|
|
229
|
+
def parse_result_and_replay_console_messages(result_string, render_options)
|
|
230
|
+
result = nil
|
|
231
|
+
begin
|
|
232
|
+
result = JSON.parse(result_string)
|
|
233
|
+
rescue JSON::ParserError => e
|
|
234
|
+
raise ReactOnRails::JsonParseError.new(parse_error: e, json: result_string)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
if render_options.logging_on_server
|
|
238
|
+
console_script = result["consoleReplayScript"]
|
|
239
|
+
console_script_lines = console_script.split("\n")
|
|
240
|
+
# Regular expression to match console.log or console.error calls with SERVER prefix
|
|
241
|
+
re = /console\.(?:log|error)\.apply\(console, \["\[SERVER\] (?<msg>.*)"\]\);/
|
|
242
|
+
console_script_lines&.each do |line|
|
|
243
|
+
match = re.match(line)
|
|
244
|
+
# Log matched messages to Rails logger with react_on_rails prefix
|
|
245
|
+
Rails.logger.info { "[react_on_rails] #{match[:msg]}" } if match
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
result
|
|
249
|
+
end
|
|
236
250
|
end
|
|
237
251
|
# rubocop:enable Metrics/ClassLength
|
|
238
252
|
end
|
data/tsconfig.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:
|
|
4
|
+
version: 15.0.0.alpha.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: 2024-
|
|
11
|
+
date: 2024-11-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: addressable
|