Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Params are:
* **prerender**: <true/false> set to false when debugging!
* **trace**: <true/false> set to true to print additional debugging information in the browser default is true for development, off otherwise
* **replay_console**: <true/false> Default is true. False will disable echoing server rendering logs, which can make troubleshooting server rendering difficult.
* Any other options are passed to the content tag, including the id.

## JavaScript

Expand Down Expand Up @@ -157,6 +158,7 @@ ReactOnRails.configure do |config|

# For server rendering. This can be set to false so that server side messages are discarded.
config.replay_console = true # Default is true. Be cautious about turning this off.
config.logging_on_server = true # Default is true. Logs server rendering messags to Rails.logger.info
end
```

Expand Down
33 changes: 25 additions & 8 deletions app/helpers/react_on_rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ module ReactOnRailsHelper
# trace: <true/false> set to true to print additional debugging information in the browser
# default is true for development, off otherwise
# replay_console: <true/false> Default is true. False will disable echoing server rendering
# logs, which can make troubleshooting server rendering difficult.
# logs to browser. While this can make troubleshooting server rendering difficult,
# so long as you have the default configuration of logging_on_server set to
# true, you'll still see the errors on the server.
# Any other options are passed to the content tag, including the id.
def react_component(component_name, props = {}, options = {})
# Create the JavaScript and HTML to allow either client or server rendering of the
# react_component.
Expand All @@ -41,16 +44,21 @@ def react_component(component_name, props = {}, options = {})
# We use this react_component_index in case we have the same component multiple times on the page.
react_component_index = next_react_component_index
react_component_name = component_name.camelize # Not sure if we should be doing this (JG)
dom_id = "#{component_name}-react-component-#{react_component_index}"
if options[:id].nil?
dom_id = "#{component_name}-react-component-#{react_component_index}"
else
dom_id = options[:id]
end

# Setup the page_loaded_js, which is the same regardless of prerendering or not!
# The reason is that React is smart about not doing extra work if the server rendering did its job.
data_variable_name = "__#{component_name.camelize(:lower)}Data#{react_component_index}__"
turbolinks_loaded = Object.const_defined?(:Turbolinks)
install_render_events = turbolinks_loaded ? turbolinks_bootstrap(dom_id) : non_turbolinks_bootstrap
props_string = props.is_a?(String) ? props : props.to_json
page_loaded_js = <<-JS
(function() {
window.#{data_variable_name} = #{props.to_json};
window.#{data_variable_name} = #{props_string};
#{define_render_if_dom_node_present(react_component_name, data_variable_name, dom_id,
trace(options), generator_function(options))}
#{install_render_events}
Expand All @@ -61,18 +69,23 @@ def react_component(component_name, props = {}, options = {})

# Create the HTML rendering part
server_rendered_html, console_script =
server_rendered_react_component_html(options, props, react_component_name,
server_rendered_react_component_html(options, props_string, react_component_name,
data_variable_name, dom_id)

content_tag_options = options.except(:generator_function, :prerender, :trace,
:replay_console, :id, :react_component_name,
:server_side)
content_tag_options[:id] = dom_id

rendered_output = content_tag(:div,
server_rendered_html,
id: dom_id)
content_tag_options)

# IMPORTANT: Ensure that we mark string as html_safe to avoid escaping.
<<-HTML.html_safe
#{data_from_server_script_tag}
#{rendered_output}
#{console_script}
#{replay_console(options) ? console_script : ""}
HTML
end

Expand All @@ -82,12 +95,12 @@ def next_react_component_index
end

# Returns Array [0]: html, [1]: script to console log
def server_rendered_react_component_html(options, props, react_component_name, data_variable, dom_id)
def server_rendered_react_component_html(options, props_string, react_component_name, data_variable, dom_id)
if prerender(options)
render_js_expression = <<-JS
(function(React) {
#{debug_js(react_component_name, data_variable, dom_id, trace(options))}
var reactElement = #{render_js_react_element(react_component_name, props.to_json, generator_function(options))}
var reactElement = #{render_js_react_element(react_component_name, props_string, generator_function(options))}
return React.renderToString(reactElement);
})(this.React);
JS
Expand Down Expand Up @@ -135,6 +148,10 @@ def prerender(options)
options.fetch(:prerender) { ReactOnRails.configuration.prerender }
end

def replay_console(options)
options.fetch(:replay_console) { ReactOnRails.configuration.replay_console }
end

def debug_js(react_component_name, data_variable, dom_id, trace)
if trace
"console.log(\"RENDERED #{react_component_name} with data_variable"\
Expand Down
9 changes: 6 additions & 3 deletions lib/react_on_rails/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@ def self.configuration
server_bundle_js_file: "app/assets/javascripts/generated/server.js",
prerender: false,
replay_console: true,
logging_on_server: true,
generator_function: false,
trace: Rails.env.development?
trace: Rails.env.development?,
)
end

class Configuration
attr_accessor :server_bundle_js_file, :prerender, :replay_console, :generator_function, :trace
attr_accessor :server_bundle_js_file, :prerender, :replay_console, :generator_function, :trace,
:logging_on_server

def initialize(server_bundle_js_file: nil, prerender: nil, replay_console: nil,
generator_function: nil, trace: nil)
generator_function: nil, trace: nil, logging_on_server: nil)
if File.exist?(server_bundle_js_file)
self.server_bundle_js_file = server_bundle_js_file
else
Expand All @@ -26,6 +28,7 @@ def initialize(server_bundle_js_file: nil, prerender: nil, replay_console: nil,

self.prerender = prerender
self.replay_console = replay_console
self.logging_on_server = logging_on_server
self.generator_function = generator_function
self.trace = trace.nil? ? Rails.env.development? : trace
end
Expand Down
17 changes: 15 additions & 2 deletions lib/react_on_rails/react_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,20 @@ def render_js(js_code, options = {})
json_string = ExecJS.eval(js_code_wrapper)
end
# element 0 is the html, element 1 is the script tag for the server console output
JSON.parse(json_string)
result = JSON.parse(json_string)
if ReactOnRails.configuration.logging_on_server
console_script = result[1]
console_script_lines = console_script.split("\n")
console_script_lines = console_script_lines[2..-2]
re = /console\.log\.apply\(console, \["\[SERVER\] (?<msg>.*)"\]\);/
console_script_lines.each do |line|
match = re.match(line)
if match
Rails.logger.info { "[react_on_rails] #{match[:msg]}"}
end
end
end
return result
end

def self.wrap_code_with_exception_handler(js_code, component_name)
Expand Down Expand Up @@ -134,7 +147,7 @@ def self.render_error_messages
end

def console_replay_js_code
@replay_console ? CONSOLE_REPLAY : ""
(@replay_console || ReactOnRails.configuration.logging_on_server) ? CONSOLE_REPLAY : ""
end

def base_js_code(bundle_js_code)
Expand Down
2 changes: 1 addition & 1 deletion spec/dummy/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ../..
specs:
react_on_rails (0.1.3)
react_on_rails (0.1.4)
execjs (~> 2.5)
rails (~> 4.2)

Expand Down
3 changes: 3 additions & 0 deletions spec/dummy/app/views/pages/_header.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
<li>
<%= link_to "Hello World Component Server Rendered", server_side_hello_world_path %>
</li>
<li>
<%= link_to "Hello World Component Server Rendered, with extra options", server_side_hello_world_with_options_path %>
</li>
<li>
<%= link_to "Hello World Component Server Rendered ES5", server_side_hello_world_es5_path %>
</li>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<%= render "header" %>

<%= react_component("HelloWorld",
@app_props_server_render.to_json,
prerender: true,
trace: true,
generator_function: false,
id: "my-hello-world-id",
class: "my-hello-world-class",
data: { x: 1, y: 2}
) %>
<hr/>

<h1>React Rails Server Rendering with options</h1>
<p>
This example demonstrates passing extram options to the example
<%= link_to "Hello World Component Server Rendered", server_side_hello_world_path %>
The differences include:
</p>
<ul>
<li>
Sending the props as already converted from JSON to a string.
</li>
<li>
Passing extra params that get passed to the tag shown in the HTML, including the option to set
the id of the component.
</li>
</ul>
<pre>
<%%= react_component("HelloWorld",
@app_props_server_render.to_json,
prerender: true,
trace: true,
generator_function: false,
id: "my-hello-world-id",
class: "my-hello-world-class",
data: { x: 1, y: 2} ) %>
</pre>
3 changes: 2 additions & 1 deletion spec/dummy/config/initializers/react_on_rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
config.trace = Rails.env.development? # default is true for development, off otherwise

# For server rendering. This can be set to false so that server side messages are discarded.
config.replay_console = true # Default is true. Be cautious about turning this off.
config.replay_console = false # Default is true. Be cautious about turning this off.
config.logging_on_server = true # Default is true. Logs server rendering messags to Rails.logger.info
end
1 change: 1 addition & 0 deletions spec/dummy/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
get "server_side_log_throw" => "pages#server_side_log_throw"
get "server_side_hello_world_es5" => "pages#server_side_hello_world_es5"
get "server_side_redux_app" => "pages#server_side_redux_app"
get "server_side_hello_world_with_options" => "pages#server_side_hello_world_with_options"
get "server_side_redux_app_cached" => "pages#server_side_redux_app_cached"
end