react-rails 1.9.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +345 -9
- data/README.md +137 -389
- data/lib/assets/javascripts/JSXTransformer.js +6 -6
- data/lib/assets/javascripts/react_ujs.js +1 -7
- data/lib/assets/react-source/development/react-server.js +423 -21528
- data/lib/assets/react-source/development/react.js +191 -21409
- data/lib/assets/react-source/production/react-server.js +2 -19
- data/lib/assets/react-source/production/react.js +2 -19
- data/lib/generators/react/component_generator.rb +203 -73
- data/lib/generators/react/install_generator.rb +98 -25
- data/lib/generators/templates/component.es6.jsx +9 -12
- data/lib/generators/templates/component.es6.tsx +24 -0
- data/lib/generators/templates/component.js.jsx +15 -18
- data/lib/generators/templates/component.js.jsx.coffee +5 -8
- data/lib/generators/templates/component.js.jsx.tsx +36 -0
- data/lib/generators/templates/react_server_rendering.rb +4 -0
- data/lib/generators/templates/server_rendering.js +6 -0
- data/lib/generators/templates/server_rendering_pack.js +5 -0
- data/lib/react/jsx/babel_transformer.rb +12 -6
- data/lib/react/jsx/jsx_transformer.rb +7 -6
- data/lib/react/jsx/processor.rb +3 -1
- data/lib/react/jsx/sprockets_strategy.rb +12 -6
- data/lib/react/jsx/template.rb +7 -6
- data/lib/react/jsx.rb +11 -7
- data/lib/react/rails/asset_variant.rb +7 -8
- data/lib/react/rails/component_mount.rb +48 -14
- data/lib/react/rails/controller_lifecycle.rb +36 -7
- data/lib/react/rails/controller_renderer.rb +13 -4
- data/lib/react/rails/railtie.rb +34 -29
- data/lib/react/rails/test_helper.rb +25 -0
- data/lib/react/rails/version.rb +4 -2
- data/lib/react/rails/view_helper.rb +3 -1
- data/lib/react/rails.rb +9 -7
- data/lib/react/server_rendering/{sprockets_renderer → bundle_renderer}/console_replay.js +1 -1
- data/lib/react/server_rendering/bundle_renderer/console_reset.js +3 -0
- data/lib/react/server_rendering/bundle_renderer/timeout_polyfill.js +26 -0
- data/lib/react/server_rendering/bundle_renderer.rb +117 -0
- data/lib/react/server_rendering/environment_container.rb +2 -0
- data/lib/react/server_rendering/exec_js_renderer.rb +43 -16
- data/lib/react/server_rendering/manifest_container.rb +5 -1
- data/lib/react/server_rendering/separate_server_bundle_container.rb +19 -0
- data/lib/react/server_rendering/yaml_manifest_container.rb +12 -4
- data/lib/react/server_rendering.rb +26 -12
- data/lib/react-rails.rb +12 -4
- data/lib/react.rb +8 -4
- metadata +106 -41
- data/lib/assets/javascripts/react_ujs_event_setup.js +0 -29
- data/lib/assets/javascripts/react_ujs_mount.js +0 -104
- data/lib/assets/javascripts/react_ujs_native.js +0 -18
- data/lib/assets/javascripts/react_ujs_pjax.js +0 -10
- data/lib/assets/javascripts/react_ujs_turbolinks.js +0 -9
- data/lib/assets/javascripts/react_ujs_turbolinks_classic.js +0 -10
- data/lib/assets/javascripts/react_ujs_turbolinks_classic_deprecated.js +0 -13
- data/lib/assets/react-source/development-with-addons/react-server.js +0 -24053
- data/lib/assets/react-source/development-with-addons/react.js +0 -23890
- data/lib/assets/react-source/production-with-addons/react-server.js +0 -19
- data/lib/assets/react-source/production-with-addons/react.js +0 -19
- data/lib/generators/react/ujs_generator.rb +0 -44
- data/lib/react/server_rendering/sprockets_renderer.rb +0 -79
- /data/lib/react/server_rendering/{sprockets_renderer → bundle_renderer}/console_polyfill.js +0 -0
@@ -1,21 +1,27 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "babel/transpiler"
|
2
4
|
module React
|
3
5
|
module JSX
|
4
6
|
# A {React::JSX}-compliant transformer which uses `Babel::Transpiler` to transform JSX.
|
5
7
|
class BabelTransformer
|
6
|
-
DEPRECATED_OPTIONS = [
|
7
|
-
DEFAULT_TRANSFORM_OPTIONS = { blacklist: [
|
8
|
+
DEPRECATED_OPTIONS = %i[harmony strip_types asset_path].freeze
|
9
|
+
DEFAULT_TRANSFORM_OPTIONS = { blacklist: ["spec.functionName", "validation.react", "strict"] }.freeze
|
8
10
|
def initialize(options)
|
9
11
|
if (options.keys & DEPRECATED_OPTIONS).any?
|
10
|
-
ActiveSupport::Deprecation.warn(
|
11
|
-
|
12
|
+
ActiveSupport::Deprecation.warn(
|
13
|
+
<<-MSG
|
14
|
+
Setting config.react.jsx_transform_options for :harmony, :strip_types, and :asset_path keys is now deprecated and has no effect with the default Babel Transformer.
|
15
|
+
Please use new Babel Transformer options :whitelist, :plugin instead.
|
16
|
+
MSG
|
17
|
+
)
|
12
18
|
end
|
13
19
|
|
14
20
|
@transform_options = DEFAULT_TRANSFORM_OPTIONS.merge(options)
|
15
21
|
end
|
16
22
|
|
17
23
|
def transform(code)
|
18
|
-
Babel::Transpiler.transform(code, @transform_options)[
|
24
|
+
Babel::Transpiler.transform(code, @transform_options)["code"]
|
19
25
|
end
|
20
26
|
end
|
21
27
|
end
|
@@ -1,31 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module JSX
|
3
5
|
# A {React::JSX}-compliant transformer which uses the deprecated `JSXTransformer.js` to transform JSX.
|
4
6
|
class JSXTransformer
|
5
|
-
DEFAULT_ASSET_PATH =
|
7
|
+
DEFAULT_ASSET_PATH = "JSXTransformer.js"
|
6
8
|
|
7
9
|
def initialize(options)
|
8
10
|
@transform_options = {
|
9
11
|
stripTypes: options.fetch(:strip_types, false),
|
10
|
-
harmony:
|
12
|
+
harmony: options.fetch(:harmony, false)
|
11
13
|
}
|
12
14
|
|
13
15
|
@asset_path = options.fetch(:asset_path, DEFAULT_ASSET_PATH)
|
14
16
|
|
15
17
|
# If execjs uses therubyracer, there is no 'global'. Make sure
|
16
18
|
# we have it so JSX script can work properly.
|
17
|
-
js_code =
|
19
|
+
js_code = "var global = global || this;#{jsx_transform_code}"
|
18
20
|
@context = ExecJS.compile(js_code)
|
19
21
|
end
|
20
22
|
|
21
|
-
|
22
23
|
def transform(code)
|
23
|
-
result = @context.call(
|
24
|
+
result = @context.call("JSXTransformer.transform", code, @transform_options)
|
24
25
|
result["code"]
|
25
26
|
end
|
26
27
|
|
27
28
|
# search for transformer file using sprockets - allows user to override
|
28
|
-
# this file in
|
29
|
+
# this file in their own application
|
29
30
|
def jsx_transform_code
|
30
31
|
::Rails.application.assets[@asset_path].to_s
|
31
32
|
end
|
data/lib/react/jsx/processor.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module JSX
|
3
5
|
# Depending on the Sprockets version,
|
@@ -17,13 +19,13 @@ module React
|
|
17
19
|
# @param [Symbol, Nil] A strategy name, or `nil` to detect a strategy
|
18
20
|
def attach_with_strategy(sprockets_env, strategy_or_nil)
|
19
21
|
strategy = strategy_or_nil || detect_strategy
|
20
|
-
|
22
|
+
public_send(strategy, sprockets_env)
|
21
23
|
end
|
22
24
|
|
23
25
|
# @return [Symbol] based on the environment, return a method name to call with the sprockets environment
|
24
26
|
def detect_strategy
|
25
27
|
sprockets_version = Gem::Version.new(Sprockets::VERSION)
|
26
|
-
if sprockets_version >= Gem::Version.new("4.
|
28
|
+
if sprockets_version >= Gem::Version.new("4.a")
|
27
29
|
:register_processors
|
28
30
|
elsif sprockets_version >= Gem::Version.new("3.0.0")
|
29
31
|
:register_engine_with_mime_type
|
@@ -37,16 +39,20 @@ module React
|
|
37
39
|
end
|
38
40
|
|
39
41
|
def register_engine_with_mime_type(sprockets_env)
|
40
|
-
sprockets_env.register_engine(".jsx", React::JSX::Processor, mime_type: "application/javascript",
|
42
|
+
sprockets_env.register_engine(".jsx", React::JSX::Processor, mime_type: "application/javascript",
|
43
|
+
silence_deprecation: true)
|
41
44
|
end
|
42
45
|
|
43
46
|
def register_processors(sprockets_env)
|
44
47
|
sprockets_env.register_mime_type("application/jsx", extensions: [".jsx", ".js.jsx", ".es.jsx", ".es6.jsx"])
|
45
48
|
sprockets_env.register_mime_type("application/jsx+coffee", extensions: [".jsx.coffee", ".js.jsx.coffee"])
|
46
49
|
sprockets_env.register_transformer("application/jsx", "application/javascript", React::JSX::Processor)
|
47
|
-
sprockets_env.register_transformer("application/jsx+coffee", "application/jsx",
|
48
|
-
|
49
|
-
sprockets_env.register_preprocessor("application/jsx
|
50
|
+
sprockets_env.register_transformer("application/jsx+coffee", "application/jsx",
|
51
|
+
Sprockets::CoffeeScriptProcessor)
|
52
|
+
sprockets_env.register_preprocessor("application/jsx",
|
53
|
+
Sprockets::DirectiveProcessor.new(comments: ["//", ["/*", "*/"]]))
|
54
|
+
sprockets_env.register_preprocessor("application/jsx+coffee",
|
55
|
+
Sprockets::DirectiveProcessor.new(comments: ["#", ["###", "###"]]))
|
50
56
|
end
|
51
57
|
end
|
52
58
|
end
|
data/lib/react/jsx/template.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tilt"
|
2
4
|
|
3
5
|
module React
|
4
6
|
module JSX
|
5
7
|
# Sprockets 2-compliant processor
|
6
8
|
class Template < Tilt::Template
|
7
|
-
self.default_mime_type =
|
9
|
+
self.default_mime_type = "application/javascript"
|
8
10
|
|
9
|
-
def prepare
|
10
|
-
end
|
11
|
+
def prepare; end
|
11
12
|
|
12
|
-
def evaluate(
|
13
|
-
@
|
13
|
+
def evaluate(_scope, _locals)
|
14
|
+
@evaluate ||= JSX.transform(data)
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
data/lib/react/jsx.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "execjs"
|
4
|
+
require "react/jsx/processor"
|
5
|
+
require "react/jsx/template"
|
6
|
+
require "react/jsx/jsx_transformer"
|
7
|
+
require "react/jsx/babel_transformer"
|
8
|
+
require "react/jsx/sprockets_strategy"
|
9
|
+
require "rails"
|
8
10
|
|
9
11
|
module React
|
10
12
|
module JSX
|
@@ -17,6 +19,8 @@ module React
|
|
17
19
|
# - #transform(code) => new code
|
18
20
|
self.transformer_class = DEFAULT_TRANSFORMER
|
19
21
|
|
22
|
+
# @param code [String] JSX code to transform into JavaScript
|
23
|
+
# @return [String] plain, browser-ready JavaScript code
|
20
24
|
def self.transform(code)
|
21
25
|
self.transformer ||= transformer_class.new(transform_options)
|
22
26
|
self.transformer.transform(code)
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module Rails
|
3
5
|
# This class accepts some options for which build you want, then exposes where you can find
|
4
6
|
# them. In general, these paths should be added to the sprockets environment.
|
5
7
|
class AssetVariant
|
6
|
-
GEM_ROOT = Pathname.new(
|
8
|
+
GEM_ROOT = Pathname.new("../../../../").expand_path(__FILE__)
|
7
9
|
# @return [String] "production" or "development"
|
8
10
|
attr_reader :react_build
|
9
11
|
|
@@ -15,14 +17,11 @@ module React
|
|
15
17
|
|
16
18
|
# @param [Hash] Options for the asset variant
|
17
19
|
# @option variant [Symbol] if `:production`, use the minified React.js build
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
@react_build = options[:variant] == :production ? 'production' : 'development'
|
22
|
-
options[:addons] && @react_build += '-with-addons'
|
20
|
+
def initialize(options = {})
|
21
|
+
@react_build = options[:variant] == :production ? "production" : "development"
|
23
22
|
|
24
|
-
@react_directory = GEM_ROOT.join(
|
25
|
-
@jsx_directory = GEM_ROOT.join(
|
23
|
+
@react_directory = GEM_ROOT.join("lib/assets/react-source/").join(@react_build).to_s
|
24
|
+
@jsx_directory = GEM_ROOT.join("lib/assets/javascripts/").to_s
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module Rails
|
3
5
|
# This is the default view helper implementation.
|
@@ -9,43 +11,75 @@ module React
|
|
9
11
|
include ActionView::Helpers::TagHelper
|
10
12
|
include ActionView::Helpers::TextHelper
|
11
13
|
attr_accessor :output_buffer
|
14
|
+
|
12
15
|
mattr_accessor :camelize_props_switch
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
def setup(env)
|
17
|
+
def initialize
|
18
|
+
@cache_ids = []
|
17
19
|
end
|
18
20
|
|
19
|
-
|
21
|
+
# {ControllerLifecycle} calls these hooks
|
22
|
+
# You can use them in custom helper implementations
|
23
|
+
def setup(controller)
|
24
|
+
@controller = controller
|
20
25
|
end
|
21
26
|
|
27
|
+
def teardown(controller); end
|
28
|
+
|
22
29
|
# Render a UJS-type HTML tag annotated with data attributes, which
|
23
30
|
# are used by react_ujs to actually instantiate the React component
|
24
31
|
# on the client.
|
25
32
|
def react_component(name, props = {}, options = {}, &block)
|
26
|
-
options = {:
|
27
|
-
if camelize_props_switch
|
28
|
-
props = React.camelize_props(props)
|
29
|
-
end
|
33
|
+
options = { tag: options } if options.is_a?(Symbol)
|
34
|
+
props = React.camelize_props(props) if options.fetch(:camelize_props, camelize_props_switch)
|
30
35
|
|
31
36
|
prerender_options = options[:prerender]
|
32
|
-
if prerender_options
|
33
|
-
|
34
|
-
|
37
|
+
block = proc { concat(prerender_component(name, props, prerender_options)) } if prerender_options
|
38
|
+
|
39
|
+
html_options = generate_html_options(name, options, props, prerender_options)
|
40
|
+
|
41
|
+
rendered_tag(html_options, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# If this controller has checked out a renderer, use that one.
|
47
|
+
# Otherwise, use {React::ServerRendering} directly (which will check one out for this rendering).
|
48
|
+
def prerender_component(component_name, props, prerender_options)
|
49
|
+
renderer = @controller.try(:react_rails_prerenderer) || React::ServerRendering
|
50
|
+
renderer.render(component_name, props, prerender_options)
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate_html_options(name, options, props, prerender_options)
|
54
|
+
html_options = options.reverse_merge(data: {})
|
35
55
|
|
36
|
-
html_options = options.reverse_merge(:data => {})
|
37
56
|
unless prerender_options == :static
|
38
57
|
html_options[:data].tap do |data|
|
39
58
|
data[:react_class] = name
|
40
59
|
data[:react_props] = (props.is_a?(String) ? props : props.to_json)
|
60
|
+
data[:hydrate] = "t" if prerender_options
|
61
|
+
|
62
|
+
num_components = @cache_ids.count { |c| c.start_with? name }
|
63
|
+
data[:react_cache_id] = "#{name}-#{num_components}"
|
41
64
|
end
|
42
65
|
end
|
66
|
+
|
67
|
+
html_options
|
68
|
+
end
|
69
|
+
|
70
|
+
def rendered_tag(html_options, &block)
|
43
71
|
html_tag = html_options[:tag] || :div
|
44
72
|
|
45
73
|
# remove internally used properties so they aren't rendered to DOM
|
46
|
-
html_options.except
|
74
|
+
html_option_to_use = html_options.except(:tag, :prerender, :camelize_props)
|
75
|
+
|
76
|
+
tag = content_tag(html_tag, "", html_option_to_use, &block)
|
77
|
+
return tag unless React::ServerRendering.renderer_options[:replay_console]
|
47
78
|
|
48
|
-
|
79
|
+
# Grab the server-rendered console replay script
|
80
|
+
# and move it _outside_ the container div
|
81
|
+
tag.sub!(%r{\n(<script class="react-rails-console-replay">.*</script>)</(\w+)>$}m, '</\2>\1')
|
82
|
+
tag.html_safe
|
49
83
|
end
|
50
84
|
end
|
51
85
|
end
|
@@ -1,25 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module Rails
|
5
|
+
# This module is included into ActionController so that
|
6
|
+
# per-request hooks can be called in the view helper.
|
3
7
|
module ControllerLifecycle
|
4
8
|
extend ActiveSupport::Concern
|
5
9
|
|
6
10
|
included do
|
7
11
|
# use both names to support Rails 3..5
|
8
|
-
|
9
|
-
|
10
|
-
public_send(before_action_with_fallback, :setup_react_component_helper)
|
11
|
-
public_send(after_action_with_fallback, :teardown_react_component_helper)
|
12
|
+
around_action_with_fallback = respond_to?(:around_action) ? :around_action : :around_filter
|
13
|
+
public_send(around_action_with_fallback, :use_react_component_helper)
|
12
14
|
attr_reader :__react_component_helper
|
13
15
|
end
|
14
16
|
|
15
|
-
|
17
|
+
module ClassMethods
|
18
|
+
# Call this in the controller to check out a prerender for the whole request.
|
19
|
+
# You can access the renderer with {#react_rails_prerenderer}.
|
20
|
+
def per_request_react_rails_prerenderer
|
21
|
+
around_action_with_fallback = respond_to?(:around_action) ? :around_action : :around_filter
|
22
|
+
public_send(around_action_with_fallback, :per_request_react_rails_prerenderer)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Instantiate the ViewHelper implementation and call its #setup method
|
27
|
+
# then let the controller action run,
|
28
|
+
# then call the ViewHelper implementation's #teardown method
|
29
|
+
def use_react_component_helper
|
16
30
|
new_helper = React::Rails::ViewHelper.helper_implementation_class.new
|
17
31
|
new_helper.setup(self)
|
18
32
|
@__react_component_helper = new_helper
|
33
|
+
yield
|
34
|
+
@__react_component_helper.teardown(self)
|
19
35
|
end
|
20
36
|
|
21
|
-
|
22
|
-
|
37
|
+
# If you want a per-request renderer, add this method as an around-action
|
38
|
+
#
|
39
|
+
# (`.per_request_react_rails_prerenderer` does this for you)
|
40
|
+
# @example Having one renderer instance for each controller action
|
41
|
+
# around_action :per_request_react_rails_prerenderer
|
42
|
+
def per_request_react_rails_prerenderer
|
43
|
+
React::ServerRendering.with_renderer do |renderer|
|
44
|
+
@__react_rails_prerenderer = renderer
|
45
|
+
yield
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# An instance of a server renderer, for use during this request
|
50
|
+
def react_rails_prerenderer
|
51
|
+
@__react_rails_prerenderer
|
23
52
|
end
|
24
53
|
end
|
25
54
|
end
|
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module Rails
|
3
5
|
# A renderer class suitable for `ActionController::Renderers`.
|
4
6
|
# It is associated to `:component` in the Railtie.
|
5
7
|
#
|
6
|
-
# It is prerendered with {React::ServerRendering}.
|
8
|
+
# It is prerendered by default with {React::ServerRendering}.
|
9
|
+
# Set options[:prerender] to `false` to disable prerendering.
|
7
10
|
#
|
8
11
|
# @example Rendering a component from a controller
|
9
12
|
# class TodosController < ApplicationController
|
@@ -19,17 +22,23 @@ module React
|
|
19
22
|
|
20
23
|
attr_accessor :output_buffer
|
21
24
|
|
22
|
-
def initialize(options={})
|
25
|
+
def initialize(options = {})
|
23
26
|
controller = options[:controller]
|
24
27
|
@__react_component_helper = controller.__react_component_helper
|
25
28
|
end
|
26
29
|
|
27
|
-
# @return [String]
|
30
|
+
# @return [String] HTML for `component_name` with `options[:props]`
|
28
31
|
def call(component_name, options, &block)
|
29
32
|
props = options.fetch(:props, {})
|
30
|
-
options = options.slice(:data, :aria, :tag, :class, :id
|
33
|
+
options = default_options.merge(options.slice(:data, :aria, :tag, :class, :id, :prerender, :camelize_props))
|
31
34
|
react_component(component_name, props, options, &block)
|
32
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def default_options
|
40
|
+
{ prerender: true }
|
41
|
+
end
|
33
42
|
end
|
34
43
|
end
|
35
44
|
end
|
data/lib/react/rails/railtie.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails"
|
2
4
|
|
3
5
|
module React
|
4
6
|
module Rails
|
@@ -6,7 +8,6 @@ module React
|
|
6
8
|
config.react = ActiveSupport::OrderedOptions.new
|
7
9
|
# Sensible defaults. Can be overridden in application.rb
|
8
10
|
config.react.variant = (::Rails.env.production? ? :production : :development)
|
9
|
-
config.react.addons = false
|
10
11
|
config.react.jsx_transform_options = {}
|
11
12
|
config.react.jsx_transformer_class = nil # defaults to BabelTransformer
|
12
13
|
config.react.camelize_props = false # pass in an underscored hash but get a camelized hash
|
@@ -15,19 +16,34 @@ module React
|
|
15
16
|
# Server rendering:
|
16
17
|
config.react.server_renderer_pool_size = 1 # increase if you're on JRuby
|
17
18
|
config.react.server_renderer_timeout = 20 # seconds
|
18
|
-
config.react.server_renderer = nil # defaults to
|
19
|
-
config.react.server_renderer_options = {} #
|
19
|
+
config.react.server_renderer = nil # defaults to BundleRenderer
|
20
|
+
config.react.server_renderer_options = {} # BundleRenderer provides defaults
|
21
|
+
# Changing files with these extensions in these directories will cause the server renderer to reload:
|
22
|
+
config.react.server_renderer_directories = ["/app/assets/javascripts/", "app/javascript"]
|
23
|
+
config.react.server_renderer_extensions = %w[jsx js]
|
20
24
|
# View helper implementation:
|
21
25
|
config.react.view_helper_implementation = nil # Defaults to ComponentMount
|
22
26
|
|
23
27
|
# Watch .jsx files for changes in dev, so we can reload the JS VMs with the new JS code.
|
24
|
-
initializer "react_rails.add_watchable_files", group: :all do |app|
|
25
|
-
|
28
|
+
initializer "react_rails.add_watchable_files", after: :load_config_initializers, group: :all do |app|
|
29
|
+
# Watch files ending in `server_renderer_extensions` in each of `server_renderer_directories`
|
30
|
+
reload_paths = config.react.server_renderer_directories.each_with_object({}) do |dir, memo|
|
31
|
+
app_dir = File.join(app.root, dir)
|
32
|
+
memo[app_dir] = config.react.server_renderer_extensions
|
33
|
+
end
|
34
|
+
|
35
|
+
# Rails checks these objects for changes:
|
36
|
+
react_reloader = app.config.file_watcher.new([], reload_paths) do
|
37
|
+
React::ServerRendering.reset_pool
|
38
|
+
end
|
39
|
+
app.reloaders << react_reloader
|
40
|
+
|
41
|
+
# Reload renderers in dev when files change
|
42
|
+
config.to_prepare { react_reloader.execute_if_updated }
|
26
43
|
end
|
27
44
|
|
28
45
|
# Include the react-rails view helper lazily
|
29
46
|
initializer "react_rails.setup_view_helpers", after: :load_config_initializers, group: :all do |app|
|
30
|
-
|
31
47
|
app.config.react.jsx_transformer_class ||= React::JSX::DEFAULT_TRANSFORMER
|
32
48
|
React::JSX.transformer_class = app.config.react.jsx_transformer_class
|
33
49
|
React::JSX.transform_options = app.config.react.jsx_transform_options
|
@@ -42,10 +58,11 @@ module React
|
|
42
58
|
|
43
59
|
ActiveSupport.on_load(:action_view) do
|
44
60
|
include ::React::Rails::ViewHelper
|
61
|
+
ActionDispatch::IntegrationTest.include React::Rails::TestHelper if ::Rails.env.test?
|
45
62
|
end
|
46
63
|
end
|
47
64
|
|
48
|
-
initializer "react_rails.add_component_renderer", group: :all do |
|
65
|
+
initializer "react_rails.add_component_renderer", group: :all do |_app|
|
49
66
|
ActionController::Renderers.add :component do |component_name, options|
|
50
67
|
renderer = ::React::Rails::ControllerRenderer.new(controller: self)
|
51
68
|
html = renderer.call(component_name, options)
|
@@ -56,22 +73,19 @@ module React
|
|
56
73
|
|
57
74
|
initializer "react_rails.bust_cache", after: :load_config_initializers, group: :all do |app|
|
58
75
|
asset_variant = React::Rails::AssetVariant.new({
|
59
|
-
|
60
|
-
|
61
|
-
})
|
76
|
+
variant: app.config.react.variant
|
77
|
+
})
|
62
78
|
|
63
79
|
sprockets_env = app.assets || app.config.try(:assets) # sprockets-rails 3.x attaches this at a different config
|
64
|
-
|
65
|
-
sprockets_env.version = [sprockets_env.version, "react-#{asset_variant.react_build}"
|
80
|
+
unless sprockets_env.nil?
|
81
|
+
sprockets_env.version = [sprockets_env.version, "react-#{asset_variant.react_build}"].compact.join("-")
|
66
82
|
end
|
67
|
-
|
68
83
|
end
|
69
84
|
|
70
85
|
initializer "react_rails.set_variant", after: :engines_blank_point, group: :all do |app|
|
71
86
|
asset_variant = React::Rails::AssetVariant.new({
|
72
|
-
|
73
|
-
|
74
|
-
})
|
87
|
+
variant: app.config.react.variant
|
88
|
+
})
|
75
89
|
|
76
90
|
if app.config.respond_to?(:assets)
|
77
91
|
app.config.assets.paths << asset_variant.react_directory
|
@@ -81,32 +95,23 @@ module React
|
|
81
95
|
|
82
96
|
config.after_initialize do |app|
|
83
97
|
# The class isn't accessible in the configure block, so assign it here if it wasn't overridden:
|
84
|
-
app.config.react.server_renderer ||= React::ServerRendering::
|
98
|
+
app.config.react.server_renderer ||= React::ServerRendering::BundleRenderer
|
85
99
|
|
86
100
|
React::ServerRendering.pool_size = app.config.react.server_renderer_pool_size
|
87
101
|
React::ServerRendering.pool_timeout = app.config.react.server_renderer_timeout
|
88
102
|
React::ServerRendering.renderer_options = app.config.react.server_renderer_options
|
89
103
|
React::ServerRendering.renderer = app.config.react.server_renderer
|
90
|
-
|
91
104
|
React::ServerRendering.reset_pool
|
92
|
-
# Reload renderers in dev when files change
|
93
|
-
if Gem::Version.new(::Rails::VERSION::STRING) >= Gem::Version.new("5.x")
|
94
|
-
ActiveSupport::Reloader.to_prepare { React::ServerRendering.reset_pool }
|
95
|
-
else
|
96
|
-
ActionDispatch::Reloader.to_prepare { React::ServerRendering.reset_pool }
|
97
|
-
end
|
98
105
|
end
|
99
106
|
|
100
|
-
initializer "react_rails.setup_engine", :
|
107
|
+
initializer "react_rails.setup_engine", group: :all do |app|
|
101
108
|
# Sprockets 3.x expects this in a different place
|
102
|
-
sprockets_env = app.assets || defined?(Sprockets) && Sprockets
|
109
|
+
sprockets_env = app.assets || (defined?(Sprockets) && Sprockets)
|
103
110
|
|
104
111
|
if app.config.react.sprockets_strategy == false
|
105
112
|
# pass, Sprockets opt-out
|
106
113
|
elsif sprockets_env.present?
|
107
114
|
React::JSX::SprocketsStrategy.attach_with_strategy(sprockets_env, app.config.react.sprockets_strategy)
|
108
|
-
else
|
109
|
-
# pass, Sprockets is not preset
|
110
115
|
end
|
111
116
|
end
|
112
117
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module React
|
4
|
+
module Rails
|
5
|
+
module TestHelper
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
# assert react_component render
|
9
|
+
#
|
10
|
+
# assert_react_component("HelloWorld") do |props|
|
11
|
+
# assert_equal "Hello world", props[:message]
|
12
|
+
# end
|
13
|
+
def assert_react_component(name)
|
14
|
+
assert_select "div[data-react-class=?]", name do |dom|
|
15
|
+
if block_given?
|
16
|
+
props = JSON.parse(dom.attr("data-react-props"))
|
17
|
+
props.deep_symbolize_keys!
|
18
|
+
|
19
|
+
yield(props)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/react/rails/version.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module Rails
|
3
5
|
# If you change this, make sure to update VERSIONS.md
|
4
|
-
#
|
5
|
-
VERSION = "
|
6
|
+
# and republish the UJS by updating package.json and `bundle exec rake ujs:publish`
|
7
|
+
VERSION = "3.2.1"
|
6
8
|
end
|
7
9
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module Rails
|
3
5
|
module ViewHelper
|
@@ -18,7 +20,7 @@ module React
|
|
18
20
|
# Otherwise, make a new instance.
|
19
21
|
def react_component(*args, &block)
|
20
22
|
helper_obj = @__react_component_helper ||= helper_implementation_class.new
|
21
|
-
helper_obj.react_component(*args
|
23
|
+
helper_obj.react_component(*args) { capture(&block) if block }
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
data/lib/react/rails.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "react/rails/asset_variant"
|
4
|
+
require "react/rails/railtie"
|
5
|
+
require "react/rails/controller_lifecycle"
|
6
|
+
require "react/rails/version"
|
7
|
+
require "react/rails/component_mount"
|
8
|
+
require "react/rails/view_helper"
|
9
|
+
require "react/rails/controller_renderer"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
(function (history) {
|
2
2
|
if (history && history.length > 0) {
|
3
|
-
result += '\n<scr'+'ipt>';
|
3
|
+
result += '\n<scr'+'ipt class="react-rails-console-replay">';
|
4
4
|
history.forEach(function (msg) {
|
5
5
|
result += '\nconsole.' + msg.level + '.apply(console, ' + JSON.stringify(msg.arguments) + ');';
|
6
6
|
});
|