reactjs/react-rails

View on GitHub
lib/react/server_rendering.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

require "connection_pool"
require "react/server_rendering/exec_js_renderer"
require "react/server_rendering/bundle_renderer"

module React
  module ServerRendering
    mattr_accessor :renderer, :renderer_options,
                   :pool_size, :pool_timeout

    self.renderer_options = {}

    # Discard the old ConnectionPool & create a new one.
    # This will clear all state such as loaded code, JS VM state, or options.
    # @return [void]
    def self.reset_pool
      options = { size: pool_size, timeout: pool_timeout }
      @pool = ConnectionPool.new(options) { renderer.new(renderer_options) }
    end

    # Check a renderer out of the pool and use it to render the component.
    # @param component_name [String] Component identifier, looked up by UJS
    # @param props [String, Hash] Props for this component
    # @param prerender_options [Hash] Renderer-specific options
    # @return [String] Prerendered HTML from `component_name`
    def self.render(component_name, props, prerender_options)
      @pool.with do |renderer|
        renderer.render(component_name, props, prerender_options)
      end
    end

    # Yield a renderer for an arbitrary block
    def self.with_renderer(&block)
      @pool.with(&block)
    end

    # Raised when something went wrong during server rendering.
    class PrerenderError < RuntimeError
      def initialize(component_name, props, js_message)
        message = ["Encountered error \"#{js_message.inspect}\" when prerendering #{component_name} with #{props}",
                   js_message.backtrace.join("\n")].join("\n")
        super(message)
      end
    end
  end
end