react_on_rails 0.1.8 → 1.0.0.pre
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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.jscsrc +3 -1
- data/.rubocop.yml +7 -2
- data/.travis.yml +24 -2
- data/README.md +105 -85
- data/Rakefile +14 -4
- data/app/assets/javascripts/react_on_rails.js +67 -33
- data/app/helpers/react_on_rails_helper.rb +14 -4
- data/docs/Contributing.md +66 -0
- data/docs/README.md +1 -0
- data/docs/sample_generated_js/client-generated.js +12 -0
- data/docs/sample_generated_js/server-generated.js +11 -0
- data/lib/react_on_rails/server_rendering_pool.rb +64 -58
- data/lib/react_on_rails/version.rb +1 -1
- metadata +8 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b275f388735a62982a5056840c44bf0779da6636
|
|
4
|
+
data.tar.gz: 27d0bfbe15a24476c55c9ba6fa8973213e875f1a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 168fd64398f5d3e015401652ce81e60fca5a083500cee3bf4645898476fdbc7161f912fe59362e73f633f889f3976de8ff332809a375e9260526b568dd7f4b94
|
|
7
|
+
data.tar.gz: bccaeff6f9225a65e246c9eeef5a48d97dcb1e8d96acba82afcd8719690eb095d4d1f8a1a577cf896b4ef540150519adc2fe895e8c0cf71e07f95046b846c795
|
data/.gitignore
CHANGED
|
@@ -11,8 +11,11 @@
|
|
|
11
11
|
|
|
12
12
|
/spec/dummy/client/node_modules
|
|
13
13
|
/spec/dummy/app/assets/javascripts/generated/
|
|
14
|
+
/spec/dummy-react-013/client/node_modules
|
|
15
|
+
/spec/dummy-react-013/app/assets/javascripts/generated/
|
|
14
16
|
|
|
15
17
|
# RVM
|
|
16
18
|
.ruby-version
|
|
17
19
|
.ruby-gemset
|
|
18
20
|
|
|
21
|
+
node_modules
|
data/.jscsrc
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"preset": "airbnb",
|
|
3
3
|
"fileExtensions": [".js", ".jsx"],
|
|
4
|
-
"excludeFiles": ["build/**", "node_modules/**"]
|
|
4
|
+
"excludeFiles": ["**/build/**", "**/node_modules/**", "**/generated/**", "**/docs/**", "**/tmp/**", "**/sample_generated/**"],
|
|
5
|
+
"requireTrailingComma": { ignoreSingleValue: true, ignoreSingleLine: true },
|
|
6
|
+
"validateQuoteMarks": false
|
|
5
7
|
}
|
data/.rubocop.yml
CHANGED
|
@@ -37,13 +37,17 @@ Lint/HandleExceptions:
|
|
|
37
37
|
|
|
38
38
|
# Offense count: 1
|
|
39
39
|
Metrics/AbcSize:
|
|
40
|
-
Max:
|
|
40
|
+
Max: 23
|
|
41
41
|
|
|
42
42
|
# Offense count: 1
|
|
43
43
|
# Configuration parameters: CountComments.
|
|
44
44
|
Metrics/ClassLength:
|
|
45
45
|
Max: 114
|
|
46
46
|
|
|
47
|
+
Metrics/ParameterLists:
|
|
48
|
+
Max: 5
|
|
49
|
+
CountKeywordArgs: false
|
|
50
|
+
|
|
47
51
|
# Offense count: 9
|
|
48
52
|
# Configuration parameters: CountComments.
|
|
49
53
|
Metrics/MethodLength:
|
|
@@ -52,11 +56,12 @@ Metrics/MethodLength:
|
|
|
52
56
|
# Offense count: 1
|
|
53
57
|
# Configuration parameters: CountComments.
|
|
54
58
|
Metrics/ModuleLength:
|
|
55
|
-
Max:
|
|
59
|
+
Max: 110
|
|
56
60
|
|
|
57
61
|
# Offense count: 3
|
|
58
62
|
# Configuration parameters: AllowedVariables.
|
|
59
63
|
Style/GlobalVars:
|
|
60
64
|
Exclude:
|
|
61
65
|
- 'spec/dummy/config/environments/development.rb'
|
|
66
|
+
- 'spec/dummy-react-013/config/environments/development.rb'
|
|
62
67
|
|
data/.travis.yml
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
language: ruby
|
|
2
2
|
rvm:
|
|
3
3
|
- 2.2.2
|
|
4
|
+
|
|
4
5
|
gemfile:
|
|
5
6
|
- spec/dummy/Gemfile
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
env:
|
|
9
|
+
- export RAILS_ENV=test
|
|
10
|
+
|
|
11
|
+
install:
|
|
12
|
+
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install 4.2.0
|
|
13
|
+
- npm install -g npm
|
|
14
|
+
- bundle install
|
|
15
|
+
- cd spec/dummy/client && npm install
|
|
16
|
+
- $(npm bin)/webpack --config webpack.server.js
|
|
17
|
+
- $(npm bin)/webpack --config webpack.client.js
|
|
18
|
+
- cd ../../dummy-react-013/client && npm install
|
|
19
|
+
- $(npm bin)/webpack --config webpack.server.js
|
|
20
|
+
- $(npm bin)/webpack --config webpack.client.js
|
|
21
|
+
|
|
22
|
+
before_script:
|
|
23
|
+
- cd ../../
|
|
24
|
+
- export DISPLAY=:99.0
|
|
25
|
+
- sh -e /etc/init.d/xvfb start
|
|
26
|
+
|
|
7
27
|
script:
|
|
8
28
|
- rake run_rspec:gem
|
|
9
|
-
- rake run_rspec:dummy
|
|
29
|
+
- DRIVER=selenium_firefox rake run_rspec:dummy
|
|
30
|
+
- DRIVER=selenium_firefox rake run_rspec:dummy_react_013
|
|
31
|
+
|
|
10
32
|
notifications:
|
|
11
33
|
slack:
|
|
12
34
|
secure: LfcUk4AJ4vAxWwRIyw4tFh8QNbYefMwfG/oLfsN3CdRMWMOtCOHR1GGsRhAOlfVVJ/FvHqVqWj5gK7z7CaO5Uvl7rD3/zJ8QzExKx/iH9yWj55iIPuKLzwFNnBwRpFW/cqyU2lFPPRxGD50BUn3c+qybkuSqtKZ6qtTowwqlxLa5iyM3N95aZp7MEIKCP7cPcnHfLbJyP8wBpotp/rtw62eXM2HIRJJwgjcp+n+My7VFR9DnBXNFf6R91aZHM4U4cHHDbu15HFtH8honVrzK1JQdyqMNHga+j04dFuaS7z9Q369/hsELMOBp/227+Pz7ZRfWZFK4UASguOvyeX7RmGTRpTuWLm1XJeUzfsPZVROecaSVQBve+U7F12yKqilt97QlvRXn2EGyBILqvxtFNNR4S9kgAf72/6EFgiM1TKq7i9zy6lVOnagU2+7amq7UeopX1uoFsUfNKMR7YbgV1WjF0IK95UP0b0/7ZOJlPYgi5zzkQi129qAFWSMmxGk+ZpsttHh/tjJtvAh0A3mHq/zb5w4ub/MbSyZqeDUNgGj72QArOWUFSAStQT1ybsVLeDoKPgOvVq7OV1D64rpcHjBXcqOCit8tDZ+TqkFhcYJo2cITSaqE4zJXn+4F5s7So5O8CyfKYQq+kFJCooYGmfgTUckJpGl7eIvKmL4TN9Q=
|
data/README.md
CHANGED
|
@@ -5,56 +5,129 @@
|
|
|
5
5
|
|
|
6
6
|
Gem Published: https://rubygems.org/gems/react_on_rails
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Live example, including server rendering + redux: http://www.reactrails.com/
|
|
9
|
+
Sponsored by [ShakaCode.com](http://www.shakacode.com/)
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
See [Action Plan for v1.0](https://github.com/shakacode/react_on_rails/issues/1). We're ready v1.0.
|
|
12
|
+
|
|
13
|
+
Feedback and pull-requests encouraged! Thanks in advance! We've got a private slack channel to discuss react + webpack + rails. [Email us for an invite contact@shakacode.com](mailto: contact@shakacode.com).
|
|
11
14
|
|
|
12
15
|
Supports:
|
|
13
16
|
|
|
14
17
|
1. Rails
|
|
15
18
|
2. Webpack
|
|
16
|
-
3. React
|
|
19
|
+
3. React, both v0.14 and v0.13.
|
|
17
20
|
4. Redux
|
|
18
21
|
5. Turbolinks
|
|
19
22
|
6. Server side rendering with fragment caching
|
|
20
|
-
7. react-router for client side rendering (and
|
|
23
|
+
7. react-router for client side rendering (and server side very soon)
|
|
21
24
|
|
|
22
25
|
## OPEN ISSUES
|
|
23
|
-
1.
|
|
24
|
-
2.
|
|
25
|
-
3.
|
|
26
|
-
4. Longer term, we hope to put in many conveniences into this gem, in terms of Webpack + Rails integration.
|
|
26
|
+
1. Almost all the open issues are nice to haves like more tests.
|
|
27
|
+
2. If you want to work on any of the open issues, please comment on the issue. My team is mentoring anybody that's trying to help with the issues.
|
|
28
|
+
3. Longer term, we hope to put in many conveniences into this gem, in terms of Webpack + Rails integration. We're open to suggestions.
|
|
27
29
|
|
|
28
30
|
## Links
|
|
29
|
-
1.
|
|
31
|
+
1. See https://github.com/shakacode/react-webpack-rails-tutorial/ for how to integrate it!
|
|
30
32
|
2. http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/
|
|
31
|
-
3. http://forum.
|
|
32
|
-
4.
|
|
33
|
-
5.
|
|
34
|
-
|
|
35
|
-
products, client work, and open source.
|
|
33
|
+
3. http://forum.shakacode.com
|
|
34
|
+
4. If you're looking for consulting on a project using React and Rails, [email us! contact@shakacode.com](mailto: contact@shakacode.com)? You can first join our slack room for some free advice.
|
|
35
|
+
5. We're looking for great developers that want to work with Rails + React with a distributed, worldwide team, for our own
|
|
36
|
+
products, client work, and open source. [More info here](http://www.shakacode.com/about/index.html#work-with-us).
|
|
36
37
|
|
|
37
38
|
## How is different than the [react-rails gem](https://github.com/reactjs/react-rails)?
|
|
38
39
|
1. `react_on_rails` depends on [webpack](http://webpack.github.io/). `react-rails` integrates closely with sprockets and
|
|
39
40
|
helps you integrate JSX and the react code into a Rails project.
|
|
40
|
-
2. Likewise, using Webpack as
|
|
41
|
+
2. Likewise, using Webpack as shown in the [react-webpack-rails-tutorial](https://github.com/justin808/react-webpack-rails-tutorial/)
|
|
41
42
|
does involve some extra setup. However, we feel that tight and simple integration with the node ecosystem is more than
|
|
42
43
|
worth any minor setup costs.
|
|
43
44
|
3. `react-rails` depends on `jquery-ujs` for client side rendering. `react_on_rails` has it's own JS code that does not
|
|
44
45
|
depend on jquery.
|
|
45
46
|
|
|
46
|
-
##
|
|
47
|
+
## Installation Checklist
|
|
48
|
+
1. Include the gems `react_on_rails` and `therubyracer` like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/361f4338ebb39a5d3934b00cb6d6fcf494773000/Gemfile#L42) and run `bundle`. Note, you can sustitute your preferable JavaScript engine.
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
gem "react_on_rails"
|
|
52
|
+
gem "therubyracer"
|
|
53
|
+
```
|
|
54
|
+
1. Globally expose React in your webpack config like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/webpack.client.base.config.js#L31):
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
module: {
|
|
58
|
+
loaders: [
|
|
59
|
+
// React is necessary for the client rendering:
|
|
60
|
+
{test: require.resolve('react'), loader: 'expose?React'},
|
|
61
|
+
```
|
|
62
|
+
1. Require `react_on_rails` in your `application.js` like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/361f4338ebb39a5d3934b00cb6d6fcf494773000/app/assets/javascripts/application.js#L15). It possibly should come after you require `turbolinks`:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
//= require react_on_rails
|
|
66
|
+
```
|
|
67
|
+
1. Expose your client globals like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/app/startup/clientGlobals.jsx#L3):
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
import App from './ClientApp';
|
|
71
|
+
window.App = App;
|
|
72
|
+
```
|
|
73
|
+
1. Put your client globals file as webpack entry points like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/webpack.client.rails.config.js#L22). Similar pattern for server rendering.
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
config.entry.app.push('./app/startup/clientGlobals');
|
|
77
|
+
```
|
|
78
|
+
1. See customization of configuration options below.
|
|
47
79
|
|
|
48
|
-
|
|
80
|
+
### Additional Steps For Server Rendering (option `prerender` shown below)
|
|
81
|
+
See the next section for a sample webpack.server.rails.config.js.
|
|
82
|
+
1. Expose your server globals like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/app/startup/serverGlobals.jsx#L7)
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
import App from './ServerApp';
|
|
86
|
+
global.App = App;
|
|
87
|
+
```
|
|
88
|
+
2. Make the server globals file an entry point in your webpack config, like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/webpack.server.rails.config.js#L7)
|
|
49
89
|
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
90
|
+
```javascript
|
|
91
|
+
entry: ['./app/startup/serverGlobals'],
|
|
92
|
+
```
|
|
93
|
+
3. Ensure the name of your ouput file (shown [here](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/webpack.server.rails.config.js#L9)) of your server bundle corresponds to the configuration of the gem. The default path is `app/assets/javascripts/generated`. See below for customization of configuration variables.
|
|
94
|
+
4. Expose `React` in your webpack config, like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/webpack.server.rails.config.js#L23)
|
|
54
95
|
|
|
55
|
-
|
|
96
|
+
#### Sample webpack.server.rails.config.js (ONLY for server rendering)
|
|
97
|
+
Be sure to check out the latest example version of [client/webpack.server.rails.config.js](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/webpack.server.rails.config.js).
|
|
56
98
|
|
|
57
|
-
|
|
99
|
+
```javascript
|
|
100
|
+
// Common webpack configuration for server bundle
|
|
101
|
+
|
|
102
|
+
module.exports = {
|
|
103
|
+
|
|
104
|
+
// the project dir
|
|
105
|
+
context: __dirname,
|
|
106
|
+
entry: ['./app/startup/serverGlobals'],
|
|
107
|
+
output: {
|
|
108
|
+
filename: 'server-bundle.js',
|
|
109
|
+
path: '../app/assets/javascripts/generated',
|
|
110
|
+
|
|
111
|
+
// CRITICAL to set libraryTarget: 'this' for enabling Rails to find the exposed modules IF you
|
|
112
|
+
// use the "expose" webpackfunctionality. See startup/serverGlobals.jsx.
|
|
113
|
+
// NOTE: This is NOT necessary if you use the syntax of global.MyComponent = MyComponent syntax.
|
|
114
|
+
// See http://webpack.github.io/docs/configuration.html#externals for documentation of this option
|
|
115
|
+
//libraryTarget: 'this',
|
|
116
|
+
},
|
|
117
|
+
resolve: {
|
|
118
|
+
extensions: ['', '.webpack.js', '.web.js', '.js', '.jsx', 'config.js'],
|
|
119
|
+
},
|
|
120
|
+
module: {
|
|
121
|
+
loaders: [
|
|
122
|
+
{test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/},
|
|
123
|
+
|
|
124
|
+
// React is necessary for the client rendering:
|
|
125
|
+
{ test: require.resolve('react'), loader: 'expose?React' },
|
|
126
|
+
{ test: require.resolve('react-dom/server'), loader: 'expose?ReactDOMServer' },
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
```
|
|
58
131
|
|
|
59
132
|
## What Happens?
|
|
60
133
|
|
|
@@ -100,8 +173,12 @@ Params are:
|
|
|
100
173
|
If you're curious as to what the gem generates for the server and client rendering, see [`spec/dummy/client/app/startup/serverGlobals.jsx`](https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/spec/sample_generated_js/server-generated.js)
|
|
101
174
|
and [`spec/dummy/client/app/startup/ClientReduxApp.jsx`](https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/spec/sample_generated_js/client-generated.js) for examples of this. Note, this is not the code that you are providing. You can see the client code by viewing the page source.
|
|
102
175
|
|
|
103
|
-
* **props**: [hash] Properties to pass to the react object
|
|
176
|
+
* **props**: [hash | string of json] Properties to pass to the react object. See this example if you're using Jbuilder: [react-webpack-rails-tutorial view rendering props using jBuilder](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/app/views/pages/index.html.erb#L20)
|
|
104
177
|
|
|
178
|
+
```erb
|
|
179
|
+
<%= react_component('App', render(template: "/comments/index.json.jbuilder"),
|
|
180
|
+
generator_function: true, prerender: true) %>
|
|
181
|
+
```
|
|
105
182
|
* **options:** [hash]
|
|
106
183
|
* **generator_function**: <true/false> default is false, set to true if you want to use a generator function rather than a React Component.
|
|
107
184
|
* **prerender**: <true/false> set to false when debugging!
|
|
@@ -238,81 +315,24 @@ gem "therubyracer"
|
|
|
238
315
|
* [Charlie Marsh's article "Rendering React Components on the Server"](http://www.crmarsh.com/react-ssr/)
|
|
239
316
|
* [Node globals](https://nodejs.org/api/globals.html#globals_global)
|
|
240
317
|
|
|
241
|
-
|
|
242
|
-
## Development Setup for Gem Contributors
|
|
243
|
-
|
|
244
|
-
### Initial Setup
|
|
245
|
-
After checking out the repo, making sure you have rvm and nvm setup (setup ruby and node),
|
|
246
|
-
cd to `spec/dummy` and run `bin/setup` to install dependencies.
|
|
247
|
-
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
248
|
-
|
|
249
|
-
### Starting the Dummy App
|
|
250
|
-
To run the test app, it's **CRITICAL** to not just run `rails s`. You have to run `foreman start`.
|
|
251
|
-
If you don't do this, then `webpack` will not generate a new bundle,
|
|
252
|
-
and you will be seriously confused when you change JavaScript and the app does not change.
|
|
253
|
-
|
|
254
|
-
### Install and Release
|
|
255
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version,
|
|
256
|
-
update the version number in `version.rb`, and then run `bundle exec rake release`,
|
|
257
|
-
which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
258
|
-
|
|
259
|
-
### RSpec Testing
|
|
260
|
-
Run `rake` for testing the gem and `spec/dummy`. Otherwise, the `rspec` command only works for testing within `spec/dummy`.
|
|
261
|
-
|
|
262
|
-
If you run `rspec` at the top level, you'll see this message: `require': cannot load such file -- rails_helper (LoadError)`
|
|
263
|
-
|
|
264
|
-
### Debugging
|
|
265
|
-
Start the sample app like this for some debug printing:
|
|
266
|
-
```bash
|
|
267
|
-
TRACE_REACT_ON_RAILS=true && foreman start
|
|
268
|
-
```
|
|
269
|
-
|
|
270
318
|
### Generated JavaScript
|
|
271
319
|
|
|
272
320
|
1. See spec/dummy/spec/sample_generated_js/server-generated.js to see the JavaScript for typical server rendering.
|
|
273
321
|
2. See spec/dummy/spec/sample_generated_js/client-generated.js to see the JavaScript for typical client rendering.
|
|
274
322
|
|
|
275
|
-
### Linting
|
|
276
|
-
All linting is performed from the docker container. You will need docker and docker-compose installed
|
|
277
|
-
locally to lint code changes via the lint container.
|
|
278
|
-
|
|
279
|
-
* [Install Docker Toolbox for Mac](https://www.docker.com/toolbox)
|
|
280
|
-
* [Install Docker Compose for Linux](https://docs.docker.com/compose/install/)
|
|
281
|
-
|
|
282
|
-
Once you have docker and docker-compose running locally, run `docker-compose build lint`. This will build
|
|
283
|
-
the `reactonrails_lint` docker image and docker-compose `lint` container. The inital build is slow,
|
|
284
|
-
but after the install, startup is very quick.
|
|
285
|
-
|
|
286
|
-
### Linting Commands
|
|
287
|
-
Run `rake -D docker` to see all docker linting commands for rake. `rake docker` will run all linters.
|
|
288
|
-
For individual rake linting commands please refer to `rake -D docker` for the list.
|
|
289
|
-
You can run specfic linting for directories or files by using `docker-compose run lint rubocop (file path or directory)`, etc.
|
|
290
|
-
`docker-compose run lint /bin/bash` sets you up to run from the container command line.
|
|
291
|
-
|
|
292
323
|
## Contributing
|
|
293
324
|
|
|
294
325
|
Bug reports and pull requests are welcome on GitHub at https://github.com/shakacode/react_on_rails. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
|
295
326
|
|
|
327
|
+
More [tips on contributing here](docs/Contributing.md)
|
|
328
|
+
|
|
296
329
|
## License
|
|
297
330
|
|
|
298
331
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
|
299
332
|
|
|
300
|
-
## Updating New Versions of the Gem
|
|
301
|
-
|
|
302
|
-
See https://github.com/svenfuchs/gem-release
|
|
303
|
-
|
|
304
|
-
```bash
|
|
305
|
-
gem bump
|
|
306
|
-
cd spec/dummy
|
|
307
|
-
bundle
|
|
308
|
-
git commit -am "Updated Gemfile.lock"
|
|
309
|
-
cd ../..
|
|
310
|
-
gem tag
|
|
311
|
-
gem release
|
|
312
|
-
```
|
|
313
|
-
|
|
314
333
|
# Authors
|
|
315
|
-
|
|
334
|
+
|
|
335
|
+
[The Shaka Code team!](http://www.shakacode.com/about/)
|
|
316
336
|
|
|
317
337
|
1. [Justin Gordon](https://github.com/justin808/)
|
|
318
338
|
2. [Samnang Chhun](https://github.com/samnang)
|
data/Rakefile
CHANGED
|
@@ -3,7 +3,7 @@ require "fileutils"
|
|
|
3
3
|
namespace :run_rspec do
|
|
4
4
|
desc "Run RSpec for top level only"
|
|
5
5
|
task :gem do
|
|
6
|
-
sh %( rspec
|
|
6
|
+
sh %( rspec spec/react_on_rails_spec.rb )
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
desc "Run RSpec for spec/dummy only"
|
|
@@ -11,7 +11,12 @@ namespace :run_rspec do
|
|
|
11
11
|
sh %( cd spec/dummy && rspec )
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
desc "Run RSpec for spec/dummy only"
|
|
15
|
+
task :dummy_react_013 do
|
|
16
|
+
sh %( cd spec/dummy-react-013 && rspec )
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
task run_rspec: [:gem, :dummy, :dummy_react_013] do
|
|
15
20
|
puts "Completed all RSpec tests"
|
|
16
21
|
end
|
|
17
22
|
end
|
|
@@ -43,13 +48,15 @@ namespace :lint do
|
|
|
43
48
|
|
|
44
49
|
desc "Run jscs from shell"
|
|
45
50
|
task :jscs do
|
|
46
|
-
sh "jscs -e ."
|
|
51
|
+
sh "jscs -e -v ."
|
|
47
52
|
end
|
|
48
53
|
|
|
49
|
-
|
|
54
|
+
desc "Run all eslint, jscs, rubocop linters. Skip ruby-lint and scss"
|
|
55
|
+
task lint: [:eslint, :jscs, :rubocop] do
|
|
50
56
|
puts "Completed all linting"
|
|
51
57
|
end
|
|
52
58
|
end
|
|
59
|
+
|
|
53
60
|
desc "Runs all linters. Run `rake -D lint` to see all available lint options"
|
|
54
61
|
task lint: ["lint:lint"]
|
|
55
62
|
|
|
@@ -86,3 +93,6 @@ end
|
|
|
86
93
|
|
|
87
94
|
desc "Runs all linters from docker. Run `rake -D docker` to see all available lint options"
|
|
88
95
|
task docker: ["docker:lint"]
|
|
96
|
+
|
|
97
|
+
desc "Run all tests and linting"
|
|
98
|
+
task ci: %w(docker run_rspec)
|
|
@@ -18,36 +18,42 @@
|
|
|
18
18
|
if (domNode) {
|
|
19
19
|
var reactElement = createReactElement(componentName, propsVarName, props,
|
|
20
20
|
domId, trace, generatorFunction);
|
|
21
|
-
|
|
21
|
+
provideClientReact().render(reactElement, domNode);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
catch (e) {
|
|
25
|
-
handleError(
|
|
25
|
+
ReactOnRails.handleError({
|
|
26
|
+
e: e,
|
|
27
|
+
componentName: componentName,
|
|
28
|
+
serverSide: false,
|
|
29
|
+
});
|
|
26
30
|
}
|
|
27
31
|
};
|
|
28
32
|
|
|
29
|
-
var turbolinksInstalled = typeof
|
|
33
|
+
var turbolinksInstalled = (typeof Turbolinks !== 'undefined');
|
|
30
34
|
if (!expectTurboLinks || (!turbolinksInstalled && expectTurboLinks)) {
|
|
31
35
|
if (expectTurboLinks) {
|
|
32
|
-
console.warn(
|
|
36
|
+
console.warn('WARNING: NO TurboLinks detected in JS, but it is in your Gemfile');
|
|
33
37
|
}
|
|
34
|
-
|
|
38
|
+
|
|
39
|
+
document.addEventListener('DOMContentLoaded', function(event) {
|
|
35
40
|
renderIfDomNodePresent();
|
|
36
41
|
});
|
|
37
42
|
} else {
|
|
38
43
|
function onPageChange(event) {
|
|
39
44
|
var removePageChangeListener = function() {
|
|
40
|
-
document.removeEventListener(
|
|
41
|
-
document.removeEventListener(
|
|
45
|
+
document.removeEventListener('page:change', onPageChange);
|
|
46
|
+
document.removeEventListener('page:before-unload', removePageChangeListener);
|
|
42
47
|
var domNode = document.getElementById(domId);
|
|
43
|
-
|
|
48
|
+
provideClientReact().unmountComponentAtNode(domNode);
|
|
44
49
|
};
|
|
45
|
-
|
|
50
|
+
|
|
51
|
+
document.addEventListener('page:before-unload', removePageChangeListener);
|
|
46
52
|
|
|
47
53
|
renderIfDomNodePresent();
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
document.addEventListener(
|
|
56
|
+
document.addEventListener('page:change', onPageChange);
|
|
51
57
|
}
|
|
52
58
|
};
|
|
53
59
|
|
|
@@ -65,31 +71,27 @@
|
|
|
65
71
|
try {
|
|
66
72
|
var reactElement = createReactElement(componentName, propsVarName, props,
|
|
67
73
|
domId, trace, generatorFunction);
|
|
68
|
-
htmlResult =
|
|
74
|
+
htmlResult = provideServerReact().renderToString(reactElement);
|
|
69
75
|
}
|
|
70
76
|
catch (e) {
|
|
71
|
-
htmlResult = handleError(
|
|
77
|
+
htmlResult = ReactOnRails.handleError({
|
|
78
|
+
e: e,
|
|
79
|
+
componentName: componentName,
|
|
80
|
+
serverSide: true,
|
|
81
|
+
});
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
consoleReplay = ReactOnRails.buildConsoleReplay();
|
|
75
85
|
return JSON.stringify([htmlResult, consoleReplay]);
|
|
76
86
|
};
|
|
77
87
|
|
|
78
|
-
function createReactElement(componentName, propsVarName, props, domId, trace, generatorFunction) {
|
|
79
|
-
if (trace) {
|
|
80
|
-
console.log('RENDERED ' + componentName + ' with data_variable ' +
|
|
81
|
-
propsVarName + ' to dom node with id: ' + domId);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (generatorFunction) {
|
|
85
|
-
return this[componentName](props);
|
|
86
|
-
} else {
|
|
87
|
-
return React.createElement(this[componentName], props);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
88
|
// Passing either componentName or jsCode
|
|
92
|
-
|
|
89
|
+
ReactOnRails.handleError = function(options) {
|
|
90
|
+
var e = options.e;
|
|
91
|
+
var componentName = options.componentName;
|
|
92
|
+
var jsCode = options.jsCode;
|
|
93
|
+
var serverSide = options.serverSide;
|
|
94
|
+
|
|
93
95
|
var lineOne =
|
|
94
96
|
'ERROR: You specified the option generator_function (could be in your defaults) to be\n';
|
|
95
97
|
var lastLine =
|
|
@@ -125,15 +127,17 @@
|
|
|
125
127
|
if (e.fileName) {
|
|
126
128
|
console.error('location: ' + e.fileName + ':' + e.lineNumber);
|
|
127
129
|
}
|
|
130
|
+
|
|
128
131
|
console.error('message: ' + e.message);
|
|
129
132
|
console.error('stack: ' + e.stack);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
if (serverSide) {
|
|
134
|
+
msg += 'Exception in rendering!\n' +
|
|
135
|
+
(e.fileName ? '\nlocation: ' + e.fileName + ':' + e.lineNumber : '') +
|
|
136
|
+
'\nMessage: ' + e.message + '\n\n' + e.stack;
|
|
137
|
+
var reactElement = React.createElement('pre', null, msg);
|
|
138
|
+
return provideServerReact().renderToString(reactElement);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
137
141
|
|
|
138
142
|
ReactOnRails.buildConsoleReplay = function() {
|
|
139
143
|
var consoleReplay = '';
|
|
@@ -145,9 +149,39 @@
|
|
|
145
149
|
consoleReplay += '\nconsole.' + msg.level + '.apply(console, ' +
|
|
146
150
|
JSON.stringify(msg.arguments) + ');';
|
|
147
151
|
});
|
|
152
|
+
|
|
148
153
|
consoleReplay += '\n</script>';
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
return consoleReplay;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
function createReactElement(componentName, propsVarName, props, domId, trace, generatorFunction) {
|
|
160
|
+
if (trace) {
|
|
161
|
+
console.log('RENDERED ' + componentName + ' with data_variable ' +
|
|
162
|
+
propsVarName + ' to dom node with id: ' + domId);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (generatorFunction) {
|
|
166
|
+
return this[componentName](props);
|
|
167
|
+
} else {
|
|
168
|
+
return React.createElement(this[componentName], props);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function provideClientReact() {
|
|
173
|
+
if (typeof ReactDOM === 'undefined') {
|
|
174
|
+
return React;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return ReactDOM;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function provideServerReact() {
|
|
181
|
+
if (typeof ReactDOMServer === 'undefined') {
|
|
182
|
+
return React;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return ReactDOMServer;
|
|
152
186
|
}
|
|
153
187
|
}.call(this));
|
|
@@ -53,7 +53,7 @@ module ReactOnRailsHelper
|
|
|
53
53
|
data_variable_name = "__#{component_name.camelize(:lower)}Data#{react_component_index}__"
|
|
54
54
|
turbolinks_loaded = Object.const_defined?(:Turbolinks)
|
|
55
55
|
# NOTE: props might include closing script tag that might cause XSS
|
|
56
|
-
props_string = props
|
|
56
|
+
props_string = sanitized_props_string(props)
|
|
57
57
|
page_loaded_js = <<-JS
|
|
58
58
|
(function() {
|
|
59
59
|
window.#{data_variable_name} = #{props_string};
|
|
@@ -89,10 +89,14 @@ module ReactOnRailsHelper
|
|
|
89
89
|
<<-HTML.html_safe
|
|
90
90
|
#{data_from_server_script_tag}
|
|
91
91
|
#{rendered_output}
|
|
92
|
-
#{replay_console(options) ? console_script :
|
|
92
|
+
#{replay_console(options) ? console_script : ''}
|
|
93
93
|
HTML
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
+
def sanitized_props_string(props)
|
|
97
|
+
props.is_a?(String) ? json_escape(props) : props.to_json
|
|
98
|
+
end
|
|
99
|
+
|
|
96
100
|
# Helper method to take javascript expression and returns the output from evaluating it.
|
|
97
101
|
# If you have more than one line that needs to be executed, wrap it in an IIFE.
|
|
98
102
|
# JS exceptions are caught and console messages are handled properly.
|
|
@@ -108,7 +112,8 @@ module ReactOnRailsHelper
|
|
|
108
112
|
return #{js_expression};
|
|
109
113
|
})();
|
|
110
114
|
} catch(e) {
|
|
111
|
-
htmlResult = handleError(e, null,
|
|
115
|
+
htmlResult = ReactOnRails.handleError({e: e, componentName: null,
|
|
116
|
+
jsCode: '#{escape_javascript(js_expression)}', serverSide: true});
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
consoleReplay = ReactOnRails.buildConsoleReplay();
|
|
@@ -117,7 +122,12 @@ module ReactOnRailsHelper
|
|
|
117
122
|
JS
|
|
118
123
|
|
|
119
124
|
result = ReactOnRails::ServerRenderingPool.server_render_js_with_console_logging(wrapper_js)
|
|
120
|
-
|
|
125
|
+
|
|
126
|
+
# IMPORTANT: Ensure that we mark string as html_safe to avoid escaping.
|
|
127
|
+
<<-HTML.html_safe
|
|
128
|
+
#{result[0]}
|
|
129
|
+
#{replay_console(options) ? result[1] : ''}
|
|
130
|
+
HTML
|
|
121
131
|
end
|
|
122
132
|
|
|
123
133
|
private
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Tips for Contributors
|
|
2
|
+
|
|
3
|
+
## Development Setup for Gem Contributors
|
|
4
|
+
|
|
5
|
+
### Checklist before Committing
|
|
6
|
+
1. `rake ci`: runs all linters and specs (you need Docker setup, see below)
|
|
7
|
+
2. Did you need any more tests for your change?
|
|
8
|
+
3. Did you document your change? Update the README.md?
|
|
9
|
+
|
|
10
|
+
### Initial Setup
|
|
11
|
+
After checking out the repo, making sure you have rvm and nvm setup (setup ruby and node),
|
|
12
|
+
cd to `spec/dummy` and run `bin/setup` to install dependencies.
|
|
13
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
14
|
+
|
|
15
|
+
### Starting the Dummy App
|
|
16
|
+
To run the test app, it's **CRITICAL** to not just run `rails s`. You have to run `foreman start`.
|
|
17
|
+
If you don't do this, then `webpack` will not generate a new bundle,
|
|
18
|
+
and you will be seriously confused when you change JavaScript and the app does not change.
|
|
19
|
+
|
|
20
|
+
### Install and Release
|
|
21
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version,
|
|
22
|
+
update the version number in `version.rb`, and then run `bundle exec rake release`,
|
|
23
|
+
which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
24
|
+
|
|
25
|
+
### RSpec Testing
|
|
26
|
+
Run `rake` for testing the gem and `spec/dummy` and `spec/dummy-react-013`. Otherwise, the `rspec` command only works for testing within the sample apps, like `spec/dummy`.
|
|
27
|
+
|
|
28
|
+
If you run `rspec` at the top level, you'll see this message: `require': cannot load such file -- rails_helper (LoadError)`
|
|
29
|
+
|
|
30
|
+
### Debugging
|
|
31
|
+
Start the sample app like this for some debug printing:
|
|
32
|
+
```bash
|
|
33
|
+
TRACE_REACT_ON_RAILS=true && foreman start
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Updating New Versions of the Gem
|
|
38
|
+
|
|
39
|
+
See https://github.com/svenfuchs/gem-release
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
gem bump
|
|
43
|
+
cd spec/dummy
|
|
44
|
+
bundle
|
|
45
|
+
git commit -am "Updated Gemfile.lock"
|
|
46
|
+
cd ../..
|
|
47
|
+
gem tag
|
|
48
|
+
gem release
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Linting
|
|
52
|
+
All linting is performed from the docker container. You will need docker and docker-compose installed
|
|
53
|
+
locally to lint code changes via the lint container.
|
|
54
|
+
|
|
55
|
+
* [Install Docker Toolbox for Mac](https://www.docker.com/toolbox)
|
|
56
|
+
* [Install Docker Compose for Linux](https://docs.docker.com/compose/install/)
|
|
57
|
+
|
|
58
|
+
Once you have docker and docker-compose running locally, run `docker-compose build lint`. This will build
|
|
59
|
+
the `reactonrails_lint` docker image and docker-compose `lint` container. The inital build is slow,
|
|
60
|
+
but after the install, startup is very quick.
|
|
61
|
+
|
|
62
|
+
### Linting Commands
|
|
63
|
+
Run `rake -D docker` to see all docker linting commands for rake. `rake docker` will run all linters.
|
|
64
|
+
For individual rake linting commands please refer to `rake -D docker` for the list.
|
|
65
|
+
You can run specfic linting for directories or files by using `docker-compose run lint rubocop (file path or directory)`, etc.
|
|
66
|
+
`docker-compose run lint /bin/bash` sets you up to run from the container command line.
|
data/docs/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
## PENDING: ADD DOCS HERE
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
window.__helloWorldData0__ = {"helloWorldData":{"name":"Mr. Server Side Rendering"}};
|
|
3
|
+
ReactOnRails.clientRenderReactComponent({
|
|
4
|
+
componentName: 'HelloWorld',
|
|
5
|
+
domId: 'HelloWorld-react-component-0',
|
|
6
|
+
propsVarName: '__helloWorldData0__',
|
|
7
|
+
props: window.__helloWorldData0__,
|
|
8
|
+
trace: true,
|
|
9
|
+
generatorFunction: false,
|
|
10
|
+
expectTurboLinks: true
|
|
11
|
+
});
|
|
12
|
+
})();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
var props = {"helloWorldData":{"name":"Mr. Server Side Rendering"}};
|
|
3
|
+
return ReactOnRails.serverRenderReactComponent({
|
|
4
|
+
componentName: 'HelloWorld',
|
|
5
|
+
domId: 'HelloWorld-react-component-0',
|
|
6
|
+
propsVarName: '__helloWorldData0__',
|
|
7
|
+
props: props,
|
|
8
|
+
trace: true,
|
|
9
|
+
generatorFunction: false
|
|
10
|
+
});
|
|
11
|
+
})();
|
|
@@ -1,62 +1,20 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "connection_pool"
|
|
2
2
|
|
|
3
|
-
# Based on the react-rails gem
|
|
3
|
+
# Based on the react-rails gem.
|
|
4
|
+
# None of these methods should be called directly.
|
|
5
|
+
# See app/helpers/react_on_rails_helper.rb
|
|
4
6
|
module ReactOnRails
|
|
5
7
|
class ServerRenderingPool
|
|
6
8
|
def self.reset_pool
|
|
7
9
|
options = { size: ReactOnRails.configuration.server_renderer_pool_size,
|
|
8
10
|
timeout: ReactOnRails.configuration.server_renderer_pool_size }
|
|
9
|
-
|
|
11
|
+
@js_context_pool = ConnectionPool.new(options) { create_js_context }
|
|
10
12
|
end
|
|
11
13
|
|
|
12
|
-
def self.eval_js(js_code)
|
|
13
|
-
@@js_context_pool.with do |js_context|
|
|
14
|
-
result = js_context.eval(js_code)
|
|
15
|
-
js_context.eval(CLEAR_CONSOLE)
|
|
16
|
-
result
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def self.create_js_context
|
|
21
|
-
server_js_file = ReactOnRails.configuration.server_bundle_js_file
|
|
22
|
-
if server_js_file.present? && File.exist?(server_js_file)
|
|
23
|
-
bundle_js_code = File.read(server_js_file)
|
|
24
|
-
base_js_code = <<-JS
|
|
25
|
-
#{CONSOLE_POLYFILL}
|
|
26
|
-
#{bundle_js_code};
|
|
27
|
-
#{::Rails.application.assets['react_on_rails.js'].to_s};
|
|
28
|
-
JS
|
|
29
|
-
ExecJS.compile(base_js_code)
|
|
30
|
-
else
|
|
31
|
-
if server_js_file.present?
|
|
32
|
-
Rails.logger.warn("You specified server rendering JS file: #{server_js_file}, but it cannot be read.")
|
|
33
|
-
end
|
|
34
|
-
ExecJS.compile("")
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
CLEAR_CONSOLE = <<-JS
|
|
39
|
-
console.history = []
|
|
40
|
-
JS
|
|
41
|
-
|
|
42
|
-
# Reimplement console methods for replaying on the client
|
|
43
|
-
CONSOLE_POLYFILL = <<-JS
|
|
44
|
-
var console = { history: [] };
|
|
45
|
-
['error', 'log', 'info', 'warn'].forEach(function (level) {
|
|
46
|
-
console[level] = function () {
|
|
47
|
-
var argArray = Array.prototype.slice.call(arguments);
|
|
48
|
-
if (argArray.length > 0) {
|
|
49
|
-
argArray[0] = '[SERVER] ' + argArray[0];
|
|
50
|
-
}
|
|
51
|
-
console.history.push({level: level, arguments: argArray});
|
|
52
|
-
};
|
|
53
|
-
});
|
|
54
|
-
JS
|
|
55
|
-
|
|
56
14
|
class PrerenderError < RuntimeError
|
|
57
15
|
def initialize(component_name, props, js_message)
|
|
58
16
|
message = ["Encountered error \"#{js_message}\" when prerendering #{component_name} with #{props}",
|
|
59
|
-
|
|
17
|
+
js_message.backtrace.join("\n")].join("\n")
|
|
60
18
|
super(message)
|
|
61
19
|
end
|
|
62
20
|
end
|
|
@@ -69,13 +27,7 @@ var console = { history: [] };
|
|
|
69
27
|
# js_code MUST RETURN json stringify array of two elements
|
|
70
28
|
# Calling code will probably call 'html_safe' on return value before rendering to the view.
|
|
71
29
|
def self.server_render_js_with_console_logging(js_code)
|
|
72
|
-
|
|
73
|
-
puts "Z" * 80
|
|
74
|
-
puts "react_renderer.rb: 92"
|
|
75
|
-
puts "wrote file tmp/server-generated.js"
|
|
76
|
-
File.write("tmp/server-generated.js", js_code)
|
|
77
|
-
puts "Z" * 80
|
|
78
|
-
end
|
|
30
|
+
trace_messsage(js_code)
|
|
79
31
|
|
|
80
32
|
json_string = eval_js(js_code)
|
|
81
33
|
# element 0 is the html, element 1 is the script tag for the server console output
|
|
@@ -89,13 +41,67 @@ var console = { history: [] };
|
|
|
89
41
|
if console_script_lines
|
|
90
42
|
console_script_lines.each do |line|
|
|
91
43
|
match = re.match(line)
|
|
92
|
-
if match
|
|
93
|
-
Rails.logger.info { "[react_on_rails] #{match[:msg]}" }
|
|
94
|
-
end
|
|
44
|
+
Rails.logger.info { "[react_on_rails] #{match[:msg]}" } if match
|
|
95
45
|
end
|
|
96
46
|
end
|
|
97
47
|
end
|
|
98
48
|
result
|
|
99
49
|
end
|
|
50
|
+
|
|
51
|
+
class << self
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def trace_messsage(js_code)
|
|
55
|
+
return unless ENV["TRACE_REACT_ON_RAILS"].present?
|
|
56
|
+
# Set to anything to print generated code.
|
|
57
|
+
puts "Z" * 80
|
|
58
|
+
puts "react_renderer.rb: 92"
|
|
59
|
+
puts "wrote file tmp/server-generated.js"
|
|
60
|
+
File.write("tmp/server-generated.js", js_code)
|
|
61
|
+
puts "Z" * 80
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def eval_js(js_code)
|
|
65
|
+
@js_context_pool.with do |js_context|
|
|
66
|
+
result = js_context.eval(js_code)
|
|
67
|
+
js_context.eval("console.history = []")
|
|
68
|
+
result
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def create_js_context
|
|
73
|
+
server_js_file = ReactOnRails.configuration.server_bundle_js_file
|
|
74
|
+
if server_js_file.present? && File.exist?(server_js_file)
|
|
75
|
+
bundle_js_code = File.read(server_js_file)
|
|
76
|
+
base_js_code = <<-JS
|
|
77
|
+
#{console_polyfill}
|
|
78
|
+
#{bundle_js_code};
|
|
79
|
+
#{::Rails.application.assets['react_on_rails.js']};
|
|
80
|
+
JS
|
|
81
|
+
ExecJS.compile(base_js_code)
|
|
82
|
+
else
|
|
83
|
+
if server_js_file.present?
|
|
84
|
+
Rails.logger.warn("You specified server rendering JS file: #{server_js_file}, but it cannot be read.")
|
|
85
|
+
end
|
|
86
|
+
ExecJS.compile("")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Reimplement console methods for replaying on the client
|
|
91
|
+
def console_polyfill
|
|
92
|
+
<<-JS
|
|
93
|
+
var console = { history: [] };
|
|
94
|
+
['error', 'log', 'info', 'warn'].forEach(function (level) {
|
|
95
|
+
console[level] = function () {
|
|
96
|
+
var argArray = Array.prototype.slice.call(arguments);
|
|
97
|
+
if (argArray.length > 0) {
|
|
98
|
+
argArray[0] = '[SERVER] ' + argArray[0];
|
|
99
|
+
}
|
|
100
|
+
console.history.push({level: level, arguments: argArray});
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
JS
|
|
104
|
+
end
|
|
105
|
+
end
|
|
100
106
|
end
|
|
101
107
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: react_on_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0.pre
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Gordon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-10-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -148,6 +148,10 @@ files:
|
|
|
148
148
|
- app/assets/javascripts/react_on_rails.js
|
|
149
149
|
- app/helpers/react_on_rails_helper.rb
|
|
150
150
|
- docker-compose.yml
|
|
151
|
+
- docs/Contributing.md
|
|
152
|
+
- docs/README.md
|
|
153
|
+
- docs/sample_generated_js/client-generated.js
|
|
154
|
+
- docs/sample_generated_js/server-generated.js
|
|
151
155
|
- lib/react_on_rails.rb
|
|
152
156
|
- lib/react_on_rails/configuration.rb
|
|
153
157
|
- lib/react_on_rails/server_rendering_pool.rb
|
|
@@ -169,9 +173,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
169
173
|
version: '0'
|
|
170
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
175
|
requirements:
|
|
172
|
-
- - "
|
|
176
|
+
- - ">"
|
|
173
177
|
- !ruby/object:Gem::Version
|
|
174
|
-
version:
|
|
178
|
+
version: 1.3.1
|
|
175
179
|
requirements: []
|
|
176
180
|
rubyforge_project:
|
|
177
181
|
rubygems_version: 2.4.8
|