react_on_rails 6.0.5 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc +2 -3
  3. data/.gitignore +1 -1
  4. data/.travis.yml +15 -13
  5. data/CHANGELOG.md +27 -15
  6. data/{docs/contributor-info/contributing.md → CONTRIBUTING.md} +24 -1
  7. data/Gemfile +1 -1
  8. data/KUDOS.md +3 -0
  9. data/NEWS.md +3 -0
  10. data/PROJECTS.md +1 -1
  11. data/README.md +143 -202
  12. data/app/helpers/react_on_rails_helper.rb +29 -17
  13. data/docs/additional-reading/node-server-rendering.md +127 -7
  14. data/docs/additional-reading/rails-assets.md +74 -10
  15. data/docs/additional-reading/react-router.md +1 -1
  16. data/docs/additional-reading/server-rendering-tips.md +3 -0
  17. data/docs/api/javascript-api.md +23 -0
  18. data/docs/contributor-info/releasing.md +1 -1
  19. data/docs/misc/doctrine.md +6 -6
  20. data/docs/tutorial.md +74 -93
  21. data/lib/generators/USAGE +5 -1
  22. data/lib/generators/react_on_rails/base_generator.rb +2 -2
  23. data/lib/generators/react_on_rails/install_generator.rb +8 -0
  24. data/lib/generators/react_on_rails/node_generator.rb +22 -0
  25. data/lib/generators/react_on_rails/templates/base/base/client/REACT_ON_RAILS_CLIENT_README.md +1 -1
  26. data/lib/generators/react_on_rails/templates/base/base/client/webpack.config.js +3 -2
  27. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt +7 -3
  28. data/lib/generators/react_on_rails/templates/node/base/client/node/package.json +10 -0
  29. data/lib/generators/react_on_rails/templates/node/base/client/node/server.js +87 -0
  30. data/lib/react_on_rails/assets_precompile.rb +112 -0
  31. data/lib/react_on_rails/configuration.rb +1 -1
  32. data/lib/react_on_rails/server_rendering_pool.rb +1 -0
  33. data/lib/react_on_rails/test_helper/ensure_assets_compiled.rb +1 -1
  34. data/lib/react_on_rails/utils.rb +1 -0
  35. data/lib/react_on_rails/version.rb +1 -1
  36. data/lib/react_on_rails/version_checker.rb +3 -2
  37. data/lib/tasks/assets.rake +10 -73
  38. data/package.json +9 -7
  39. metadata +7 -5
  40. data/Dockerfile_tests +0 -12
  41. data/docker-compose.yml +0 -11
@@ -341,29 +341,41 @@ ReactOnRails.setStore('#{store_name}', store);
341
341
 
342
342
  # This is the definitive list of the default values used for the rails_context, which is the
343
343
  # second parameter passed to both component and store generator functions.
344
+ # rubocop:disable Metrics/AbcSize
344
345
  def rails_context(server_side:)
345
346
  @rails_context ||= begin
346
- # Using Addressable instead of standard URI to better deal with
347
- # non-ASCII characters (see https://github.com/shakacode/react_on_rails/pull/405)
348
- uri = Addressable::URI.parse(request.original_url)
349
- # uri = Addressable::URI.parse("http://foo.com:3000/posts?id=30&limit=5#time=1305298413")
350
-
351
347
  result = {
352
- # URL settings
353
- href: request.original_url,
354
- location: "#{uri.path}#{uri.query.present? ? "?#{uri.query}" : ''}",
355
- scheme: uri.scheme, # http
356
- host: uri.host, # foo.com
357
- port: uri.port,
358
- pathname: uri.path, # /posts
359
- search: uri.query, # id=30&limit=5
360
-
348
+ inMailer: controller.present? && controller.is_a?(ActionMailer::Base),
361
349
  # Locale settings
362
350
  i18nLocale: I18n.locale,
363
- i18nDefaultLocale: I18n.default_locale,
364
- httpAcceptLanguage: request.env["HTTP_ACCEPT_LANGUAGE"]
351
+ i18nDefaultLocale: I18n.default_locale
365
352
  }
366
-
353
+ if request.present?
354
+ # Check for encoding of the request's original_url and try to force-encoding the
355
+ # URLs as UTF-8. This situation can occur in browsers that do not encode the
356
+ # entire URL as UTF-8 already, mostly on the Windows platform (IE11 and lower).
357
+ original_url_normalized = request.original_url
358
+ if original_url_normalized.encoding.to_s == "ASCII-8BIT"
359
+ original_url_normalized = original_url_normalized.force_encoding("ISO-8859-1").encode("UTF-8")
360
+ end
361
+
362
+ # Using Addressable instead of standard URI to better deal with
363
+ # non-ASCII characters (see https://github.com/shakacode/react_on_rails/pull/405)
364
+ uri = Addressable::URI.parse(original_url_normalized)
365
+ # uri = Addressable::URI.parse("http://foo.com:3000/posts?id=30&limit=5#time=1305298413")
366
+
367
+ result.merge!(
368
+ # URL settings
369
+ href: uri.to_s,
370
+ location: "#{uri.path}#{uri.query.present? ? "?#{uri.query}" : ''}",
371
+ scheme: uri.scheme, # http
372
+ host: uri.host, # foo.com
373
+ port: uri.port,
374
+ pathname: uri.path, # /posts
375
+ search: uri.query, # id=30&limit=5
376
+ httpAcceptLanguage: request.env["HTTP_ACCEPT_LANGUAGE"]
377
+ )
378
+ end
367
379
  if ReactOnRails.configuration.rendering_extension
368
380
  custom_context = ReactOnRails.configuration.rendering_extension.custom_context(self)
369
381
  result.merge!(custom_context) if custom_context
@@ -1,18 +1,32 @@
1
- ## Node Server Rendering
1
+ # Node.js for Server Rendering
2
2
 
3
- ### Warning: this is an experimental feature
3
+ Node.js can be used as the backend for server-side rendering instead of [execJS](https://github.com/rails/execjs). Before you try this, consider the tradeoff of extra complexity with your deployments versus *potential* performance gains. We've found that using ExecJS with [mini_racer](https://github.com/discourse/mini_racer) to be "fast enough" so far. That being said, we've heard of other large websites using Node.js for better server rendering performance.
4
4
 
5
- The default server rendering exploits ExecJS to render react components.
6
- Node server rendering allows you to use separate NodeJS process as a renderer. The process loads your configured server_bundle_js file and
7
- then executes javascript to render the component inside its environment. The communication between rails and node occurs
8
- via socket (`client/node/node.sock`)
5
+ If you're serious about this comparing Node.js versus execJS/mini_racer, then [get in touch](mailto:justin@shakacode.com)! We can definitely collaborate with you on refining this solution. However, please try out these instructions first.
6
+
7
+ ## Setup of React on Rails with Node.js Server Rendering
8
+ **Warning: this is an experimental feature.**
9
+
10
+ * Every time the webpack bundle changes, you have to restart the server yourself.
11
+
12
+ To do this you need to add a few files and then configure react_on_rails to use NodeJS. Here are the relevant files to add.
13
+
14
+ Node server rendering allows you to use separate NodeJS process as a renderer. The process loads your configured server_bundle_js file and then executes javascript to render the component inside its environment. The communication between rails and node occurs
15
+ via a socket (`client/node/node.sock`)
9
16
 
10
17
  ### Getting started
11
18
 
19
+ ### Configuration
20
+
21
+ #### Update the React on Rails Initializer
22
+
12
23
  To use node process just set `server_render_method = "NodeJS"` in `config/initializers/react_on_rails.rb`. To change back
13
24
  to ExecJS set `server_render_method = "ExecJS"`
14
25
 
15
- ### Configuration
26
+ ```ruby
27
+ # app/config/initializers/react_on_rails.rb
28
+ config.server_render_method = "NodeJS"
29
+ ```
16
30
 
17
31
  You need to configure the name of the server bundle in two places:
18
32
 
@@ -26,3 +40,109 @@ You need to configure the name of the server bundle in two places:
26
40
  # not affect performance.
27
41
  config.server_bundle_js_file = "webpack-bundle.js"
28
42
  ```
43
+
44
+ And in `client/node/package.json`
45
+
46
+ ```javascript
47
+ // client/node/package.json
48
+ {
49
+ "name": "react_on_rails_node",
50
+ "version": "0.0.0",
51
+ "private": true,
52
+ "scripts": {
53
+ "start": "node ./server.js -s webpack-bundle.js"
54
+ },
55
+ "dependencies": {
56
+ }
57
+ }
58
+ ```
59
+
60
+ And you'll need this file: `client/node/server.js`
61
+
62
+ ```javascript
63
+ // client/node/server.js
64
+ var net = require('net');
65
+ var fs = require('fs');
66
+
67
+ var bundlePath = '../../app/assets/webpack/';
68
+ var bundleFileName = 'webpack-bundle.js';
69
+
70
+ var currentArg;
71
+
72
+ function Handler() {
73
+ this.queue = [];
74
+ this.initialized = false;
75
+ }
76
+
77
+ Handler.prototype.handle = function (connection) {
78
+ var callback = function () {
79
+ connection.setEncoding('utf8');
80
+ connection.on('data', (data)=> {
81
+ console.log('Processing request: ' + data);
82
+ var result = eval(data);
83
+ connection.write(result);
84
+ });
85
+ };
86
+
87
+ if (this.initialized) {
88
+ callback();
89
+ } else {
90
+ this.queue.push(callback);
91
+ }
92
+ };
93
+
94
+ Handler.prototype.initialize = function () {
95
+ console.log('Processing ' + this.queue.length + ' pending requests');
96
+ var callback;
97
+ while (callback = this.queue.pop()) {
98
+ callback();
99
+ }
100
+
101
+ this.initialized = true;
102
+ };
103
+
104
+ var handler = new Handler();
105
+
106
+ process.argv.forEach((val) => {
107
+ if (val[0] == '-') {
108
+ currentArg = val.slice(1);
109
+ return;
110
+ }
111
+
112
+ if (currentArg == 's') {
113
+ bundleFileName = val;
114
+ }
115
+ });
116
+
117
+ try {
118
+ fs.mkdirSync(bundlePath);
119
+ } catch (e) {
120
+ if (e.code != 'EEXIST') throw e;
121
+ }
122
+
123
+ fs.watchFile(bundlePath + bundleFileName, (curr) => {
124
+ if (curr && curr.blocks && curr.blocks > 0) {
125
+ if (handler.initialized) {
126
+ console.log('Reloading server bundle must be implemented by restarting the node process!');
127
+ return;
128
+ }
129
+
130
+ require(bundlePath + bundleFileName);
131
+ console.log('Loaded server bundle: ' + bundlePath + bundleFileName);
132
+ handler.initialize();
133
+ }
134
+ });
135
+
136
+ var unixServer = net.createServer(function (connection) {
137
+ handler.handle(connection);
138
+ });
139
+
140
+ unixServer.listen('node.sock');
141
+
142
+ process.on('SIGINT', () => {
143
+ unixServer.close();
144
+ process.exit();
145
+ });
146
+
147
+ ```
148
+
@@ -1,19 +1,83 @@
1
- ## Rails assets
1
+ # Rails assets and the Extract Text Plugin
2
2
 
3
- ### Problem
4
- When client js uses images in render methods, e.g. `<img src='...' />` or in css, e.g. `background-image: url(...)`
5
- these assets fail to load. This happens because rails adds digest hashes to filenames
6
- when compiling assets, e.g. `img1.jpg` becomes `img1-dbu097452jf2v2.jpg`.
3
+ The [Webpack file loader](https://github.com/webpack/file-loader) copies referenced files to
4
+ the destination output directory, with an MD5 hash. The other term for this is a "digest".
5
+
6
+ > By default the filename of the resulting file is the MD5 hash of the file's contents with
7
+ the original extension of the required resource.
8
+
9
+ The most common use cases for Webpack processed files are images used for backgrounds in
10
+ CSS and fonts for CSS. However, this applies to any file that might be processed using the
11
+ Webpack file loader.
12
+
13
+ ## The Problem
14
+ To understand the problem, it helps to read this article:
15
+ [What is fingerprinting and why should I care](http://guides.rubyonrails.org/asset_pipeline.html#what-is-fingerprinting-and-why-should-i-care-questionmark)
16
+ Basically, when Rails prepares assets for production deployments, it also adds a digest
17
+ to the file names. E.g., `img1.jpg` becomes `img1-dbu097452jf2v2.jpg`.
7
18
 
8
19
  When compiling its native css Rails transforms all urls and links to digested
9
20
  versions, i.e. `background-image: image-url(img1.jpg)` becomes
10
21
  `background-image: url(img1-dbu097452jf2v2.jpg)`. However this doesn't happen for js and
11
22
  css files compiled by webpack on the client side, because they don't use
12
- `image-url` and `asset-url` and therefore assets fail to load.
23
+ `image-url` and `asset-url`. Without some fix, these assets would fail to load.
13
24
 
14
- ### Solution
25
+ When Webpack's client JavaScript uses images in render methods, e.g. `<img src='...' />` or
26
+ in css, e.g. `background-image: url(...)` The code (such as the CSS) generated by the Webpack
27
+ will have the Webpack digested name (MD5 hash). Since the Webpack generated CSS expects
28
+ just one level of "digesting", this "double-digesting" from Rails will cause such these assets
29
+ fail to load.
15
30
 
16
- React on Rails creates symlinks of non-digested versions to digested versions when doing a Rails assets compile.
17
- The solution is implemented using `assets:precompile` after-hook. The assets for symlinking
18
- are defined by `config.symlink_non_digested_assets_regex` in `config/initializers/react_on_rails.rb`.
31
+ ## The Solution: Symlink Original File Names to New File Names
32
+ React on Rails creates symlinks of non-digested versions (original webpack digested file names)
33
+ to the Rails deployed digested versions when doing a Rails assets compile. The solution is
34
+ implemented using `assets:precompile` after-hook in
35
+ file [lib/tasks/assets.rake](../../lib/tasks/assets.rake)
36
+ The assets for symlinking are defined by `config.symlink_non_digested_assets_regex` in
37
+ `config/initializers/react_on_rails.rb`.
38
+
39
+ ## Disabling the Symlinking
19
40
  To disable symlinks set this parameter to `nil`.
41
+
42
+
43
+ ## Example from /spec/dummy
44
+
45
+ If you run
46
+
47
+ ```
48
+ cd spec/dummy
49
+ RAILS_ENV=production bundle exec rake assets:precompile
50
+ rails s -e production
51
+ ```
52
+
53
+ You will see this. This shows how the file names output by rails. Note the original names after
54
+ being processed by Webpack are just MD5's.
55
+
56
+ ```
57
+ I, [2016-07-17T23:46:56.301981 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/server-bundle-42935dea382802a27e91b7df444a2813f74b4e6a0fce5606d863aaa10c0623d7.js
58
+ I, [2016-07-17T23:46:56.305649 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/server-bundle-42935dea382802a27e91b7df444a2813f74b4e6a0fce5606d863aaa10c0623d7.js.gz
59
+ I, [2016-07-17T23:46:56.370390 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/application_static-dfa728160c3cdebc633c2f6fb3823411530b307044f4dfe460790eef00b4e421.js
60
+ I, [2016-07-17T23:46:56.370566 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/application_static-dfa728160c3cdebc633c2f6fb3823411530b307044f4dfe460790eef00b4e421.js.gz
61
+ I, [2016-07-17T23:46:56.372895 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/application_static-17ed778d5061d4797556632b7bfbf405e067d9e7f140060a7f56a09788251f16.css
62
+ I, [2016-07-17T23:46:56.373012 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/application_static-17ed778d5061d4797556632b7bfbf405e067d9e7f140060a7f56a09788251f16.css.gz
63
+ I, [2016-07-17T23:46:56.374531 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/2ac2dd94f9b7e54292f6d051f1e4e756-ab14eebb171a9a5c9bfdeb2f88933d2dc4904ea8bb09444984e52b13d230e251.svg
64
+ I, [2016-07-17T23:46:56.374818 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/2ac2dd94f9b7e54292f6d051f1e4e756-ab14eebb171a9a5c9bfdeb2f88933d2dc4904ea8bb09444984e52b13d230e251.svg.gz
65
+ I, [2016-07-17T23:46:56.392207 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/5cf5db49df178f9357603f945752a1ef-033650e1d6193b70d59bb60e773f47b6d9aefdd56abc7ccdba3c7bed4e57ccad.png
66
+ I, [2016-07-17T23:46:56.393208 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/8970f5e1e92aea933b502a2d73976b76-877bde3739dc7080c3fb00ee9012db6f21ed0dbbf11cd596dbb6e1a35bfb71f9.png
67
+ I, [2016-07-17T23:46:56.395490 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/ecb4572a5e478b107dfcb60c16a7eefa-6d1ab3741d5a164dc2aab48bb74429aebe2e2e29606feca581081697624dc18c.ttf
68
+ I, [2016-07-17T23:46:56.395846 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/ecb4572a5e478b107dfcb60c16a7eefa-6d1ab3741d5a164dc2aab48bb74429aebe2e2e29606feca581081697624dc18c.ttf.gz
69
+ I, [2016-07-17T23:46:56.396979 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fbd0d00cc9b670f05c17893a40da08d0-5731789fd0d7847a582b52b55a83e7a0ad4684acd5a9b487557635a08c112d0e.svg
70
+ I, [2016-07-17T23:46:56.397669 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fbd0d00cc9b670f05c17893a40da08d0-5731789fd0d7847a582b52b55a83e7a0ad4684acd5a9b487557635a08c112d0e.svg.gz
71
+ I, [2016-07-17T23:46:56.399261 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fc2dcaaf2057331ff76c5d37e1aa7056-efba50c701b697fc8160603b9e876adcf47511f35af68701db285272c965a45f.svg
72
+ I, [2016-07-17T23:46:56.399660 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fc2dcaaf2057331ff76c5d37e1aa7056-efba50c701b697fc8160603b9e876adcf47511f35af68701db285272c965a45f.svg.gz
73
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/2ac2dd94f9b7e54292f6d051f1e4e756-ab14eebb171a9a5c9bfdeb2f88933d2dc4904ea8bb09444984e52b13d230e251.svg to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/2ac2dd94f9b7e54292f6d051f1e4e756.svg
74
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/2ac2dd94f9b7e54292f6d051f1e4e756-ab14eebb171a9a5c9bfdeb2f88933d2dc4904ea8bb09444984e52b13d230e251.svg.gz to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/2ac2dd94f9b7e54292f6d051f1e4e756.svg.gz
75
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/5cf5db49df178f9357603f945752a1ef-033650e1d6193b70d59bb60e773f47b6d9aefdd56abc7ccdba3c7bed4e57ccad.png to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/5cf5db49df178f9357603f945752a1ef.png
76
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/8970f5e1e92aea933b502a2d73976b76-877bde3739dc7080c3fb00ee9012db6f21ed0dbbf11cd596dbb6e1a35bfb71f9.png to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/8970f5e1e92aea933b502a2d73976b76.png
77
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/ecb4572a5e478b107dfcb60c16a7eefa-6d1ab3741d5a164dc2aab48bb74429aebe2e2e29606feca581081697624dc18c.ttf to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/ecb4572a5e478b107dfcb60c16a7eefa.ttf
78
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/ecb4572a5e478b107dfcb60c16a7eefa-6d1ab3741d5a164dc2aab48bb74429aebe2e2e29606feca581081697624dc18c.ttf.gz to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/ecb4572a5e478b107dfcb60c16a7eefa.ttf.gz
79
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fbd0d00cc9b670f05c17893a40da08d0-5731789fd0d7847a582b52b55a83e7a0ad4684acd5a9b487557635a08c112d0e.svg to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fbd0d00cc9b670f05c17893a40da08d0.svg
80
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fbd0d00cc9b670f05c17893a40da08d0-5731789fd0d7847a582b52b55a83e7a0ad4684acd5a9b487557635a08c112d0e.svg.gz to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fbd0d00cc9b670f05c17893a40da08d0.svg.gz
81
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fc2dcaaf2057331ff76c5d37e1aa7056-efba50c701b697fc8160603b9e876adcf47511f35af68701db285272c965a45f.svg to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fc2dcaaf2057331ff76c5d37e1aa7056.svg
82
+ React On Rails: Symlinking /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fc2dcaaf2057331ff76c5d37e1aa7056-efba50c701b697fc8160603b9e876adcf47511f35af68701db285272c965a45f.svg.gz to /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fc2dcaaf2057331ff76c5d37e1aa7056.svg
83
+ ```
@@ -3,7 +3,7 @@ React on Rails supports the use of React Router. Client-side code doesn't need a
3
3
 
4
4
  However, when attempting to use server-rendering, it is necessary to take steps that prevent rendering when there is a router error or redirect. In these cases, the client code should return an object containing the `error` and a `redirectLocation` instead of the React component. The `react_component` helper method in your Rails view will automatically detect that there was an error/redirect and handle it accordingly.
5
5
 
6
- If you are working with the HelloWorldApp created by the react_on_rails generator, then the code below corresponds to the module in `client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx`.
6
+ If you are working with the HelloWorldApp created by the react_on_rails generator, then the code below corresponds to the module in `client/app/bundles/HelloWorld/startup/HelloWorldApp.jsx`.
7
7
 
8
8
  ```js
9
9
  const RouterApp = (props, railsContext) => {
@@ -1,5 +1,7 @@
1
1
  # Server Rendering Tips
2
2
 
3
+ Be sure to use mini_racer. See [issues/428](https://github.com/shakacode/react_on_rails/issues/428)
4
+
3
5
  ## General Tips
4
6
  - Your code can't reference `document`. Server side JS execution does not have access to `document`, so jQuery and some
5
7
  other libs won't work in this environment. You can debug this by putting in `console.log`
@@ -8,6 +10,7 @@
8
10
  component. Since the passed in props Hash from the view helper applies to client and server side code, the best way to
9
11
  do this is to use a generator function.
10
12
  - If you're serious about server rendering, it's worth the effort to have different entry points for client and server rendering. It's worth the extra complexity.
13
+ - You can enable node server rendering if you want. See more information here: https://github.com/shakacode/react_on_rails/blob/master/docs/additional-reading/node-server-rendering.md
11
14
 
12
15
  The point is that you have separate files for top level client or server side, and you pass some extra option indicating that rendering is happening server side.
13
16
 
@@ -34,4 +34,27 @@ The best source of docs is the main [ReactOnRails.js](../../node_package/src/Rea
34
34
  * `traceTurbolinks: true|false Gives you debugging messages on Turbolinks events
35
35
  */
36
36
  setOptions(options)
37
+
38
+ /**
39
+ * Allow directly calling the page loaded script in case the default events that trigger react
40
+ * rendering are not sufficient, such as when loading JavaScript asynchronously with TurboLinks:
41
+ * More details can be found here:
42
+ * https://github.com/shakacode/react_on_rails/blob/master/docs/additional-reading/turbolinks.md
43
+ */
44
+ reactOnRailsPageLoaded()
45
+
46
+ /**
47
+ * Returns CSRF authenticity token inserted by Rails csrf_meta_tags
48
+ * @returns String or null
49
+ */
50
+
51
+ authenticityToken()
52
+
53
+ /**
54
+ * Returns header with csrf authenticity token and XMLHttpRequest
55
+ * @param {*} other headers
56
+ * @returns {*} header
57
+ */
58
+
59
+ authenticityHeaders(otherHeaders = {})
37
60
  ```
@@ -3,7 +3,7 @@
3
3
  We're now releasing this as a combined ruby gem plus npm package. We will keep the version numbers in sync.
4
4
 
5
5
  ## Testing the Gem before Release from a Rails App
6
- See [Contributing](./contributing.md)
6
+ See [Contributing](../../CONTRIBUTING.md)
7
7
 
8
8
  ## Releasing a new gem version
9
9
  Run `rake -D release` to see instructions on how to release via the rake task.
@@ -4,7 +4,7 @@ By Justin Gordon, January 26, 2016
4
4
 
5
5
  This document is an extension and complement to [The Rails Doctrine](http://rubyonrails.org/doctrine/). If you haven't read that document, I suggest you do so first.
6
6
 
7
- As stated in the [React on Rails README](../README.md), the project objective is to provide an opinionated and optimal framework for integrating **Ruby on Rails** with modern JavaScript tooling and libraries. When considering what goes into **react_on_rails**, we ask ourselves, is the functionality related to the intersection of using Rails and with modern JavaScript? A good example is view helper integration of React components on a Rails view. If the answer is yes, then the functionality belongs right here. In other cases, we're releasing separate npm packages or Ruby gems. For example, we needed an easy way to integrate [Twitter Bootstrap](http://getbootstrap.com/) with Webpack, and we released the [npm bootstrap-loader](https://github.com/shakacode/bootstrap-loader/).
7
+ As stated in the [React on Rails README](../../README.md), the project objective is to provide an opinionated and optimal framework for integrating **Ruby on Rails** with modern JavaScript tooling and libraries. When considering what goes into **react_on_rails**, we ask ourselves, is the functionality related to the intersection of using Rails and with modern JavaScript? A good example is view helper integration of React components on a Rails view. If the answer is yes, then the functionality belongs right here. In other cases, we're releasing separate npm packages or Ruby gems. For example, we needed an easy way to integrate [Twitter Bootstrap](http://getbootstrap.com/) with Webpack, and we released the [npm bootstrap-loader](https://github.com/shakacode/bootstrap-loader/).
8
8
 
9
9
  Besides the project objective, let's stick with the "Rails Doctrine" and keep the following in mind.
10
10
 
@@ -19,13 +19,13 @@ The React on Rails setup provides several key components related to front-end de
19
19
  6. Happiness for us is actively participating in open source, so we want to be where the action is, which is with the npm libraries on github.com.
20
20
  7. You can get set up on React on Rails **FAST** using our application generator.
21
21
  8. By placing all client-side development inside of the `/client` directory, pure JavaScript developers can productively do development separate from Rails. Instead of Rails APIs, stub APIs on an express server can provide a simple backend, allowing for rapid iteration of UI prototypes.
22
- 9. Just because we're not relying on the Rails asset pipeline for ES6 conversion does not mean that we're deploying Rails apps in any different way. We still use the asset pipeline to include our Webpack compiled JavaScript. This only requires a few small modifications, as explained in our doc [Heroku Deployment](additional-reading/heroku_deployment.md).
22
+ 9. Just because we're not relying on the Rails asset pipeline for ES6 conversion does not mean that we're deploying Rails apps in any different way. We still use the asset pipeline to include our Webpack compiled JavaScript. This only requires a few small modifications, as explained in our doc [Heroku Deployment](../additional-reading/heroku-deployment.md).
23
23
 
24
24
  ## Convention over Configuration
25
25
  * React on Rails has taken the hard work out of figuring out the JavaScript tooling that works best with Rails. Not only could you spend lots of time researching different tooling, but then you'd have to figure out how to splice it all together. This is where a lot of "JavaScript fatigue" comes from. The following keep the code clean and consistent:
26
- * [Style Guide](coding-style/style.md)
27
- * [linters](coding-style/linters.md)
28
- * [Recommended Project Structure](recommended-project-structure.md)
26
+ * [Style Guide](../coding-style/style.md)
27
+ * [linters](../contributor-info/linters.md)
28
+ * [Recommended Project Structure](../additional-reading/recommended-project-structure.md)
29
29
 
30
30
  We're big believers in this quote from the Rails Doctrine:
31
31
 
@@ -61,7 +61,7 @@ ES5 was ugly. ES6 is beautiful. React is beautiful. Client side code written wit
61
61
  Assuming that you're building the type of app that's a good fit for Rails (document/database based with lots of business rules), the tight integration of modern JavaScript with React on top of Ruby on Rails is better than building a pure client side app and separate microservices. Here's why:
62
62
 
63
63
  * Via React on Rails, we can seamlessly integrate React UI components with Rails.
64
- * Tight integration allows for trivial set up of server rendering of React on top of Rails, complete with support for fragment caching of the server rendered HTML, and integration with [Turbolinks](https://github.com/rails/turbolinks).
64
+ * Tight integration allows for trivial set up of server rendering of React on top of Rails, complete with support for fragment caching of the server rendered HTML, and integration with [Turbolinks](https://github.com/turbolinks/turbolinks).
65
65
  * Tight integration allows mixing and matching Rails pages with React driven pages, even on the same page. Not every part of a UI requires the high fidelity achievable using React. Many existing apps may have hundreds of standards Rails forms. Support for mixing and matching React with Rails forms provides the best of both worlds.
66
66
 
67
67
  ## Progress over Stability
@@ -1,12 +1,17 @@
1
- # Tutorial for React on Rails (THIS ONLY WORKS UP TO VERSION 5.1.1)
2
-
3
- *Version 5.2 and greater have removed the non-essential options. See the [changelog](../CHANGELOG.md) for details on what was removed.*
1
+ # React on Rails Basic Tutorial
4
2
 
5
3
  This tutorial setups up a new Rails app with **React on Rails**, demonstrating Rails + React + Redux + Server Rendering.
6
4
 
7
- You can find:
5
+ After finishing this tutorial you will get application that can do the following (live on Heroku):
6
+
7
+ ![example](https://cloud.githubusercontent.com/assets/371302/17368567/111cc722-596b-11e6-9b72-ac5967a60e42.gif)
8
+
9
+ You can find here:
10
+ * [Source code for this app](https://github.com/dzirtusss/hello-react-on-rails)
11
+ * [Live on Heroku](https://hello-react-on-rails.herokuapp.com/)
8
12
 
9
- * [Source code for this sample app](https://github.com/justin808/test-react-on-rails-3) (for an older version)
13
+ Old version of this app is here:
14
+ * [Source code](https://github.com/justin808/test-react-on-rails-3)
10
15
  * [Live on Heroku](https://shakacode-react-on-rails.herokuapp.com/hello_world)
11
16
 
12
17
  By the time you read this, the latest may have changed. Be sure to check the versions here:
@@ -14,116 +19,84 @@ By the time you read this, the latest may have changed. Be sure to check the ver
14
19
  * https://rubygems.org/gems/react_on_rails
15
20
  * https://www.npmjs.com/package/react-on-rails
16
21
 
17
- Trying out v4 is super easy, so long as you have the basic prerequisites. This includes the basics for Rails 4.x and node version 5+. I recommend `rvm` and `nvm` to install Ruby and Node.
22
+ ##Setting up the environment
18
23
 
19
- ```
20
- cd <directory where you want to create your new Rails app>
21
- # any name you like
22
- rails new test-react-on-rails-3
23
- cd test-react-on-rails-3
24
- # git-extras command to make a new git repo and commit everything
25
- git setup
26
- vim Gemfile
27
- ```
24
+ Trying out **React on Rails** is super easy, so long as you have the basic prerequisites. This includes the basics for Rails 4.x and node version 5+. I recommend `rvm` and `nvm` to install Ruby and Node. Rails can be installed as ordinary gem.
28
25
 
29
- Add this line to your Gemfile:
30
-
31
- ```
32
- gem 'react_on_rails'
33
26
  ```
27
+ nvm install node # download and install latest stable Node
28
+ nvm alias default node # make it default version
29
+ nvm list # check
34
30
 
31
+ rvm install 2.3.1 # download and install latest stable Ruby (update to exact version)
32
+ rvm use 2.3.1 --default # use it and make it default
33
+ rvm list # check
35
34
 
36
- ```
37
- bundle
38
- bundle exec rails generate react_on_rails:install -R -S -H -L
39
- bundle && npm i
40
- npm run rails-server
35
+ gem install rails # download and install latest stable Rails
41
36
  ```
42
37
 
43
- * R => Redux
44
- * S => Server Rendering
45
- * H => Heroku setup
46
- * L => Linters
38
+ Then we need to create a fresh Rails application as following:
47
39
 
48
-
49
- Visit http://localhost:3000/hello_world and see your React On Rails app running!
50
-
51
- ```
52
- npm run express-server
53
40
  ```
41
+ cd <basic directory where you want to create your new Rails app>
54
42
 
55
- <img src="http://forum.shakacode.com/uploads/default/original/1X/5bd396a7f9c0764929b693fb79eb6685ec6f62cf.png" width="470" height="499">
56
-
57
- Visit http://localhost:4000 and see your React On Rails app running using the Webpack Dev server.
58
-
59
- With this setup, you can make changes to your JS or CSS and the browser will hot reload the changes (no page refresh required).
43
+ rails new test-react-on-rails # any name you like
60
44
 
61
- I'm going to add this line to client/app/bundles/HelloWorld/HelloWorldWidget.jsx:
62
-
63
- ```html
64
- <h1>Welcome to React On Rails!</h1>
45
+ cd test-react-on-rails
65
46
  ```
66
47
 
67
- <img src="http://forum.shakacode.com/uploads/default/original/1X/d20719a52541e95ddd968a95192d3247369c3bf6.png" width="498" height="500">
68
-
69
- If you save, you'll soon see this screen:
70
-
71
- <img src="http://forum.shakacode.com/uploads/default/original/1X/228706a99a411548a4539f72446d3f115ed36f95.png" width="555" height="500">
72
-
48
+ ![01](https://cloud.githubusercontent.com/assets/20628911/17464917/3c29e55a-5cf2-11e6-8754-046ba3ee92d9.png)
73
49
 
74
- If you're motivated to try the linting setup, you'll want to run the following commands:
50
+ Add **React On Rails** gem to your Gemfile (`vim Gemfile` or `nano Gemfile` or in IDE):
75
51
 
76
- bin/rake lint
77
-
78
- You'll see a few rubocop errors.
52
+ ```
53
+ gem 'react_on_rails', '~>6' # use latest gem version > 6
54
+ ```
79
55
 
80
- rubocop -a
56
+ ![02](https://cloud.githubusercontent.com/assets/20628911/17464919/3c2d74c2-5cf2-11e6-8704-a84958832fbb.png)
81
57
 
82
- That will fix almost all the errors. However, the linter setup expects you to have rspec (small bug currently). These two commands address that issue:
58
+ put everything under git repository (or `rails generate` will not work properly)
83
59
 
84
60
  ```
85
- rm -rf test
86
- mkdir spec
61
+ # Here are git commands to make a new git repo and commit everything
62
+ git init
63
+ git add -A
64
+ git commit -m "Initial commit"
87
65
  ```
88
66
 
89
- bin/rake lint
67
+ update dependencies and generate empty app via `react_on_rails:install`. If you haven't done first git commit it will generate error and you just need to commit.
90
68
 
91
- The edit `application.scss`. Delete the comment at the top.
69
+ ```
70
+ bundle
71
+ rails generate react_on_rails:install
72
+ bundle && npm install
73
+ ```
92
74
 
93
- bin/rake lint
75
+ ![03](https://cloud.githubusercontent.com/assets/20628911/17464918/3c2c1f00-5cf2-11e6-9525-7b2e15659e01.png)
94
76
 
95
- You should see
77
+ and then run server with
96
78
 
97
79
  ```
98
- bin/rake lint
80
+ foreman start -f Procfile.dev
81
+ ```
99
82
 
100
- Running via Spring preloader in process 26674
101
- Running Rubocop Linters via `rubocop -S -D .`
102
- rubocop -S -D .
103
- Warning: Deprecated pattern style '/Users/justin/scratch/test-react-on-rails-3/client/node_modules/**/*' in /Users/justin/scratch/test-react-on-rails-3/.rubocop.yml
104
- Inspecting 22 files
105
- ......................
83
+ ![04](https://cloud.githubusercontent.com/assets/20628911/17464921/3c2fdb40-5cf2-11e6-9343-6afa53593a70.png)
106
84
 
107
- 22 files inspected, no offenses detected
108
- Running ruby-lint Linters via `ruby-lint app config spec lib`
109
- ruby-lint app config spec lib
110
- scss-lint found no lints
111
- Running eslint via `cd client && npm run eslint . -- --ext .jsx,.js`
112
- cd client && npm run eslint . -- --ext .jsx,.js
113
85
 
114
- > react-webpack-rails-tutorial@1.1.0 eslint /Users/justin/scratch/test-react-on-rails-3/client
115
- > eslint --ext .js,.jsx . "." "--ext" ".jsx,.js"
86
+ Visit http://localhost:3000/hello_world and see your **React On Rails** app running!
116
87
 
117
- Running jscs via `cd client && npm run jscs .`
118
- cd client && npm run jscs .
88
+ ![05](https://cloud.githubusercontent.com/assets/20628911/17464920/3c2e8ae2-5cf2-11e6-9e30-5ec5f9e2cbc6.png)
119
89
 
120
- > react-webpack-rails-tutorial@1.1.0 jscs /Users/justin/scratch/test-react-on-rails-3/client
121
- > jscs --verbose . "."
90
+ ### Custom IP & PORT setup (Cloud9 example)
122
91
 
123
- Completed running all JavaScript Linters
124
- Completed all linting
92
+ In case you are running some custom setup with different IP or PORT you should also edit Procfile.dev. For example to be able to run on free Cloud9 IDE we are putting IP 0.0.0.0 and PORT 8080
93
+
94
+ ``` Procfile.dev
95
+ web: rails s -p 8080 -b 0.0.0.0
125
96
  ```
126
97
 
98
+ Then visit https://your-shared-addr.c9users.io:8080/hello_world
99
+
127
100
  ## RubyMine
128
101
 
129
102
  It's super important to exclude certain directories from RubyMine or else it will slow to a crawl as it tries to parse all the npm files.
@@ -131,9 +104,6 @@ It's super important to exclude certain directories from RubyMine or else it wil
131
104
  * `app/assets/webpack`
132
105
  * `client/node_modules`
133
106
 
134
- <img src="http://forum.shakacode.com/uploads/default/original/1X/a1b3e1146d86915f7d5d1c89548e81ec208458cc.png" width="338" height="500">
135
-
136
-
137
107
  ## Deploying to Heroku
138
108
 
139
109
  ### Create Your Heroku App
@@ -141,7 +111,7 @@ It's super important to exclude certain directories from RubyMine or else it wil
141
111
 
142
112
  1. Visit https://dashboard.heroku.com/new and create an app, say named `my-name-react-on-rails`:
143
113
 
144
- <img src="http://forum.shakacode.com/uploads/default/original/1X/2d1b6abc40eef8e411e84d2679de91353f617567.png" width="690" height="319">
114
+ ![06](https://cloud.githubusercontent.com/assets/20628911/17465014/1f29bf3c-5cf4-11e6-869f-4215987ae854.png)
145
115
 
146
116
  Run this command that looks like this from your new heroku app
147
117
 
@@ -161,6 +131,9 @@ Set heroku to use multiple buildpacks:
161
131
  gem 'pg'
162
132
  ```
163
133
 
134
+ ![07](https://cloud.githubusercontent.com/assets/20628911/17465015/1f2f4042-5cf4-11e6-8287-2fb077550809.png)
135
+
136
+
164
137
  2. Replace your `database.yml` file with this (assuming your app name is "ror").
165
138
 
166
139
  ```yml
@@ -190,25 +163,33 @@ Then you need to setup postgres so you can run locally:
190
163
 
191
164
  ```
192
165
  bundle
193
- bin/rake db:migrate
194
- bin/rake db:setup
166
+ rake db:setup
167
+ rake db:migrate
195
168
  ```
196
169
 
170
+ ![08](https://cloud.githubusercontent.com/assets/20628911/17465016/1f3559f0-5cf4-11e6-8ab4-c5572e4644a5.png)
171
+
197
172
  I'd recommend adding this line to the top of your `routes.rb`. That way, your root page will go to the Hello World page for React On Rails.
198
173
 
199
174
  ```ruby
200
175
  root "hello_world#index"
201
176
  ```
202
177
 
203
- You can see the changes [here on github](https://github.com/justin808/test-react-on-rails-3/commit/09909433c186566a53f611e8b1cfeca3238f5266).
178
+ ![09](https://cloud.githubusercontent.com/assets/20628911/17465018/1f3b685e-5cf4-11e6-93f8-105fc48517d0.png)
204
179
 
205
- Then push your app to Heroku!
180
+ Then after all changes are done don't forget to commit them with git and finally you can push your app to Heroku!
206
181
 
207
- git push heroku master
182
+ ```
183
+ git add -A
184
+ git commit -m "Latest changes"
185
+ git push heroku master
186
+ ```
208
187
 
209
- Here's mine:
188
+ ![10](https://cloud.githubusercontent.com/assets/20628911/17465017/1f38fbaa-5cf4-11e6-8d86-a3d91e3878e0.png)
210
189
 
211
- * [Source code for this sample app](https://github.com/justin808/test-react-on-rails-3)
212
- * [Live on Heroku](https://shakacode-react-on-rails.herokuapp.com/hello_world)
190
+ Here it is:
191
+
192
+ * [Source code for this sample app](https://github.com/dzirtusss/hello-react-on-rails)
193
+ * [Live on Heroku](https://hello-react-on-rails.herokuapp.com/)
213
194
 
214
195
  Feedback is greatly appreciated! As are stars on github!