Class: ReactOnRailsPro::ServerRenderingPool::NodeRenderingPool

Inherits:
Object
  • Object
show all
Defined in:
lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb

Overview

This implementation of the rendering pool uses NodeJS to execute javasript code

Constant Summary collapse

RENDERED_HTML_KEY =
"renderedHtml"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.bundle_hashObject (readonly)

Returns the value of attribute bundle_hash.



23
24
25
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 23

def bundle_hash
  @bundle_hash
end

Class Method Details

.eval_js(js_code, render_options, send_bundle: false) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 100

def eval_js(js_code, render_options, send_bundle: false)
  path = prepare_render_path(js_code, render_options)

  response = ReactOnRailsPro::Request.render_code(path, js_code, send_bundle)

  case response.status
  when 200
    response.body
  when ReactOnRailsPro::STATUS_SEND_BUNDLE
    # To prevent infinite loop
    ReactOnRailsPro::Error.raise_duplicate_bundle_upload_error if send_bundle

    eval_js(js_code, render_options, send_bundle: true)
  when ReactOnRailsPro::STATUS_BAD_REQUEST
    raise ReactOnRailsPro::Error,
          "Renderer rejected malformed request or hit an unhandled VM error: " \
          "#{response.status}:\n#{response.body}"
  else
    raise ReactOnRailsPro::Error,
          "Unexpected response code from renderer: #{response.status}:\n#{response.body}"
  end
rescue StandardError => e
  raise e unless ReactOnRailsPro.configuration.renderer_use_fallback_exec_js

  fallback_exec_js(js_code, render_options, e)
end

.eval_streaming_js(js_code, render_options) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 68

def eval_streaming_js(js_code, render_options)
  is_rsc_payload = ReactOnRailsPro.configuration.enable_rsc_support && render_options.rsc_payload_streaming?
  async_props_block = render_options.internal_option(:async_props_block)
  rsc_stream_observability = render_options.internal_option(:rsc_stream_observability) == true

  if async_props_block
    # Use incremental rendering when async props block is provided
    path = prepare_incremental_render_path(js_code, render_options)
    push_props = render_options.internal_option(:push_props)
    # Pull mode is enabled whenever push_props is set, including [] for pure pull.
    # nil means push-only mode with no bidirectional prop-request channel.
    pull_enabled = !push_props.nil?
    ReactOnRailsPro::Request.render_code_with_incremental_updates(
      path,
      js_code,
      async_props_block:,
      pull_enabled:,
      push_props:,
      rsc_stream_observability:
    )
  else
    # Use standard streaming when no async props block
    path = prepare_render_path(js_code, render_options)
    ReactOnRailsPro::Request.render_code_as_stream(
      path,
      js_code,
      is_rsc_payload:,
      rsc_stream_observability:
    )
  end
end

.exec_server_render_js(js_code, render_options) ⇒ Object

js_code: JavaScript expression that returns a string. Returns a Hash:

html: string of HTML for direct insertion on the page by evaluating js_code
consoleReplayScript: script for replaying console
hasErrors: true if server rendering errors

Note, js_code does not have to be based on React. js_code MUST RETURN json stringify Object Calling code will probably call 'html_safe' on return value before rendering to the view.



61
62
63
64
65
66
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 61

def exec_server_render_js(js_code, render_options)
  # The secret sauce is passing self as the 3rd param, the js_evaluator
  render_options.set_option(:throw_js_errors, ReactOnRailsPro.configuration.throw_js_errors)
  ReactOnRails::ServerRenderingPool::RubyEmbeddedJavaScript
    .exec_server_render_js(js_code, render_options, self)
end

.prepare_incremental_render_path(js_code, render_options) ⇒ Object



142
143
144
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 142

def prepare_incremental_render_path(js_code, render_options)
  build_render_path(js_code, render_options, "incremental-render")
end

.prepare_render_path(js_code, render_options) ⇒ Object



135
136
137
138
139
140
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 135

def prepare_render_path(js_code, render_options)
  # TODO: Remove the request_digest. See https://github.com/shakacode/react_on_rails_pro/issues/119
  # From the request path
  # path = "/bundles/#{@bundle_hash}/render"
  build_render_path(js_code, render_options, "render")
end

.renderer_bundle_file_nameObject



45
46
47
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 45

def renderer_bundle_file_name
  "#{ReactOnRailsPro::Utils.bundle_hash}.js"
end

.reset_poolObject



25
26
27
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 25

def reset_pool
  ReactOnRailsPro::Request.reset_connection
end

.reset_pool_if_server_bundle_was_modifiedObject



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 29

def reset_pool_if_server_bundle_was_modified
  # Resetting the pool for server bundle modifications is accomplished by changing the mtime
  # of the server bundle in the request to the remote rendering server.
  # In non-development mode, we don't need to re-read this value.
  if @server_bundle_hash.blank? || ReactOnRails.configuration.development_mode
    @server_bundle_hash = ReactOnRailsPro::Utils.bundle_hash
  end

  unless ReactOnRailsPro.configuration.enable_rsc_support &&
         (@rsc_bundle_hash.blank? || ReactOnRails.configuration.development_mode)
    return
  end

  @rsc_bundle_hash = ReactOnRailsPro::Utils.rsc_bundle_hash
end

.rsc_bundle_hashObject



131
132
133
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 131

def rsc_bundle_hash
  @rsc_bundle_hash ||= ReactOnRailsPro::Utils.rsc_bundle_hash
end

.rsc_renderer_bundle_file_nameObject



49
50
51
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 49

def rsc_renderer_bundle_file_name
  "#{ReactOnRailsPro::Utils.rsc_bundle_hash}.js"
end

.server_bundle_hashObject



127
128
129
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 127

def server_bundle_hash
  @server_bundle_hash ||= ReactOnRailsPro::Utils.bundle_hash
end