react_on_rails 1.0.0.pre → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.dockerignore +2 -0
- data/.eslintignore +2 -0
- data/.eslintrc +1 -0
- data/.gitignore +4 -0
- data/.jscsrc +2 -2
- data/.rubocop.yml +2 -0
- data/.scss-lint.yml +3 -3
- data/.travis.yml +31 -18
- data/Dockerfile_ci +12 -0
- data/Dockerfile_tests +12 -0
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +170 -290
- data/Rakefile +20 -7
- data/app/helpers/react_on_rails_helper.rb +5 -5
- data/docker-compose.yml +12 -0
- data/docs/Contributing.md +26 -2
- data/docs/gen-notes/react_syntax.md +3 -0
- data/docs/gen-notes/reducers.md +31 -0
- data/docs/generator_testing_script.md +50 -0
- data/docs/linters.md +8 -0
- data/docs/manual_configuration.md +202 -0
- data/docs/node_dependencies_and_npm.md +29 -0
- data/lib/generators/react_on_rails/base_generator.rb +116 -0
- data/lib/generators/react_on_rails/bootstrap_generator.rb +84 -0
- data/lib/generators/react_on_rails/generator_helper.rb +48 -0
- data/lib/generators/react_on_rails/heroku_deployment_generator.rb +22 -0
- data/lib/generators/react_on_rails/install_generator.rb +86 -0
- data/lib/generators/react_on_rails/linters_generator.rb +38 -0
- data/lib/generators/react_on_rails/react_no_redux_generator.rb +37 -0
- data/lib/generators/react_on_rails/react_with_redux_generator.rb +61 -0
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev.tt +4 -0
- data/lib/generators/react_on_rails/templates/base/base/REACT_ON_RAILS.md +16 -0
- data/lib/generators/react_on_rails/templates/base/base/app/controllers/hello_world_controller.rb +5 -0
- data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +6 -0
- data/lib/generators/react_on_rails/templates/base/base/client/.babelrc +3 -0
- data/lib/generators/react_on_rails/templates/base/base/client/REACT_ON_RAILS_CLIENT_README.md +3 -0
- data/lib/generators/react_on_rails/templates/base/base/client/app/bundles/HelloWorld/startup/clientGlobals.jsx +4 -0
- data/lib/generators/react_on_rails/templates/base/base/client/index.jade +15 -0
- data/lib/generators/react_on_rails/templates/base/base/client/npm-shrinkwrap.json +2907 -0
- data/lib/generators/react_on_rails/templates/base/base/client/server.js +58 -0
- data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.base.config.js +58 -0
- data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.hot.config.js +65 -0
- data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.rails.config.js +45 -0
- data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +30 -0
- data/lib/generators/react_on_rails/templates/base/base/lib/tasks/assets.rake +26 -0
- data/lib/generators/react_on_rails/templates/base/base/package.json +31 -0
- data/lib/generators/react_on_rails/templates/base/server_rendering/client/app/bundles/HelloWorld/startup/serverGlobals.jsx +3 -0
- data/lib/generators/react_on_rails/templates/base/server_rendering/client/webpack.server.rails.config.js +37 -0
- data/lib/generators/react_on_rails/templates/bootstrap/app/assets/stylesheets/_bootstrap-custom.scss +63 -0
- data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_post-bootstrap.scss +10 -0
- data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_pre-bootstrap.scss +8 -0
- data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_react-on-rails-sass-helper.scss +19 -0
- data/lib/generators/react_on_rails/templates/bootstrap/client/bootstrap-sass.config.js +89 -0
- data/lib/generators/react_on_rails/templates/client/README.md +97 -0
- data/lib/generators/react_on_rails/templates/heroku_deployment/.buildpacks +2 -0
- data/lib/generators/react_on_rails/templates/heroku_deployment/Procfile +1 -0
- data/lib/generators/react_on_rails/templates/linters/client/.eslintignore +1 -0
- data/lib/generators/react_on_rails/templates/linters/client/.eslintrc +17 -0
- data/lib/generators/react_on_rails/templates/linters/client/.jscsrc +7 -0
- data/lib/generators/react_on_rails/templates/linters/lib/tasks/brakeman.rake +17 -0
- data/lib/generators/react_on_rails/templates/linters/lib/tasks/ci.rake +33 -0
- data/lib/generators/react_on_rails/templates/linters/lib/tasks/linters.rake +81 -0
- data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +39 -0
- data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +33 -0
- data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx +11 -0
- data/lib/generators/react_on_rails/templates/no_redux/base/client/package.json.tt +75 -0
- data/lib/generators/react_on_rails/templates/no_redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +11 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/actions/helloWorldActionCreators.jsx +8 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +48 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/constants/helloWorldConstants.jsx +8 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +43 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx +21 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/index.jsx +14 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx +20 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/store/helloWorldStore.jsx +35 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/app/lib/middlewares/loggerMiddleware.js +25 -0
- data/lib/generators/react_on_rails/templates/redux/base/client/package.json.tt +82 -0
- data/lib/generators/react_on_rails/templates/redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +21 -0
- data/lib/react_on_rails.rb +1 -7
- data/lib/react_on_rails/configuration.rb +14 -5
- data/lib/react_on_rails/engine.rb +7 -0
- data/lib/react_on_rails/server_rendering_pool.rb +14 -1
- data/lib/react_on_rails/version.rb +1 -1
- data/react_on_rails.gemspec +2 -2
- data/ruby-lint.yml +1 -0
- metadata +75 -11
- data/Dockerfile +0 -14
- data/docs/README.md +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fde8cbadfff66bb7793dbc144644d60d46d4803
|
4
|
+
data.tar.gz: 29f6b282949c98382a6821d7b56a987ede72f80c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41b6e18bc73f593867cf322feb405d8c1eb77ccf2063860aac2d519cefc8994708cf838b783fca3b8056cb509bc2e1253d4a7da30874d193271d978d3724b110
|
7
|
+
data.tar.gz: 179393aadd9f9d2b1431eb7b21cc436f9e036fe504b25901dd0a69002725032f12daaedaee0e64f3ae05c2d04ef3a412bc05a0ba8b8d72c20aa5f735407eecb8
|
data/.dockerignore
ADDED
data/.eslintignore
CHANGED
data/.eslintrc
CHANGED
data/.gitignore
CHANGED
@@ -8,11 +8,15 @@
|
|
8
8
|
/spec/reports/
|
9
9
|
/tmp/
|
10
10
|
*.gem
|
11
|
+
/vendor/
|
11
12
|
|
12
13
|
/spec/dummy/client/node_modules
|
13
14
|
/spec/dummy/app/assets/javascripts/generated/
|
14
15
|
/spec/dummy-react-013/client/node_modules
|
15
16
|
/spec/dummy-react-013/app/assets/javascripts/generated/
|
17
|
+
/spec/dummy-react-013/coverage/
|
18
|
+
/spec/dummy/coverage/
|
19
|
+
/spec/react_on_rails/dummy-for-generators/
|
16
20
|
|
17
21
|
# RVM
|
18
22
|
.ruby-version
|
data/.jscsrc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"preset": "airbnb",
|
3
3
|
"fileExtensions": [".js", ".jsx"],
|
4
|
-
"excludeFiles": ["**/build/**", "**/node_modules/**", "**/generated/**", "**/docs/**", "**/tmp/**", "**/sample_generated/**"],
|
5
|
-
"requireTrailingComma": { ignoreSingleValue: true, ignoreSingleLine: true },
|
4
|
+
"excludeFiles": ["**/build/**", "**/node_modules/**", "**/generated/**", "**/docs/**", "**/tmp/**", "**/sample_generated/**", "**/coverage/**", "**/vendor/**", "**/dummy-for-generators/**"],
|
5
|
+
"requireTrailingComma": { "ignoreSingleValue": true, "ignoreSingleLine": true },
|
6
6
|
"validateQuoteMarks": false
|
7
7
|
}
|
data/.rubocop.yml
CHANGED
@@ -9,12 +9,14 @@ AllCops:
|
|
9
9
|
- 'vendor/**/*'
|
10
10
|
- 'spec/fixtures/**/*'
|
11
11
|
- 'node_modules/**/*'
|
12
|
+
- 'coverage/**/*'
|
12
13
|
- 'db/**/*'
|
13
14
|
- 'db/schema.rb'
|
14
15
|
- 'db/seeds.rb'
|
15
16
|
- 'client/node_modules/**/*'
|
16
17
|
- 'bin/**/*'
|
17
18
|
- !ruby/regexp /old_and_unused\.rb$/
|
19
|
+
- 'spec/react_on_rails/dummy-for-generators/**/*'
|
18
20
|
|
19
21
|
Metrics/LineLength:
|
20
22
|
Max: 120
|
data/.scss-lint.yml
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# See http://sass-guidelin.es/#zeros
|
2
2
|
|
3
3
|
scss_files:
|
4
|
-
- 'app/assets/stylesheets/**/*.scss'
|
5
|
-
|
6
|
-
|
4
|
+
- 'spec/dummy/app/assets/stylesheets/**/*.scss'
|
5
|
+
exclude:
|
6
|
+
- 'spec/dummy/app/assets/stylesheets/application.css'
|
7
7
|
linters:
|
8
8
|
# BangFormat:
|
9
9
|
# enabled: true
|
data/.travis.yml
CHANGED
@@ -1,33 +1,46 @@
|
|
1
|
+
sudo: required
|
2
|
+
|
1
3
|
language: ruby
|
4
|
+
|
2
5
|
rvm:
|
3
|
-
- 2.2.
|
6
|
+
- 2.2.3
|
7
|
+
|
8
|
+
services:
|
9
|
+
- docker
|
4
10
|
|
5
11
|
gemfile:
|
6
|
-
- spec/dummy/Gemfile
|
12
|
+
- spec/dummy/Gemfile
|
7
13
|
|
8
14
|
env:
|
9
|
-
|
15
|
+
- export RAILS_ENV=test
|
16
|
+
|
17
|
+
before_install:
|
18
|
+
- sudo apt-get update
|
19
|
+
- curl -L https://github.com/docker/compose/releases/download/1.4.0/docker-compose-`uname -s`-`uname -m` > docker-compose
|
20
|
+
- chmod +x docker-compose
|
21
|
+
- sudo mv docker-compose /usr/local/bin
|
22
|
+
- sudo apt-get install -y xvfb
|
10
23
|
|
11
24
|
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
|
25
|
+
- 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
|
26
|
+
- npm install -g npm
|
27
|
+
- bundle install
|
28
|
+
- cd spec/dummy/client && npm install
|
29
|
+
- $(npm bin)/webpack --config webpack.server.js
|
30
|
+
- $(npm bin)/webpack --config webpack.client.js
|
31
|
+
- cd ../../dummy-react-013/client && npm install
|
32
|
+
- $(npm bin)/webpack --config webpack.server.js
|
33
|
+
- $(npm bin)/webpack --config webpack.client.js
|
34
|
+
- cd ../../../
|
35
|
+
- docker-compose up lint
|
21
36
|
|
22
37
|
before_script:
|
23
|
-
-
|
24
|
-
-
|
25
|
-
- sh -e /etc/init.d/xvfb start
|
38
|
+
- "export DISPLAY=:99"
|
39
|
+
- Xvfb :99 -ac -screen scn 1600x1200x16 &
|
26
40
|
|
27
41
|
script:
|
28
|
-
- rake
|
29
|
-
-
|
30
|
-
- DRIVER=selenium_firefox rake run_rspec:dummy_react_013
|
42
|
+
- rake
|
43
|
+
- rake docker:lint
|
31
44
|
|
32
45
|
notifications:
|
33
46
|
slack:
|
data/Dockerfile_ci
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
FROM dylangrafmyre/docker-ci
|
2
|
+
|
3
|
+
WORKDIR /app/
|
4
|
+
|
5
|
+
COPY ["/lib/react_on_rails/version.rb", "/app/lib/react_on_rails/"]
|
6
|
+
COPY ["Gemfile", "Gemfile.lock", "react_on_rails.gemspec", "/app/"]
|
7
|
+
COPY ["/spec/dummy/Gemfile", "/spec/dummy/Gemfile.lock", "/app/spec/dummy/"]
|
8
|
+
RUN bundle install --gemfile=spec/dummy/Gemfile
|
9
|
+
|
10
|
+
ENV DISPLAY :99
|
11
|
+
ENTRYPOINT service xvfd start \
|
12
|
+
&& rake ci
|
data/Dockerfile_tests
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
FROM dylangrafmyre/docker-ci
|
2
|
+
|
3
|
+
WORKDIR /app/
|
4
|
+
|
5
|
+
COPY ["/lib/react_on_rails/version.rb", "/app/lib/react_on_rails/"]
|
6
|
+
COPY ["Gemfile", "Gemfile.lock", "react_on_rails.gemspec", "/app/"]
|
7
|
+
COPY ["/spec/dummy/Gemfile", "/spec/dummy/Gemfile.lock", "/app/spec/dummy/"]
|
8
|
+
RUN bundle install --gemfile=spec/dummy/Gemfile
|
9
|
+
|
10
|
+
ENV DISPLAY :99
|
11
|
+
ENTRYPOINT service xvfd start \
|
12
|
+
&& rake
|
data/{LICENSE.txt → LICENSE}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -1,341 +1,221 @@
|
|
1
|
-
[![Build Status](https://travis-ci.org/shakacode/react_on_rails.svg?branch=master)](https://travis-ci.org/shakacode/react_on_rails)
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
depend on jquery.
|
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.
|
1
|
+
[![Build Status](https://travis-ci.org/shakacode/react_on_rails.svg?branch=master)](https://travis-ci.org/shakacode/react_on_rails) [![Coverage Status](https://coveralls.io/repos/shakacode/react_on_rails/badge.svg?branch=master&service=github)](https://coveralls.io/github/shakacode/react_on_rails?branch=master) [![Dependency Status](https://gemnasium.com/shakacode/react_on_rails.svg)](https://gemnasium.com/shakacode/react_on_rails) [![Gem Version](https://badge.fury.io/rb/react_on_rails.svg)](https://badge.fury.io/rb/react_on_rails)
|
2
|
+
|
3
|
+
# React on Rails
|
4
|
+
React on Rails integrates Facebook's [React](https://github.com/facebook/react) front-end framework with Rails. Currently, both React v0.14 and v0.13 are supported. See the Rails on Maui [blog post](http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/) that started it all!
|
5
|
+
|
6
|
+
Like the [react-rails](https://github.com/reactjs/react-rails) gem, React on Rails is capable of server-side rendering with fragment caching and is compatible with [turbolinks](https://github.com/rails/turbolinks). Unlike react-rails, which depends heavily on sprockets and jquery-ujs, React on Rails uses [webpack](http://webpack.github.io/) and does not depend on jQuery. While the initial setup is slightly more involved, it allows for advanced functionality such as:
|
7
|
+
|
8
|
+
+ [Redux](https://github.com/rackt/redux)
|
9
|
+
+ [Webpack dev server](https://webpack.github.io/docs/webpack-dev-server.html) with [hot module replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html)
|
10
|
+
+ [Webpack optimization functionality](https://github.com/webpack/docs/wiki/optimization)
|
11
|
+
+ **(Coming Soon)** [React Router](https://github.com/rackt/react-router)
|
12
|
+
|
13
|
+
See the [react-webpack-rails-tutorial](https://github.com/justin808/react-webpack-rails-tutorial/) for an example of a live implementation and code.
|
14
|
+
|
15
|
+
### Including your React Component in your Rails Views
|
16
|
+
Please see [Getting Started](#getting-started) for how to set up your Rails project for React on Rails if you have not already done so.
|
17
|
+
|
18
|
+
+ *Normal Mode (JavaScript is rendered on client):*
|
19
|
+
|
20
|
+
```erb
|
21
|
+
<%= react_component("HelloWorldApp", @some_props) %>
|
22
|
+
```
|
23
|
+
+ *Server-Side Rendering:*
|
24
|
+
|
25
|
+
```erb
|
26
|
+
<%= react_component("HelloWorldApp", @some_props, prerender: true) %>
|
27
|
+
```
|
28
|
+
|
29
|
+
+ The `component_name` parameter here would be a string matching the name you used when globally exposing your React component.
|
30
|
+
+ `@some_props` can be either a hash or JSON string or {} if you have no props. This will make the data available in your component:
|
31
|
+
|
32
|
+
```javascript
|
33
|
+
this.props.name
|
34
|
+
```
|
35
|
+
|
36
|
+
### Client-Side Rendering vs. Server-Side Rendering
|
37
|
+
In most cases, you should use the provided helper method to render the React component from your Rails views with `prerender: false` (default behavior). In some cases, such as when SEO is vital or many users will not have JavaScript enabled, you can pass the `--server-rendering` option to the generator to configure your application for server-side rendering. Your JavaScript can then be first rendered on the server and passed to the client as HTML.
|
38
|
+
|
39
|
+
In the following screenshot you can see the actual HTML rendered for a side-by-side comparison of a React component left as JavaScript for the client to render followed by the same component rendered on the server to HTML along with any console error messages generated:
|
40
|
+
|
41
|
+
![Comparison of a normal React Component with its server-rendered version](https://cloud.githubusercontent.com/assets/1118459/10157268/41435186-6624-11e5-9341-6fc4cf35ee90.png)
|
42
|
+
|
43
|
+
## Getting Started
|
44
|
+
1. Add the following to your Gemfile and bundle install:
|
49
45
|
|
50
46
|
```ruby
|
51
47
|
gem "react_on_rails"
|
52
48
|
gem "therubyracer"
|
53
49
|
```
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
50
|
+
|
51
|
+
2. Run the generator with a simple "Hello World" example:
|
52
|
+
|
53
|
+
```bash
|
54
|
+
rails generate react_on_rails:install
|
66
55
|
```
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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');
|
56
|
+
|
57
|
+
3. NPM install:
|
58
|
+
|
59
|
+
```bash
|
60
|
+
npm install
|
77
61
|
```
|
78
|
-
1. See customization of configuration options below.
|
79
62
|
|
80
|
-
|
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)
|
89
|
-
|
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)
|
95
|
-
|
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).
|
98
|
-
|
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
|
-
```
|
63
|
+
4. Start your Rails server:
|
131
64
|
|
132
|
-
|
65
|
+
```bash
|
66
|
+
foreman start -f Procfile.dev
|
67
|
+
```
|
133
68
|
|
134
|
-
|
135
|
-
![2015-09-28_20-24-35](https://cloud.githubusercontent.com/assets/1118459/10157268/41435186-6624-11e5-9341-6fc4cf35ee90.png)
|
69
|
+
5. Visit [localhost:3000/hello_world](http://localhost:3000/hello_world)
|
136
70
|
|
137
|
-
##
|
71
|
+
## How it Works
|
72
|
+
The generator installs your webpack files in the `client` folder. Foreman uses webpack to compile your code and output the bundled results to `app/assets/javascripts/generated`, which are then loaded by sprockets. These generated bundle files have been added to your `.gitignore` for your convenience.
|
138
73
|
|
139
|
-
|
74
|
+
Inside your Rails views, you can now use the `react_component` helper method provided by React on Rails.
|
140
75
|
|
141
|
-
###
|
142
|
-
The
|
76
|
+
### Building the Bundles
|
77
|
+
Each time you change your client code, you will need to re-generate the bundles. The included Foreman `Procfile.dev` will take care of this for you by watching your JavaScript code files for changes. Simply run `foreman start -f Procfile.dev`.
|
143
78
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
Params are:
|
79
|
+
### Globally Exposing Your React Components
|
80
|
+
Place your JavaScript code inside of the provided `client/app` folder. Use modules just as you would when using webpack alone. The difference here is that instead of mounting React components directly to an element using `React.render`, you **expose your components globally and then mount them with helpers inside of your Rails views**.
|
81
|
+
|
82
|
+
+ *Normal Mode (JavaScript is Rendered on client):*
|
149
83
|
|
150
|
-
* **react_component_name**: [string] can be a React component, created using a ES6 class, or React.createClass,
|
151
|
-
or a `generator function` that returns a React component
|
152
|
-
|
153
|
-
using ES6
|
154
84
|
```javascript
|
155
|
-
|
156
|
-
```
|
157
|
-
|
158
|
-
|
85
|
+
window.HelloWorld = HelloWorldAppClient;
|
86
|
+
```
|
87
|
+
+ *Server-Side Rendering:*
|
88
|
+
|
159
89
|
```javascript
|
160
|
-
|
90
|
+
global.HelloWorld = HelloWorldAppServer;
|
161
91
|
```
|
162
|
-
Exposing the react_component_name is necessary to both a plain ReactComponent as well as
|
163
|
-
a generator:
|
164
|
-
For client rendering, expose the react_component_name on window:
|
165
92
|
|
166
|
-
```javascript
|
167
|
-
window.MyReactComponentApp = MyReactComponentApp;
|
168
|
-
```
|
169
|
-
For server rendering, export the react_component_name on global:
|
170
|
-
```javascript
|
171
|
-
global.MyReactComponentApp = MyReactComponentApp;
|
172
|
-
```
|
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)
|
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.
|
175
|
-
|
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)
|
177
93
|
|
178
|
-
|
179
|
-
|
180
|
-
|
94
|
+
## Generator Options
|
95
|
+
Run `rails generate react_on_rails:install --help` for descriptions of all available options:
|
96
|
+
|
181
97
|
```
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
```
|
199
|
-
3. Follow the examples in `spec/dummy/client/app/startup/serverGlobals.jsx` to expose your react components
|
200
|
-
for server side rendering.
|
201
|
-
```ruby
|
202
|
-
import HelloWorld from '../components/HelloWorld';
|
203
|
-
global.HelloWorld = HelloWorld;
|
204
|
-
```
|
205
|
-
|
206
|
-
## Server Rendering Tips
|
207
|
-
|
208
|
-
- Your code can't reference `document`. Server side JS execution does not have access to `document`, so jQuery and some
|
209
|
-
other libs won't work in this environment. You can debug this by putting in `console.log`
|
210
|
-
statements in your code.
|
211
|
-
- You can conditionally avoid running code that references document by passing in a boolean prop to your top level react
|
212
|
-
component. Since the passed in props Hash from the view helper applies to client and server side code, the best way to
|
213
|
-
do this is to use a generator function.
|
214
|
-
|
215
|
-
You might do something like this in some file for your top level component:
|
216
|
-
```javascript
|
217
|
-
global.App = () => <MyComponent serverSide={true} />;
|
98
|
+
Usage:
|
99
|
+
rails generate react_on_rails:install [options]
|
100
|
+
|
101
|
+
Options:
|
102
|
+
-R, [--redux], [--no-redux] # Setup Redux files
|
103
|
+
-S, [--server-rendering], [--no-server-rendering] # Configure for server-side rendering of webpack JavaScript
|
104
|
+
-L, [--skip-linters], [--no-skip-linters] # Don't install linter files
|
105
|
+
|
106
|
+
Runtime options:
|
107
|
+
-f, [--force] # Overwrite files that already exist
|
108
|
+
-p, [--pretend], [--no-pretend] # Run but do not make any changes
|
109
|
+
-q, [--quiet], [--no-quiet] # Suppress status output
|
110
|
+
-s, [--skip], [--no-skip] # Skip files that already exist
|
111
|
+
|
112
|
+
Description:
|
113
|
+
Create react on rails files for install generator.
|
218
114
|
```
|
219
115
|
|
220
|
-
|
116
|
+
We have a repo showing the results of running the generator with various combinations of options, each combination on its own branch: [Generator Results](https://github.com/shakacode/react_on_rails-generator-results-pre-0/pulls).
|
221
117
|
|
222
|
-
|
118
|
+
### Understanding the Organization of the Generated Client Code
|
119
|
+
The generated client code follows our organization scheme. Each unique set of functionality, is given its own folder inside of `client/app/bundles`. This encourages for modularity of DOMAINS.
|
223
120
|
|
224
|
-
|
225
|
-
the default options are below.
|
121
|
+
Inside of the generated "HelloWorld" domain you will find the following folders:
|
226
122
|
|
227
|
-
|
123
|
+
+ `startup`: two types of files, one that return a container component and implement any code that differs between client and server code (if using server-rendering), and a `clientGlobals` file that exposes the aforementioned files (as well as a `serverGlobals` file if using server rendering). These globals files are what webpack is using as an entry point.
|
124
|
+
+ `containers`: "smart components" (components that have functionality and logic that is passed to child "dumb components").
|
125
|
+
+ `components`: includes "dumb components", or components that simply render their properties and call functions given to them as properties by a parent component. Ultimately, at least one of these dumb components will have a parent container component.
|
228
126
|
|
229
|
-
|
230
|
-
# Shown below are the defaults for configuration
|
231
|
-
ReactOnRails.configure do |config|
|
232
|
-
# Client bundles are configured in application.js
|
233
|
-
# Server bundle is a single file for all server rendering of components.
|
234
|
-
config.server_bundle_js_file = "app/assets/javascripts/generated/server.js" # This is the default
|
127
|
+
You may also notice the `app/lib` folder. This is for any code that is common between bundles and therefore needs to be shared (for example, middleware).
|
235
128
|
|
236
|
-
|
237
|
-
|
238
|
-
config.generator_function = false # default is false, meaning that you expose ReactComponents directly
|
239
|
-
config.trace = Rails.env.development? # default is true for development, off otherwise
|
129
|
+
#### Additional Redux Folders
|
130
|
+
If you have used the `--redux` generator option, you will notice the familiar additional redux folders in addition to the aforementioned folders. In this organization paradigm, each bundle has its own store. We do not set a global store and then use partial stores based off of that. Again, this is for bundle code modularity and isolation. Note that if you want to reuse redux reducers across domains, then you will want to put the shared reducers under `/client/app/lib`.
|
240
131
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
132
|
+
### Using Images and Fonts
|
133
|
+
The generator has amended the folders created in `client/assets/` to Rails's asset path. We would that if you have any existing assets that you want to use with your client code that you should move them to these folders and use webpack as normal.
|
134
|
+
|
135
|
+
Alternatively, if you have many existing assets and don't wish to move them, you could consider creating symlinks from client/assets that point to your Rails assets folders inside of `app/assets/`. The assets there will then be visible to both Rails and webpack.
|
136
|
+
|
137
|
+
### Bootstrap Integration
|
138
|
+
React on Rails ships with Twitter Bootstrap already integrated into the build. Note that the generator removes `require_tree` in both the application.js and application.css.scss files. This is to ensure the correct load order for the bootstrap integration, and is usually a good idea in general. You will therefore need to explicitly require your files.
|
139
|
+
|
140
|
+
How the Bootstrap library is loaded depends upon whether one is using the Rails server or the HMR development server.
|
141
|
+
|
142
|
+
#### Bootstrap via Rails Server
|
143
|
+
In the former case, the Rails server loads `bootstrap-sprockets`, provided by the `bootstrap-sass` ruby gem (added automatically to your Gemfile by the generator) via the `app/assets/stylesheets/_bootstrap-custom.scss` partial.
|
250
144
|
|
251
|
-
|
145
|
+
This allows for using Bootstrap in your regular Rails stylesheets. If you wish to customize any of the Bootstrap variables, you can do so via the `client/assets/stylesheets/_pre-bootstrap.scss` partial.
|
252
146
|
|
253
|
-
|
254
|
-
|
255
|
-
- If you're using JRuby, you can increase `pool_size` to have real multi-threaded rendering.
|
147
|
+
#### Bootstrap via Webpack HMR Dev Server
|
148
|
+
When using the webpack dev server, which does not go through Rails, bootstrap is loaded via the [bootstrap-sass-loader](https://github.com/shakacode/bootstrap-sass-loader) which uses the `client/bootstrap-sass-config.js` file.
|
256
149
|
|
257
|
-
|
258
|
-
|
150
|
+
#### Keeping Custom Bootstrap Configurations Synced
|
151
|
+
Because the HMR dev server and Rails each load Bootstrap via a different file (explained in the two sections immediately above), any changes to the way components are loaded in one file must also be made to the other file in order to keep styling consistent between the two. For example, if an import is excluded in `_bootstrap-custom.scss`, the same import should be excluded in `bootstrap-sass-config.js` so that styling in the Rails server and the webpack dev server will be the same.
|
152
|
+
|
153
|
+
## Rails View Helpers In-Depth
|
154
|
+
Once the bundled files have been generated in your `app/assets/javascripts/generated` folder and you have exposed your components globally, you will want to run your code in your Rails views using the included helper method.
|
155
|
+
|
156
|
+
This is how you actually render the React components you exposed to `window` inside of `clientGlobals` (and `global` inside of `serverGlobals` if you are server rendering).
|
157
|
+
|
158
|
+
`react_component(component_name, props = {}, options = {})`
|
159
|
+
+ **react_component_name:** Can be a React component, created using a ES6 class, or `React.createClass`, or a generator function that returns a React component.
|
160
|
+
+ **props:** Ruby Hash which contains the properties to pass to the react object
|
161
|
+
+ **options:**
|
162
|
+
+ **generator_function:** default is false, set to true if you want to use a generator function rather than a React Component.
|
163
|
+
+ **prerender:** enable server-side rendering of component. Set to false when debugging!
|
164
|
+
+ **trace:** set to true to print additional debugging information in the browser. Defaults to true for development, off otherwise.
|
165
|
+
+ **replay_console:** Default is true. False will disable echoing server-rendering logs to the browser. While this can make troubleshooting server rendering difficult, so long as you have the default configuration of logging_on_server set to true, you'll still see the errors on the server.
|
166
|
+
+ Any other options are passed to the content tag, including the id
|
167
|
+
|
168
|
+
`def server_render_js(js_expression, options = {})`
|
169
|
+
|
170
|
+
This is a helper method that takes any JavaScript expression and returns the output from evaluating it. If you have more than one line that needs to be executed, wrap it in an IIFE. JS exceptions will be caught and console messages handled properly.
|
171
|
+
|
172
|
+
## Developing with Webpack Dev Server
|
173
|
+
One of the benefits of using webpack is access to [webpack's dev server](https://webpack.github.io/docs/webpack-dev-server.html) and its [hot module replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html) functionality.
|
174
|
+
|
175
|
+
The webpack dev server with HMR will apply changes from the code (or styles!) to the browser as soon as you save whatever file you're working on. You won't need to reload the page, and your data will still be there. Start foreman as normal (it boots up the Rails server *and* the webpack HMR dev server at the same time).
|
259
176
|
|
260
|
-
1. Setup and run the test app in `spec/dummy`. Note, there's no database.
|
261
177
|
```bash
|
262
|
-
|
263
|
-
bundle
|
264
|
-
npm i
|
265
|
-
foreman start
|
178
|
+
foreman start -f Procfile.dev
|
266
179
|
```
|
267
|
-
3. Visit http://localhost:3000
|
268
|
-
4. Notice that the first time you hit the page, you'll see a message that server is rendering.
|
269
|
-
See `spec/dummy/app/views/pages/index.html.erb:17` for the generation of that message.
|
270
|
-
5. Look at the layouts in `spec/dummy/app/views/pages` for samples of usage.
|
271
|
-
5. Open up the browser console and see some tracing.
|
272
|
-
6. Open up the source for the page and see the server rendered code.
|
273
|
-
7. If you want to turn on server caching for development, run the server like:
|
274
|
-
`export RAILS_USE_CACHE=YES && foreman start`
|
275
|
-
2. If you're testing with caching, you'll need to open the console and run `Rails.cache.clear` to clear
|
276
|
-
the cache. Note, even if you stop the server, you'll still have the cache entries around.
|
277
|
-
8. If you click back and forth between the react page links, you can see the rails console
|
278
|
-
log as well as the browser console to see what's going on with regards to server rendering and
|
279
|
-
caching.
|
280
|
-
|
281
|
-
# Key Tips
|
282
|
-
1. See sample app in `spec/dummy` for how to set this up. See note below on ensuring you
|
283
|
-
**DO NOT RUN `rails s` and instead run `foreman start`.
|
284
|
-
2. Test out the different options and study the JSX samples in `spec/dummy/client/app/startup`.
|
285
|
-
3. Experiment with changing the settings on the `render_component` helper calls in the ERB files.
|
286
|
-
2. The file used for server rendering is hard coded as `generated/server.js`
|
287
|
-
(assets/javascripts/generated/server.js).
|
288
|
-
3. The default for rendering right now is `prerender: false`. **NOTE:** Server side rendering does
|
289
|
-
not work for some components, namely react-router, that use an async setup for server rendering.
|
290
|
-
You can configure the default for prerender in your config.
|
291
|
-
4. You can expose either a React component or a function that returns a React component. If you
|
292
|
-
wish to create a React component via a function, rather than simply props, then you need to set
|
293
|
-
the property "generator" on that function to true. When that is done, the function is invoked
|
294
|
-
with a single parameter of "props", and that function should return a React element.
|
295
|
-
5. Be sure you can first render your react component client only before you try to debug server
|
296
|
-
rendering!
|
297
|
-
4. Open up the HTML source and take a look at the generated HTML and the JavaScript to see what's
|
298
|
-
going on under the covers. Not that when server rendering is turned on, then you'll see the
|
299
|
-
server rendered react components. When server rendering is turned off, then you'll only see
|
300
|
-
the `div` element where the inline JavaScript will render the component. You might also notice
|
301
|
-
how the props you pass (a Ruby Hash) becomes inline JavaScript on the HTML page.
|
302
|
-
|
303
|
-
## JavaScript Runtime Configuration
|
304
|
-
See this [discussion on JavaScript performance](https://github.com/shakacode/react_on_rails/issues/21).
|
305
|
-
The net result is that you want to add this line to your Gemfile to get therubyracer as your default
|
306
|
-
JavaScript engine.
|
307
|
-
|
308
|
-
```ruby
|
309
|
-
gem "therubyracer"
|
310
|
-
```
|
311
180
|
|
312
|
-
|
313
|
-
* [Making the helper for server side rendering work with JS created by Webpack] (https://github.com/reactjs/react-rails/issues/301#issuecomment-133098974)
|
314
|
-
* [Add Demonstration of Server Side Rendering](https://github.com/justin808/react-webpack-rails-tutorial/issues/2)
|
315
|
-
* [Charlie Marsh's article "Rendering React Components on the Server"](http://www.crmarsh.com/react-ssr/)
|
316
|
-
* [Node globals](https://nodejs.org/api/globals.html#globals_global)
|
181
|
+
Open your browser to [localhost:4000](http://localhost:4000). Whenever you make changes to your JavaScript code in the `client` folder, they will automatically show up in the browser. Hot module replacement is already enabled by default.
|
317
182
|
|
318
|
-
|
183
|
+
Note that **React-related error messages are typically significantly more helpful when encountered in the dev server** than the Rails server as they do not include noise added by the React on Rails gem.
|
319
184
|
|
320
|
-
|
321
|
-
|
185
|
+
### Adding Additional Routes for the Dev Server
|
186
|
+
As you add more routes to your front-end application, you will need to make the corresponding API for the dev server in `client/server.js`. See our example `server.js` from our [tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/server.js).
|
322
187
|
|
323
|
-
##
|
188
|
+
## Additional Documentation:
|
324
189
|
|
325
|
-
|
190
|
+
+ [Linters](docs/linters.md)
|
191
|
+
+ [Manual Configuration](docs/manual_configuration.md)
|
192
|
+
+ [Node Dependencies and NPM](docs/node_dependencies_and_npm.md)
|
326
193
|
|
327
|
-
|
328
|
-
|
329
|
-
## License
|
194
|
+
## Contributing
|
195
|
+
Bug reports and pull requests are welcome. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to our version of the [Contributor Covenant](contributor-covenant.org) code of conduct (see [CODE OF CONDUCT](CODE_OF_CONDUCT.md)).
|
330
196
|
|
331
|
-
|
197
|
+
See [Contributing](docs/Contributing.md) to get started.
|
332
198
|
|
333
|
-
|
199
|
+
## License
|
200
|
+
The gem is available as open source under the terms of the [MIT License](LICENSE).
|
334
201
|
|
202
|
+
## Authors
|
335
203
|
[The Shaka Code team!](http://www.shakacode.com/about/)
|
336
204
|
|
337
205
|
1. [Justin Gordon](https://github.com/justin808/)
|
338
206
|
2. [Samnang Chhun](https://github.com/samnang)
|
339
207
|
3. [Alex Fedoseev](https://github.com/alexfedoseev)
|
208
|
+
4. [Rob Wise](https://github.com/robwise)
|
209
|
+
5. [Blaine Hatab](https://github.com/jbhatab)
|
210
|
+
6. [Roger Studner](https://github.com/rstudner)
|
211
|
+
7. [Aaron Van Bokhoven](https://github.com/aaronvb)
|
340
212
|
|
341
213
|
And based on the work of the [react-rails gem](https://github.com/reactjs/react-rails)
|
214
|
+
|
215
|
+
## About [ShakaCode](http://www.shakacode.com/)
|
216
|
+
|
217
|
+
Visit [our forums!](http://forum.shakacode.com)
|
218
|
+
|
219
|
+
If you're looking for consulting on a project using React and Rails, email us ([contact@shakacode.com](mailto: contact@shakacode.com))! You can also join our slack room for some free advice.
|
220
|
+
|
221
|
+
We're looking for great developers that want to work with Rails + React with a distributed, worldwide team, for our own products, client work, and open source. [More info here](http://www.shakacode.com/about/index.html#work-with-us).
|