react-rails 1.11.0 → 2.0.0

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.
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