Class: ReactOnRailsPro::ServerRenderingPool::NodeRenderingPool

Inherits:
Object
  • Object
show all
Includes:
ScoutApm::Tracer
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.



10
11
12
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 10

def bundle_hash
  @bundle_hash
end

Class Method Details

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



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 64

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 400
    raise ReactOnRailsPro::Error,
          "Renderer unhandled error at the VM level: #{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



55
56
57
58
59
60
61
62
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 55

def eval_streaming_js(js_code, render_options)
  path = prepare_render_path(js_code, render_options)
  ReactOnRailsPro::Request.render_code_as_stream(
    path,
    js_code,
    is_rsc_payload: ReactOnRailsPro.configuration.enable_rsc_support && render_options.rsc_payload_streaming?
  )
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.



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

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

.fallback_exec_js(js_code, render_options, error) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 111

def fallback_exec_js(js_code, render_options, error)
  Rails.logger.warn do
    "[ReactOnRailsPro] Falling back to ExecJS because of #{error}"
  end
  fallback_renderer = ReactOnRails::ServerRenderingPool::RubyEmbeddedJavaScript

  # Pool is actually discarded btw requests:
  # 1) not to keep ExecJS in memory once NodeRenderer is available back
  # 2) to avoid issues with server bundle changes
  fallback_renderer.reset_pool
  result = fallback_renderer.eval_js(js_code, render_options)
  fallback_renderer.instance_variable_set(:@js_context_pool, nil)
  result
end

.prepare_render_path(js_code, render_options) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 98

def prepare_render_path(js_code, render_options)
  ReactOnRailsPro::ServerRenderingPool::ProRendering
    .set_request_digest_on_render_options(js_code, render_options)

  rsc_support_enabled = ReactOnRailsPro.configuration.enable_rsc_support
  is_rendering_rsc_payload = rsc_support_enabled && render_options.rsc_payload_streaming?
  bundle_hash = is_rendering_rsc_payload ? rsc_bundle_hash : server_bundle_hash
  # 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"
  "/bundles/#{bundle_hash}/render/#{render_options.request_digest}"
end

.renderer_bundle_file_nameObject



32
33
34
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 32

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

.reset_poolObject



12
13
14
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 12

def reset_pool
  ReactOnRailsPro::Request.reset_connection
end

.reset_pool_if_server_bundle_was_modifiedObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 16

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



94
95
96
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 94

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

.rsc_renderer_bundle_file_nameObject



36
37
38
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 36

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

.server_bundle_hashObject



90
91
92
# File 'lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb', line 90

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