Skip to content

Instantly share code, notes, and snippets.

@johnthethird
Created February 2, 2014 19:01
Show Gist options
  • Save johnthethird/8773084 to your computer and use it in GitHub Desktop.
Save johnthethird/8773084 to your computer and use it in GitHub Desktop.
React Server-Side Rendering for Rails
require 'connection_pool'
class ReactRenderer
mattr_accessor :pool
def self.setup!
size = ::Rails.configuration.react.max_renderers || 10
timeout = ::Rails.configuration.react.renderer_timeout || 20 #seconds
@@pool ||= ConnectionPool.new(:size => size, :timeout => timeout) { ReactRenderer.new }
end
def self.render(component, args={})
@@pool.with do |renderer|
renderer.render(component, args)
end
end
def context
@context ||= begin
react_code = File.read(::React::Source.bundled_path_for("react-with-addons.min.js"))
components_code = ::Rails.application.assets['components.js'].to_s
all_code = <<-CODE
var global = global || this;
#{react_code};
React = global.React;
#{components_code};
CODE
ExecJS.compile(all_code)
end
end
def render(component, args={})
# This works because even though renderComponentToString uses a callback API it is really synchronous
jscode = <<-JS
function() {
var html = "";
React.renderComponentToString(#{component}(#{args.to_json}), function(s){html = s});
return html;
}()
JS
context.eval(jscode).html_safe
end
end
@ku1ik
Copy link

ku1ik commented Apr 4, 2014

@johnthethird Great job! Are you planning to submit your changes on "server-rendering" branch to upstream repo? That would be fantastic. I'd love to use this but until it's in the official repo I can't be sure about its long-term future. If you know what I mean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment