react-rails 1.11.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/README.md +294 -214
- data/lib/assets/javascripts/react_ujs.js +429 -7
- data/lib/generators/react/component_generator.rb +24 -12
- data/lib/generators/react/install_generator.rb +76 -18
- data/lib/generators/templates/react_server_rendering.rb +2 -0
- data/lib/generators/templates/server_rendering.js +6 -0
- data/lib/generators/templates/server_rendering_pack.js +5 -0
- data/lib/react/jsx.rb +2 -0
- data/lib/react/rails/component_mount.rb +23 -5
- data/lib/react/rails/controller_lifecycle.rb +35 -7
- data/lib/react/rails/railtie.rb +17 -11
- data/lib/react/rails/version.rb +1 -1
- data/lib/react/server_rendering.rb +16 -4
- data/lib/react/server_rendering/{sprockets_renderer.rb → bundle_renderer.rb} +40 -20
- data/lib/react/server_rendering/{sprockets_renderer → bundle_renderer}/console_polyfill.js +0 -0
- 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/{sprockets_renderer → bundle_renderer}/timeout_polyfill.js +0 -0
- data/lib/react/server_rendering/exec_js_renderer.rb +4 -1
- data/lib/react/server_rendering/webpacker_manifest_container.rb +34 -0
- data/lib/react/server_rendering/yaml_manifest_container.rb +1 -1
- metadata +16 -16
- 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/generators/react/ujs_generator.rb +0 -44
File without changes
|
@@ -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
|
});
|
File without changes
|
@@ -5,6 +5,9 @@ module React
|
|
5
5
|
# - No Rails dependency
|
6
6
|
# - No browser concerns
|
7
7
|
class ExecJSRenderer
|
8
|
+
# @return [ExecJS::Runtime::Context] The JS context for this renderer
|
9
|
+
attr_reader :context
|
10
|
+
|
8
11
|
def initialize(options={})
|
9
12
|
js_code = options[:code] || raise("Pass `code:` option to instantiate a JS context!")
|
10
13
|
@context = ExecJS.compile(GLOBAL_WRAPPER + js_code)
|
@@ -38,7 +41,7 @@ module React
|
|
38
41
|
|
39
42
|
def main_render(component_name, props, prerender_options)
|
40
43
|
render_function = prerender_options.fetch(:render_function, "renderToString")
|
41
|
-
"
|
44
|
+
"this.ReactRailsUJS.serverRender('#{render_function}', '#{component_name}', #{props})"
|
42
45
|
end
|
43
46
|
|
44
47
|
def compose_js(before, main, after)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "open-uri"
|
2
|
+
|
3
|
+
module React
|
4
|
+
module ServerRendering
|
5
|
+
# Get a compiled file from Webpacker. It may come from:
|
6
|
+
#
|
7
|
+
# - webpack-dev-server
|
8
|
+
# - compiled pack
|
9
|
+
class WebpackerManifestContainer
|
10
|
+
# This pattern matches the code that initializes the dev-server client.
|
11
|
+
CLIENT_REQUIRE = %r{__webpack_require__\(.*webpack-dev-server\/client\/index\.js.*\n}
|
12
|
+
|
13
|
+
def find_asset(logical_path)
|
14
|
+
# raises if not found
|
15
|
+
asset_path = Webpacker::Manifest.lookup(logical_path).to_s
|
16
|
+
if asset_path.start_with?("http")
|
17
|
+
# Get a file from the webpack-dev-server
|
18
|
+
dev_server_asset = open(asset_path).read
|
19
|
+
# Remove `webpack-dev-server/client/index.js` code which causes ExecJS to 💥
|
20
|
+
dev_server_asset.sub!(CLIENT_REQUIRE, '//\0')
|
21
|
+
dev_server_asset
|
22
|
+
else
|
23
|
+
# Read the already-compiled pack:
|
24
|
+
full_path = Webpacker::Manifest.lookup_path(logical_path).to_s
|
25
|
+
File.read(full_path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.compatible?
|
30
|
+
!!defined?(Webpacker)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module React
|
2
2
|
module ServerRendering
|
3
|
-
# Get asset content by reading the compiled file from disk using the generated
|
3
|
+
# Get asset content by reading the compiled file from disk using the generated manifest.yml file
|
4
4
|
#
|
5
5
|
# This is good for Rails production when assets are compiled to public/assets
|
6
6
|
# but sometimes, they're compiled to other directories (or other servers)
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: react-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul O’Shannessy
|
8
|
+
- Robert Mosolgo
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
12
|
+
date: 2017-04-13 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: appraisal
|
@@ -248,9 +249,11 @@ dependencies:
|
|
248
249
|
- - ">="
|
249
250
|
- !ruby/object:Gem::Version
|
250
251
|
version: 0.7.0
|
251
|
-
description:
|
252
|
+
description: Render components in views or controller actions. Server-side rendering
|
253
|
+
powered by ExecJS. Transform JSX in the asset pipeline or use Webpacker.
|
252
254
|
email:
|
253
255
|
- paul@oshannessy.com
|
256
|
+
- rmosolgo@gmail.com
|
254
257
|
executables: []
|
255
258
|
extensions: []
|
256
259
|
extra_rdoc_files: []
|
@@ -260,13 +263,6 @@ files:
|
|
260
263
|
- README.md
|
261
264
|
- lib/assets/javascripts/JSXTransformer.js
|
262
265
|
- lib/assets/javascripts/react_ujs.js
|
263
|
-
- lib/assets/javascripts/react_ujs_event_setup.js
|
264
|
-
- lib/assets/javascripts/react_ujs_mount.js
|
265
|
-
- lib/assets/javascripts/react_ujs_native.js
|
266
|
-
- lib/assets/javascripts/react_ujs_pjax.js
|
267
|
-
- lib/assets/javascripts/react_ujs_turbolinks.js
|
268
|
-
- lib/assets/javascripts/react_ujs_turbolinks_classic.js
|
269
|
-
- lib/assets/javascripts/react_ujs_turbolinks_classic_deprecated.js
|
270
266
|
- lib/assets/react-source/development-with-addons/react-server.js
|
271
267
|
- lib/assets/react-source/development-with-addons/react.js
|
272
268
|
- lib/assets/react-source/development/react-server.js
|
@@ -277,10 +273,12 @@ files:
|
|
277
273
|
- lib/assets/react-source/production/react.js
|
278
274
|
- lib/generators/react/component_generator.rb
|
279
275
|
- lib/generators/react/install_generator.rb
|
280
|
-
- lib/generators/react/ujs_generator.rb
|
281
276
|
- lib/generators/templates/component.es6.jsx
|
282
277
|
- lib/generators/templates/component.js.jsx
|
283
278
|
- lib/generators/templates/component.js.jsx.coffee
|
279
|
+
- lib/generators/templates/react_server_rendering.rb
|
280
|
+
- lib/generators/templates/server_rendering.js
|
281
|
+
- lib/generators/templates/server_rendering_pack.js
|
284
282
|
- lib/react-rails.rb
|
285
283
|
- lib/react.rb
|
286
284
|
- lib/react/jsx.rb
|
@@ -298,13 +296,15 @@ files:
|
|
298
296
|
- lib/react/rails/version.rb
|
299
297
|
- lib/react/rails/view_helper.rb
|
300
298
|
- lib/react/server_rendering.rb
|
299
|
+
- lib/react/server_rendering/bundle_renderer.rb
|
300
|
+
- lib/react/server_rendering/bundle_renderer/console_polyfill.js
|
301
|
+
- lib/react/server_rendering/bundle_renderer/console_replay.js
|
302
|
+
- lib/react/server_rendering/bundle_renderer/console_reset.js
|
303
|
+
- lib/react/server_rendering/bundle_renderer/timeout_polyfill.js
|
301
304
|
- lib/react/server_rendering/environment_container.rb
|
302
305
|
- lib/react/server_rendering/exec_js_renderer.rb
|
303
306
|
- lib/react/server_rendering/manifest_container.rb
|
304
|
-
- lib/react/server_rendering/
|
305
|
-
- lib/react/server_rendering/sprockets_renderer/console_polyfill.js
|
306
|
-
- lib/react/server_rendering/sprockets_renderer/console_replay.js
|
307
|
-
- lib/react/server_rendering/sprockets_renderer/timeout_polyfill.js
|
307
|
+
- lib/react/server_rendering/webpacker_manifest_container.rb
|
308
308
|
- lib/react/server_rendering/yaml_manifest_container.rb
|
309
309
|
homepage: https://github.com/reactjs/react-rails
|
310
310
|
licenses:
|
@@ -329,5 +329,5 @@ rubyforge_project:
|
|
329
329
|
rubygems_version: 2.5.1
|
330
330
|
signing_key:
|
331
331
|
specification_version: 4
|
332
|
-
summary: React
|
332
|
+
summary: React integration for Ruby on Rails
|
333
333
|
test_files: []
|
@@ -1,29 +0,0 @@
|
|
1
|
-
;(function(document, window) {
|
2
|
-
// jQuery is optional. Use it to support legacy browsers.
|
3
|
-
var $ = (typeof window.jQuery !== 'undefined') && window.jQuery;
|
4
|
-
if ($) {
|
5
|
-
ReactRailsUJS.handleEvent = function(eventName, callback) {
|
6
|
-
$(document).on(eventName, callback);
|
7
|
-
};
|
8
|
-
} else {
|
9
|
-
ReactRailsUJS.handleEvent = function(eventName, callback) {
|
10
|
-
document.addEventListener(eventName, callback);
|
11
|
-
};
|
12
|
-
}
|
13
|
-
// Detect which kind of events to set up:
|
14
|
-
if (typeof Turbolinks !== 'undefined' && Turbolinks.supported) {
|
15
|
-
if (typeof Turbolinks.EVENTS !== 'undefined') {
|
16
|
-
// Turbolinks.EVENTS is in classic version 2.4.0+
|
17
|
-
ReactRailsUJS.TurbolinksClassic.setup();
|
18
|
-
} else if (typeof Turbolinks.controller !== "undefined") {
|
19
|
-
// Turbolinks.controller is in version 5+
|
20
|
-
ReactRailsUJS.Turbolinks.setup();
|
21
|
-
} else {
|
22
|
-
ReactRailsUJS.TurbolinksClassicDeprecated.setup();
|
23
|
-
}
|
24
|
-
} else if ($ && typeof $.pjax === 'function') {
|
25
|
-
ReactRailsUJS.pjax.setup();
|
26
|
-
} else {
|
27
|
-
ReactRailsUJS.Native.setup();
|
28
|
-
}
|
29
|
-
})(document, window);
|
@@ -1,104 +0,0 @@
|
|
1
|
-
;(function(document, window) {
|
2
|
-
// jQuery is optional. Use it to support legacy browsers.
|
3
|
-
var $ = (typeof window.jQuery !== 'undefined') && window.jQuery;
|
4
|
-
|
5
|
-
window.ReactRailsUJS = {
|
6
|
-
// This attribute holds the name of component which should be mounted
|
7
|
-
// example: `data-react-class="MyApp.Items.EditForm"`
|
8
|
-
CLASS_NAME_ATTR: 'data-react-class',
|
9
|
-
|
10
|
-
// This attribute holds JSON stringified props for initializing the component
|
11
|
-
// example: `data-react-props="{\"item\": { \"id\": 1, \"name\": \"My Item\"} }"`
|
12
|
-
PROPS_ATTR: 'data-react-props',
|
13
|
-
|
14
|
-
// helper method for the mount and unmount methods to find the
|
15
|
-
// `data-react-class` DOM elements
|
16
|
-
findDOMNodes: function(searchSelector) {
|
17
|
-
// we will use fully qualified paths as we do not bind the callbacks
|
18
|
-
var selector, parent;
|
19
|
-
|
20
|
-
switch (typeof searchSelector) {
|
21
|
-
case 'undefined':
|
22
|
-
selector = '[' + window.ReactRailsUJS.CLASS_NAME_ATTR + ']';
|
23
|
-
parent = document;
|
24
|
-
break;
|
25
|
-
case 'object':
|
26
|
-
selector = '[' + window.ReactRailsUJS.CLASS_NAME_ATTR + ']';
|
27
|
-
parent = searchSelector;
|
28
|
-
break;
|
29
|
-
case 'string':
|
30
|
-
selector = searchSelector + '[' + window.ReactRailsUJS.CLASS_NAME_ATTR + '], ' +
|
31
|
-
searchSelector + ' [' + window.ReactRailsUJS.CLASS_NAME_ATTR + ']';
|
32
|
-
parent = document;
|
33
|
-
break
|
34
|
-
default:
|
35
|
-
break;
|
36
|
-
}
|
37
|
-
|
38
|
-
if ($) {
|
39
|
-
return $(selector, parent);
|
40
|
-
} else {
|
41
|
-
return parent.querySelectorAll(selector);
|
42
|
-
}
|
43
|
-
},
|
44
|
-
|
45
|
-
// Get the constructor for a className
|
46
|
-
getConstructor: function(className) {
|
47
|
-
// Assume className is simple and can be found at top-level (window).
|
48
|
-
// Fallback to eval to handle cases like 'My.React.ComponentName'.
|
49
|
-
// Also, try to gracefully import Babel 6 style default exports
|
50
|
-
//
|
51
|
-
var constructor;
|
52
|
-
|
53
|
-
// Try to access the class globally first
|
54
|
-
constructor = window[className];
|
55
|
-
|
56
|
-
// If that didn't work, try eval
|
57
|
-
if (!constructor) {
|
58
|
-
constructor = eval.call(window, className);
|
59
|
-
}
|
60
|
-
|
61
|
-
// Lastly, if there is a default attribute try that
|
62
|
-
if (constructor && constructor['default']) {
|
63
|
-
constructor = constructor['default'];
|
64
|
-
}
|
65
|
-
|
66
|
-
return constructor;
|
67
|
-
},
|
68
|
-
|
69
|
-
// Within `searchSelector`, find nodes which should have React components
|
70
|
-
// inside them, and mount them with their props.
|
71
|
-
mountComponents: function(searchSelector) {
|
72
|
-
var nodes = window.ReactRailsUJS.findDOMNodes(searchSelector);
|
73
|
-
|
74
|
-
for (var i = 0; i < nodes.length; ++i) {
|
75
|
-
var node = nodes[i];
|
76
|
-
var className = node.getAttribute(window.ReactRailsUJS.CLASS_NAME_ATTR);
|
77
|
-
var constructor = this.getConstructor(className);
|
78
|
-
var propsJson = node.getAttribute(window.ReactRailsUJS.PROPS_ATTR);
|
79
|
-
var props = propsJson && JSON.parse(propsJson);
|
80
|
-
|
81
|
-
if (typeof(constructor) === "undefined") {
|
82
|
-
var message = "Cannot find component: '" + className + "'"
|
83
|
-
if (console && console.log) { console.log("%c[react-rails] %c" + message + " for element", "font-weight: bold", "", node) }
|
84
|
-
var error = new Error(message + ". Make sure your component is globally available to render.")
|
85
|
-
throw error
|
86
|
-
} else {
|
87
|
-
ReactDOM.render(React.createElement(constructor, props), node);
|
88
|
-
}
|
89
|
-
}
|
90
|
-
},
|
91
|
-
|
92
|
-
// Within `searchSelector`, find nodes which have React components
|
93
|
-
// inside them, and unmount those components.
|
94
|
-
unmountComponents: function(searchSelector) {
|
95
|
-
var nodes = window.ReactRailsUJS.findDOMNodes(searchSelector);
|
96
|
-
|
97
|
-
for (var i = 0; i < nodes.length; ++i) {
|
98
|
-
var node = nodes[i];
|
99
|
-
|
100
|
-
ReactDOM.unmountComponentAtNode(node);
|
101
|
-
}
|
102
|
-
}
|
103
|
-
};
|
104
|
-
})(document, window);
|
@@ -1,18 +0,0 @@
|
|
1
|
-
;(function(document, window) {
|
2
|
-
// jQuery is optional. Use it to support legacy browsers.
|
3
|
-
var $ = (typeof window.jQuery !== 'undefined') && window.jQuery;
|
4
|
-
|
5
|
-
window.ReactRailsUJS.Native = {
|
6
|
-
// Attach handlers to browser events to mount & unmount components
|
7
|
-
setup: function() {
|
8
|
-
if ($) {
|
9
|
-
$(function() {window.ReactRailsUJS.mountComponents()});
|
10
|
-
} else if ('addEventListener' in window) {
|
11
|
-
document.addEventListener('DOMContentLoaded', function() {window.ReactRailsUJS.mountComponents()});
|
12
|
-
} else {
|
13
|
-
// add support to IE8 without jQuery
|
14
|
-
window.attachEvent('onload', function() {window.ReactRailsUJS.mountComponents()});
|
15
|
-
}
|
16
|
-
}
|
17
|
-
};
|
18
|
-
})(document, window);
|
@@ -1,10 +0,0 @@
|
|
1
|
-
;(function(document, window) {
|
2
|
-
window.ReactRailsUJS.pjax = {
|
3
|
-
// pjax support
|
4
|
-
setup: function() {
|
5
|
-
ReactRailsUJS.handleEvent('ready', function() {window.ReactRailsUJS.mountComponents()});
|
6
|
-
ReactRailsUJS.handleEvent('pjax:end', function(e) {window.ReactRailsUJS.mountComponents(e.target)});
|
7
|
-
ReactRailsUJS.handleEvent('pjax:beforeReplace', function(e) {window.ReactRailsUJS.unmountComponents(e.target)});
|
8
|
-
}
|
9
|
-
};
|
10
|
-
})(document, window);
|
@@ -1,9 +0,0 @@
|
|
1
|
-
;(function(document, window) {
|
2
|
-
window.ReactRailsUJS.Turbolinks = {
|
3
|
-
// Turbolinks 5+ got rid of named events (?!)
|
4
|
-
setup: function() {
|
5
|
-
ReactRailsUJS.handleEvent('turbolinks:load', function() {window.ReactRailsUJS.mountComponents()});
|
6
|
-
ReactRailsUJS.handleEvent('turbolinks:before-render', function() {window.ReactRailsUJS.unmountComponents()});
|
7
|
-
}
|
8
|
-
};
|
9
|
-
})(document, window);
|
@@ -1,10 +0,0 @@
|
|
1
|
-
;(function(document, window) {
|
2
|
-
window.ReactRailsUJS.TurbolinksClassic = {
|
3
|
-
// Attach handlers to Turbolinks-Classic events
|
4
|
-
// for mounting and unmounting components
|
5
|
-
setup: function() {
|
6
|
-
ReactRailsUJS.handleEvent(Turbolinks.EVENTS.CHANGE, function() {window.ReactRailsUJS.mountComponents()});
|
7
|
-
ReactRailsUJS.handleEvent(Turbolinks.EVENTS.BEFORE_UNLOAD, function() {window.ReactRailsUJS.unmountComponents()});
|
8
|
-
}
|
9
|
-
};
|
10
|
-
})(document, window);
|
@@ -1,13 +0,0 @@
|
|
1
|
-
;(function(document, window) {
|
2
|
-
window.ReactRailsUJS.TurbolinksClassicDeprecated = {
|
3
|
-
// Before Turbolinks 2.4.0, Turbolinks didn't
|
4
|
-
// have named events and didn't have a before-unload event.
|
5
|
-
// Also, it didn't work with the Turbolinks cache, see
|
6
|
-
// https://github.com/reactjs/react-rails/issues/87
|
7
|
-
setup: function() {
|
8
|
-
Turbolinks.pagesCached(0)
|
9
|
-
ReactRailsUJS.handleEvent('page:change', function() {window.ReactRailsUJS.mountComponents()});
|
10
|
-
ReactRailsUJS.handleEvent('page:receive', function() {window.ReactRailsUJS.unmountComponents()});
|
11
|
-
}
|
12
|
-
};
|
13
|
-
})(document, window);
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module React
|
2
|
-
module Generators
|
3
|
-
class UjsGenerator < ::Rails::Generators::Base
|
4
|
-
desc "Create a custom copy of react_ujs for your application"
|
5
|
-
|
6
|
-
class_option :output, required: true, desc: "File path for new react_ujs.js"
|
7
|
-
|
8
|
-
class_option :turbolinks, type: :boolean, default: true, desc: "Include Turbolinks 5 support?"
|
9
|
-
class_option :turbolinks_classic, type: :boolean, default: true, desc: "Include Turbolinks 2.4 / 3 support?"
|
10
|
-
class_option :turbolinks_classic_deprecated, type: :boolean, default: true, desc: "Include Turbolinks < 2.4 support?"
|
11
|
-
class_option :pjax, type: :boolean, default: true, desc: "Include PJAX support?"
|
12
|
-
class_option :native, type: :boolean, default: true, desc: "Include native events support?"
|
13
|
-
|
14
|
-
EVENT_SUPPORT_OPTIONS = [
|
15
|
-
:turbolinks,
|
16
|
-
:turbolinks_classic,
|
17
|
-
:turbolinks_classic_deprecated,
|
18
|
-
:pjax,
|
19
|
-
:native,
|
20
|
-
]
|
21
|
-
|
22
|
-
def create_ujs_file
|
23
|
-
files_to_merge = ["react_ujs_mount.js"]
|
24
|
-
|
25
|
-
EVENT_SUPPORT_OPTIONS.each do |event_support_option|
|
26
|
-
if options[event_support_option]
|
27
|
-
files_to_merge << "react_ujs_#{event_support_option}.js"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
files_to_merge << "react_ujs_event_setup.js"
|
32
|
-
|
33
|
-
asset_dir = File.expand_path("../../../assets/javascripts", __FILE__)
|
34
|
-
|
35
|
-
custom_ujs_content = files_to_merge
|
36
|
-
.map { |filename| File.read(File.join(asset_dir, filename)) }
|
37
|
-
.join("\n")
|
38
|
-
|
39
|
-
new_ujs_path = options[:output]
|
40
|
-
create_file(new_ujs_path, custom_ujs_content)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|