forked from shakacode/react_on_rails
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into feature/no-request-context
- Loading branch information
Showing
39 changed files
with
627 additions
and
277 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,30 @@ | ||
## Node Server Rendering | ||
# Node.js for Server Rendering | ||
|
||
### Warning: this is an experimental feature | ||
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. | ||
|
||
The default server rendering exploits ExecJS to render react components. | ||
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 | ||
via socket (`client/node/node.sock`) | ||
If you're serious about this comparing Node.js versus execJS/mini_racer, then [get in touch](mailto:[email protected])! We can definitely collaborate with you on refining this solution. However, please try out these instructions first. | ||
|
||
## Setup of React on Rails with Node.js Server Rendering | ||
**Warning: this is an experimental feature.** | ||
|
||
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. | ||
|
||
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 | ||
via a socket (`client/node/node.sock`) | ||
|
||
### Getting started | ||
|
||
### Configuration | ||
|
||
#### Update the React on Rails Initializer | ||
|
||
To use node process just set `server_render_method = "NodeJS"` in `config/initializers/react_on_rails.rb`. To change back | ||
to ExecJS set `server_render_method = "ExecJS"` | ||
|
||
### Configuration | ||
```ruby | ||
# app/config/initializers/react_on_rails.rb | ||
config.server_render_method = "NodeJS" | ||
``` | ||
|
||
You need to configure the name of the server bundle in two places: | ||
|
||
|
@@ -26,3 +38,109 @@ You need to configure the name of the server bundle in two places: | |
# not affect performance. | ||
config.server_bundle_js_file = "webpack-bundle.js" | ||
``` | ||
|
||
And in `client/node/package.json` | ||
|
||
```javascript | ||
// client/node/package.json | ||
{ | ||
"name": "react_on_rails_node", | ||
"version": "0.0.0", | ||
"private": true, | ||
"scripts": { | ||
"start": "node ./server.js -s webpack-bundle.js" | ||
}, | ||
"dependencies": { | ||
} | ||
} | ||
``` | ||
|
||
And you'll need this file: `client/node/server.js` | ||
|
||
```javascript | ||
// client/node/server.js | ||
var net = require('net'); | ||
var fs = require('fs'); | ||
|
||
var bundlePath = '../../app/assets/webpack/'; | ||
var bundleFileName = 'webpack-bundle.js'; | ||
|
||
var currentArg; | ||
|
||
function Handler() { | ||
this.queue = []; | ||
this.initialized = false; | ||
} | ||
|
||
Handler.prototype.handle = function (connection) { | ||
var callback = function () { | ||
connection.setEncoding('utf8'); | ||
connection.on('data', (data)=> { | ||
console.log('Processing request: ' + data); | ||
var result = eval(data); | ||
connection.write(result); | ||
}); | ||
}; | ||
|
||
if (this.initialized) { | ||
callback(); | ||
} else { | ||
this.queue.push(callback); | ||
} | ||
}; | ||
|
||
Handler.prototype.initialize = function () { | ||
console.log('Processing ' + this.queue.length + ' pending requests'); | ||
var callback; | ||
while (callback = this.queue.pop()) { | ||
callback(); | ||
} | ||
|
||
this.initialized = true; | ||
}; | ||
|
||
var handler = new Handler(); | ||
|
||
process.argv.forEach((val) => { | ||
if (val[0] == '-') { | ||
currentArg = val.slice(1); | ||
return; | ||
} | ||
|
||
if (currentArg == 's') { | ||
bundleFileName = val; | ||
} | ||
}); | ||
|
||
try { | ||
fs.mkdirSync(bundlePath); | ||
} catch (e) { | ||
if (e.code != 'EEXIST') throw e; | ||
} | ||
|
||
fs.watchFile(bundlePath + bundleFileName, (curr) => { | ||
if (curr && curr.blocks && curr.blocks > 0) { | ||
if (handler.initialized) { | ||
console.log('Reloading server bundle must be implemented by restarting the node process!'); | ||
return; | ||
} | ||
|
||
require(bundlePath + bundleFileName); | ||
console.log('Loaded server bundle: ' + bundlePath + bundleFileName); | ||
handler.initialize(); | ||
} | ||
}); | ||
|
||
var unixServer = net.createServer(function (connection) { | ||
handler.handle(connection); | ||
}); | ||
|
||
unixServer.listen('node.sock'); | ||
|
||
process.on('SIGINT', () => { | ||
unixServer.close(); | ||
process.exit(); | ||
}); | ||
|
||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,83 @@ | ||
## Rails assets | ||
# Rails assets and the Extract Text Plugin | ||
|
||
### Problem | ||
When client js uses images in render methods, e.g. `<img src='...' />` or in css, e.g. `background-image: url(...)` | ||
these assets fail to load. This happens because rails adds digest hashes to filenames | ||
when compiling assets, e.g. `img1.jpg` becomes `img1-dbu097452jf2v2.jpg`. | ||
The [Webpack file loader](https://github.com/webpack/file-loader) copies referenced files to | ||
the destination output directory, with an MD5 hash. The other term for this is a "digest". | ||
|
||
> By default the filename of the resulting file is the MD5 hash of the file's contents with | ||
the original extension of the required resource. | ||
|
||
The most common use cases for Webpack processed files are images used for backgrounds in | ||
CSS and fonts for CSS. However, this applies to any file that might be processed using the | ||
Webpack file loader. | ||
|
||
## The Problem | ||
To understand the problem, it helps to read this article: | ||
[What is fingerprinting and why should I care](http://guides.rubyonrails.org/asset_pipeline.html#what-is-fingerprinting-and-why-should-i-care-questionmark) | ||
Basically, when Rails prepares assets for production deployments, it also adds a digest | ||
to the file names. E.g., `img1.jpg` becomes `img1-dbu097452jf2v2.jpg`. | ||
|
||
When compiling its native css Rails transforms all urls and links to digested | ||
versions, i.e. `background-image: image-url(img1.jpg)` becomes | ||
`background-image: url(img1-dbu097452jf2v2.jpg)`. However this doesn't happen for js and | ||
css files compiled by webpack on the client side, because they don't use | ||
`image-url` and `asset-url` and therefore assets fail to load. | ||
`image-url` and `asset-url`. Without some fix, these assets would fail to load. | ||
|
||
### Solution | ||
When Webpack's client JavaScript uses images in render methods, e.g. `<img src='...' />` or | ||
in css, e.g. `background-image: url(...)` The code (such as the CSS) generated by the Webpack | ||
will have the Webpack digested name (MD5 hash). Since the Webpack generated CSS expects | ||
just one level of "digesting", this "double-digesting" from Rails will cause such these assets | ||
fail to load. | ||
|
||
React on Rails creates symlinks of non-digested versions to digested versions when doing a Rails assets compile. | ||
The solution is implemented using `assets:precompile` after-hook. The assets for symlinking | ||
are defined by `config.symlink_non_digested_assets_regex` in `config/initializers/react_on_rails.rb`. | ||
## The Solution: Symlink Original File Names to New File Names | ||
React on Rails creates symlinks of non-digested versions (original webpack digested file names) | ||
to the Rails deployed digested versions when doing a Rails assets compile. The solution is | ||
implemented using `assets:precompile` after-hook in | ||
file [lib/tasks/assets.rake](../../lib/tasks/assets.rake) | ||
The assets for symlinking are defined by `config.symlink_non_digested_assets_regex` in | ||
`config/initializers/react_on_rails.rb`. | ||
|
||
## Disabling the Symlinking | ||
To disable symlinks set this parameter to `nil`. | ||
|
||
|
||
## Example from /spec/dummy | ||
|
||
If you run | ||
|
||
``` | ||
cd spec/dummy | ||
RAILS_ENV=production bundle exec rake assets:precompile | ||
rails s -e production | ||
``` | ||
|
||
You will see this. This shows how the file names output by rails. Note the original names after | ||
being processed by Webpack are just MD5's. | ||
|
||
``` | ||
I, [2016-07-17T23:46:56.301981 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/server-bundle-42935dea382802a27e91b7df444a2813f74b4e6a0fce5606d863aaa10c0623d7.js | ||
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 | ||
I, [2016-07-17T23:46:56.370390 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/application_static-dfa728160c3cdebc633c2f6fb3823411530b307044f4dfe460790eef00b4e421.js | ||
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 | ||
I, [2016-07-17T23:46:56.372895 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/application_static-17ed778d5061d4797556632b7bfbf405e067d9e7f140060a7f56a09788251f16.css | ||
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 | ||
I, [2016-07-17T23:46:56.374531 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/2ac2dd94f9b7e54292f6d051f1e4e756-ab14eebb171a9a5c9bfdeb2f88933d2dc4904ea8bb09444984e52b13d230e251.svg | ||
I, [2016-07-17T23:46:56.374818 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/2ac2dd94f9b7e54292f6d051f1e4e756-ab14eebb171a9a5c9bfdeb2f88933d2dc4904ea8bb09444984e52b13d230e251.svg.gz | ||
I, [2016-07-17T23:46:56.392207 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/5cf5db49df178f9357603f945752a1ef-033650e1d6193b70d59bb60e773f47b6d9aefdd56abc7ccdba3c7bed4e57ccad.png | ||
I, [2016-07-17T23:46:56.393208 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/8970f5e1e92aea933b502a2d73976b76-877bde3739dc7080c3fb00ee9012db6f21ed0dbbf11cd596dbb6e1a35bfb71f9.png | ||
I, [2016-07-17T23:46:56.395490 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/ecb4572a5e478b107dfcb60c16a7eefa-6d1ab3741d5a164dc2aab48bb74429aebe2e2e29606feca581081697624dc18c.ttf | ||
I, [2016-07-17T23:46:56.395846 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/ecb4572a5e478b107dfcb60c16a7eefa-6d1ab3741d5a164dc2aab48bb74429aebe2e2e29606feca581081697624dc18c.ttf.gz | ||
I, [2016-07-17T23:46:56.396979 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fbd0d00cc9b670f05c17893a40da08d0-5731789fd0d7847a582b52b55a83e7a0ad4684acd5a9b487557635a08c112d0e.svg | ||
I, [2016-07-17T23:46:56.397669 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fbd0d00cc9b670f05c17893a40da08d0-5731789fd0d7847a582b52b55a83e7a0ad4684acd5a9b487557635a08c112d0e.svg.gz | ||
I, [2016-07-17T23:46:56.399261 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fc2dcaaf2057331ff76c5d37e1aa7056-efba50c701b697fc8160603b9e876adcf47511f35af68701db285272c965a45f.svg | ||
I, [2016-07-17T23:46:56.399660 #77382] INFO -- : Writing /Users/justin/shakacode/react_on_rails/spec/dummy/public/assets/fc2dcaaf2057331ff76c5d37e1aa7056-efba50c701b697fc8160603b9e876adcf47511f35af68701db285272c965a45f.svg.gz | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,5 +5,5 @@ See documentation [at github.com/shakacode/react_on_rails](https://github.com/sh | |
If you need additional help, please consider: | ||
|
||
* [Our ShakaCode Forum for React on Rails](https://forum.shakacode.com/c/rails/reactonrails). | ||
* Joining our Slack discussion room by [email us a bit about you and your project](mailto:[email protected]). | ||
* Joining our Slack discussion room by [emailing us a bit about you and your project](mailto:[email protected]). | ||
* [Hiring us](https://forum.shakacode.com/c/rails/reactonrails) for coaching and custom web application development for your project. |
Oops, something went wrong.