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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/README.md +294 -214
  4. data/lib/assets/javascripts/react_ujs.js +429 -7
  5. data/lib/generators/react/component_generator.rb +24 -12
  6. data/lib/generators/react/install_generator.rb +76 -18
  7. data/lib/generators/templates/react_server_rendering.rb +2 -0
  8. data/lib/generators/templates/server_rendering.js +6 -0
  9. data/lib/generators/templates/server_rendering_pack.js +5 -0
  10. data/lib/react/jsx.rb +2 -0
  11. data/lib/react/rails/component_mount.rb +23 -5
  12. data/lib/react/rails/controller_lifecycle.rb +35 -7
  13. data/lib/react/rails/railtie.rb +17 -11
  14. data/lib/react/rails/version.rb +1 -1
  15. data/lib/react/server_rendering.rb +16 -4
  16. data/lib/react/server_rendering/{sprockets_renderer.rb → bundle_renderer.rb} +40 -20
  17. data/lib/react/server_rendering/{sprockets_renderer → bundle_renderer}/console_polyfill.js +0 -0
  18. data/lib/react/server_rendering/{sprockets_renderer → bundle_renderer}/console_replay.js +1 -1
  19. data/lib/react/server_rendering/bundle_renderer/console_reset.js +3 -0
  20. data/lib/react/server_rendering/{sprockets_renderer → bundle_renderer}/timeout_polyfill.js +0 -0
  21. data/lib/react/server_rendering/exec_js_renderer.rb +4 -1
  22. data/lib/react/server_rendering/webpacker_manifest_container.rb +34 -0
  23. data/lib/react/server_rendering/yaml_manifest_container.rb +1 -1
  24. metadata +16 -16
  25. data/lib/assets/javascripts/react_ujs_event_setup.js +0 -29
  26. data/lib/assets/javascripts/react_ujs_mount.js +0 -104
  27. data/lib/assets/javascripts/react_ujs_native.js +0 -18
  28. data/lib/assets/javascripts/react_ujs_pjax.js +0 -10
  29. data/lib/assets/javascripts/react_ujs_turbolinks.js +0 -9
  30. data/lib/assets/javascripts/react_ujs_turbolinks_classic.js +0 -10
  31. data/lib/assets/javascripts/react_ujs_turbolinks_classic_deprecated.js +0 -13
  32. data/lib/generators/react/ujs_generator.rb +0 -44
@@ -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
  });
@@ -0,0 +1,3 @@
1
+ if (typeof console !== "undefined" && console.history) {
2
+ console.history = [];
3
+ }
@@ -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
- "ReactDOMServer.#{render_function}(React.createElement(#{component_name}, #{props}))"
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 maniftest.yml file
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: 1.11.0
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-04 00:00:00.000000000 Z
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: Compile your JSX on demand or precompile for production.
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/sprockets_renderer.rb
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/JSX adapter for the Ruby on Rails asset pipeline.
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