react_on_rails 5.2.0 → 6.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +31 -0
- data/PROJECTS.md +11 -2
- data/README.md +33 -203
- data/app/helpers/react_on_rails_helper.rb +32 -49
- data/docs/additional-reading/heroku-deployment.md +2 -35
- data/docs/additional-reading/node-server-rendering.md +30 -0
- data/docs/additional-reading/rails-assets.md +19 -0
- data/docs/additional-reading/rspec-configuration.md +38 -4
- data/docs/additional-reading/webpack-dev-server.md +16 -0
- data/docs/additional-reading/webpack.md +0 -10
- data/docs/api/javascript-api.md +37 -0
- data/docs/api/ruby-api-hot-reload-view-helpers.md +42 -0
- data/docs/api/ruby-api.md +3 -0
- data/docs/basics/generator.md +49 -0
- data/docs/{additional-reading → basics}/installation-overview.md +0 -0
- data/docs/basics/migrating-from-react-rails.md +17 -0
- data/docs/contributor-info/contributing.md +11 -0
- data/docs/{coding-style → contributor-info}/linters.md +0 -0
- data/lib/generators/USAGE +3 -95
- data/lib/generators/react_on_rails/base_generator.rb +10 -43
- data/lib/generators/react_on_rails/dev_tests_generator.rb +17 -1
- data/lib/generators/react_on_rails/install_generator.rb +0 -6
- data/lib/generators/react_on_rails/react_no_redux_generator.rb +3 -17
- data/lib/generators/react_on_rails/react_with_redux_generator.rb +4 -21
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev.tt +2 -2
- data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +3 -4
- data/lib/generators/react_on_rails/templates/base/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx.tt +1 -11
- data/lib/generators/react_on_rails/templates/base/base/client/node/package.json +10 -0
- data/lib/generators/react_on_rails/templates/base/base/client/node/server.js +82 -0
- data/lib/generators/react_on_rails/templates/base/base/client/package.json.tt +3 -20
- data/lib/generators/react_on_rails/templates/base/base/client/webpack.config.js +58 -0
- data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt +60 -26
- data/lib/generators/react_on_rails/templates/base/base/lib/tasks/assets.rake.tt +1 -4
- data/lib/generators/react_on_rails/templates/base/base/lib/tasks/load_test.rake +8 -0
- data/lib/generators/react_on_rails/templates/base/base/package.json.tt +0 -12
- data/lib/generators/react_on_rails/templates/dev_tests/spec/features/hello_world_spec.rb +1 -1
- data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +1 -0
- data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +1 -7
- data/lib/generators/react_on_rails/templates/{base/base/client/app/bundles/HelloWorld/startup/clientRegistration.jsx.tt → no_redux/base/client/app/bundles/HelloWorld/startup/HelloWorldApp.jsx.tt} +7 -1
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/startup/{HelloWorldAppClient.jsx.tt → HelloWorldApp.jsx.tt} +5 -1
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/store/helloWorldStore.jsx +1 -5
- data/lib/react_on_rails.rb +2 -1
- data/lib/react_on_rails/configuration.rb +17 -5
- data/lib/react_on_rails/react_component/options.rb +76 -0
- data/lib/react_on_rails/server_rendering_pool.rb +9 -151
- data/lib/react_on_rails/server_rendering_pool/exec.rb +166 -0
- data/lib/react_on_rails/server_rendering_pool/node.rb +77 -0
- data/lib/react_on_rails/test_helper.rb +1 -6
- data/lib/react_on_rails/test_helper/ensure_assets_compiled.rb +4 -77
- data/lib/react_on_rails/test_helper/node_process_launcher.rb +12 -0
- data/lib/react_on_rails/test_helper/webpack_assets_compiler.rb +4 -28
- data/lib/react_on_rails/version.rb +1 -1
- data/lib/tasks/assets.rake +115 -0
- data/package.json +2 -1
- data/rakelib/example_type.rb +3 -10
- data/rakelib/examples_config.yml +2 -2
- data/react_on_rails.gemspec +1 -0
- metadata +41 -20
- data/lib/generators/react_on_rails/templates/base/base/REACT_ON_RAILS.md +0 -16
- data/lib/generators/react_on_rails/templates/base/base/client/REACT_ON_RAILS_CLIENT_README.md +0 -3
- data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.base.config.js +0 -65
- data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.rails.config.js +0 -53
- data/lib/generators/react_on_rails/templates/base/server_rendering/client/app/bundles/HelloWorld/startup/serverRegistration.jsx +0 -4
- data/lib/generators/react_on_rails/templates/base/server_rendering/client/webpack.server.rails.config.js +0 -39
- data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx.tt +0 -6
- data/lib/generators/react_on_rails/templates/no_redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +0 -6
- data/lib/generators/react_on_rails/templates/redux/base/client/app/lib/middlewares/loggerMiddleware.js +0 -21
- data/lib/generators/react_on_rails/templates/redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +0 -19
- data/lib/react_on_rails/test_helper/webpack_process_checker.rb +0 -54
@@ -87,14 +87,7 @@ module ReactOnRailsHelper
|
|
87
87
|
# raise_on_prerender_error: <true/false> Default to false. True will raise exception on server
|
88
88
|
# if the JS code throws
|
89
89
|
# Any other options are passed to the content tag, including the id.
|
90
|
-
def react_component(component_name,
|
91
|
-
props: {},
|
92
|
-
prerender: nil,
|
93
|
-
trace: nil,
|
94
|
-
replay_console: nil,
|
95
|
-
raise_on_prerender_error: nil,
|
96
|
-
id: nil,
|
97
|
-
html_options: {})
|
90
|
+
def react_component(component_name, raw_options = {})
|
98
91
|
# Create the JavaScript and HTML to allow either client or server rendering of the
|
99
92
|
# react_component.
|
100
93
|
#
|
@@ -104,44 +97,31 @@ module ReactOnRailsHelper
|
|
104
97
|
# We use this react_component_index in case we have the same component multiple times on the page.
|
105
98
|
|
106
99
|
react_component_index = next_react_component_index
|
107
|
-
|
108
|
-
|
100
|
+
options = ReactOnRails::ReactComponent::Options.new(name: component_name,
|
101
|
+
index: react_component_index,
|
102
|
+
options: raw_options)
|
109
103
|
|
110
104
|
# Setup the page_loaded_js, which is the same regardless of prerendering or not!
|
111
105
|
# The reason is that React is smart about not doing extra work if the server rendering did its job.
|
112
106
|
|
113
|
-
props = {} if props.nil?
|
114
|
-
|
115
|
-
prerender = prerender_option(prerender)
|
116
|
-
trace = trace_option(trace)
|
117
|
-
replay_console = replay_console_option(replay_console)
|
118
|
-
raise_on_prerender_error = raise_on_prerender_error_option(raise_on_prerender_error)
|
119
|
-
|
120
|
-
data = {
|
121
|
-
component_name: react_component_name,
|
122
|
-
props: props,
|
123
|
-
trace: trace,
|
124
|
-
dom_id: dom_id
|
125
|
-
}
|
126
|
-
|
127
107
|
component_specification_tag =
|
128
108
|
content_tag(:div,
|
129
109
|
"",
|
130
110
|
class: "js-react-on-rails-component",
|
131
|
-
style:
|
132
|
-
data: data)
|
111
|
+
style: options.style,
|
112
|
+
data: options.data)
|
133
113
|
|
134
114
|
# Create the HTML rendering part
|
135
|
-
result = server_rendered_react_component_html(props,
|
136
|
-
prerender: prerender,
|
137
|
-
trace: trace,
|
138
|
-
raise_on_prerender_error: raise_on_prerender_error)
|
115
|
+
result = server_rendered_react_component_html(options.props, options.name, options.dom_id,
|
116
|
+
prerender: options.prerender,
|
117
|
+
trace: options.trace,
|
118
|
+
raise_on_prerender_error: options.raise_on_prerender_error)
|
139
119
|
|
140
120
|
server_rendered_html = result["html"]
|
141
121
|
console_script = result["consoleReplayScript"]
|
142
122
|
|
143
|
-
content_tag_options = html_options
|
144
|
-
content_tag_options[:id] = dom_id
|
123
|
+
content_tag_options = options.html_options
|
124
|
+
content_tag_options[:id] = options.dom_id
|
145
125
|
|
146
126
|
rendered_output = content_tag(:div,
|
147
127
|
server_rendered_html.html_safe,
|
@@ -151,7 +131,7 @@ module ReactOnRailsHelper
|
|
151
131
|
result = <<-HTML.html_safe
|
152
132
|
#{component_specification_tag}
|
153
133
|
#{rendered_output}
|
154
|
-
#{replay_console ? console_script : ''}
|
134
|
+
#{options.replay_console ? console_script : ''}
|
155
135
|
HTML
|
156
136
|
|
157
137
|
prepend_render_rails_context(result)
|
@@ -290,16 +270,29 @@ module ReactOnRailsHelper
|
|
290
270
|
# On server `location` option is added (`location = request.fullpath`)
|
291
271
|
# React Router needs this to match the current route
|
292
272
|
|
293
|
-
# Make sure that we use up-to-date server
|
273
|
+
# Make sure that we use up-to-date bundle file used for server rendering, which is defined
|
274
|
+
# by config file value for config.server_bundle_js_file
|
294
275
|
ReactOnRails::ServerRenderingPool.reset_pool_if_server_bundle_was_modified
|
295
276
|
|
296
277
|
# Since this code is not inserted on a web page, we don't need to escape props
|
278
|
+
#
|
279
|
+
# However, as JSON (returned from `props_string(props)`) isn't JavaScript,
|
280
|
+
# but we want treat it as such, we need to compensate for the difference.
|
281
|
+
#
|
282
|
+
# \u2028 and \u2029 are valid characters in strings in JSON, but are treated
|
283
|
+
# as newline separators in JavaScript. As no newlines are allowed in
|
284
|
+
# strings in JavaScript, this causes an exception.
|
285
|
+
#
|
286
|
+
# We fix this by replacing these unicode characters with their escaped versions.
|
287
|
+
# This should be safe, as the only place they can appear is in strings anyway.
|
288
|
+
#
|
289
|
+
# Read more here: http://timelessrepo.com/json-isnt-a-javascript-subset
|
297
290
|
|
298
291
|
wrapper_js = <<-JS
|
299
292
|
(function() {
|
300
293
|
var railsContext = #{rails_context(server_side: true).to_json};
|
301
294
|
#{initialize_redux_stores}
|
302
|
-
var props = #{props_string(props)};
|
295
|
+
var props = #{props_string(props).gsub("\u2028", '\u2028').gsub("\u2029", '\u2029')};
|
303
296
|
return ReactOnRails.serverRenderReactComponent({
|
304
297
|
name: '#{react_component_name}',
|
305
298
|
domNodeId: '#{dom_id}',
|
@@ -358,8 +351,10 @@ ReactOnRails.setStore('#{store_name}', store);
|
|
358
351
|
# second parameter passed to both component and store generator functions.
|
359
352
|
def rails_context(server_side:)
|
360
353
|
@rails_context ||= begin
|
361
|
-
|
362
|
-
#
|
354
|
+
# Using Addressable instead of standard URI to better deal with
|
355
|
+
# non-ASCII characters (see https://github.com/shakacode/react_on_rails/pull/405)
|
356
|
+
uri = Addressable::URI.parse(request.original_url)
|
357
|
+
# uri = Addressable::URI.parse("http://foo.com:3000/posts?id=30&limit=5#time=1305298413")
|
363
358
|
|
364
359
|
result = {
|
365
360
|
# URL settings
|
@@ -387,18 +382,6 @@ ReactOnRails.setStore('#{store_name}', store);
|
|
387
382
|
@rails_context.merge(serverSide: server_side)
|
388
383
|
end
|
389
384
|
|
390
|
-
def raise_on_prerender_error_option(val)
|
391
|
-
val.nil? ? ReactOnRails.configuration.raise_on_prerender_error : val
|
392
|
-
end
|
393
|
-
|
394
|
-
def trace_option(val)
|
395
|
-
val.nil? ? ReactOnRails.configuration.trace : val
|
396
|
-
end
|
397
|
-
|
398
|
-
def prerender_option(val)
|
399
|
-
val.nil? ? ReactOnRails.configuration.prerender : val
|
400
|
-
end
|
401
|
-
|
402
385
|
def replay_console_option(val)
|
403
386
|
val.nil? ? ReactOnRails.configuration.replay_console : val
|
404
387
|
end
|
@@ -26,13 +26,13 @@ If for some reason you need custom buildpacks that are not officially supported
|
|
26
26
|
|
27
27
|
### Swap out sqlite for postgres by doing the following:
|
28
28
|
|
29
|
-
1. Delete the line with `sqlite` and replace it with:
|
29
|
+
#### 1. Delete the line with `sqlite` and replace it with:
|
30
30
|
|
31
31
|
```ruby
|
32
32
|
gem 'pg'
|
33
33
|
```
|
34
34
|
|
35
|
-
2. Replace your `database.yml` file with this (assuming your app name is "ror")
|
35
|
+
#### 2. Replace your `database.yml` file with this (assuming your app name is "ror")
|
36
36
|
|
37
37
|
```yml
|
38
38
|
default: &default
|
@@ -64,36 +64,3 @@ bundle
|
|
64
64
|
bin/rake db:migrate
|
65
65
|
bin/rake db:setup
|
66
66
|
```
|
67
|
-
|
68
|
-
3. Create a rake file to add webpack compilation to asset precompilation. You may already have this file if you used the React on Rails generator.
|
69
|
-
|
70
|
-
```ruby
|
71
|
-
# lib/tasks/assets.rake
|
72
|
-
# The webpack task must run before assets:environment task.
|
73
|
-
# Otherwise Sprockets cannot find the files that webpack produces.
|
74
|
-
# This is the secret sauce for how a Heroku deployment knows to create the webpack generated JavaScript files.
|
75
|
-
Rake::Task["assets:precompile"]
|
76
|
-
.clear_prerequisites
|
77
|
-
.enhance(["assets:compile_environment"])
|
78
|
-
|
79
|
-
namespace :assets do
|
80
|
-
# In this task, set prerequisites for the assets:precompile task
|
81
|
-
task compile_environment: :webpack do
|
82
|
-
Rake::Task["assets:environment"].invoke
|
83
|
-
end
|
84
|
-
|
85
|
-
desc "Compile assets with webpack"
|
86
|
-
task :webpack do
|
87
|
-
sh "cd client && npm run build:client"
|
88
|
-
# If you are doing server rendering
|
89
|
-
# sh "cd client && npm run build:server"
|
90
|
-
end
|
91
|
-
|
92
|
-
task :clobber do
|
93
|
-
rm_r Dir.glob(Rails.root.join("app/assets/webpack/*"))
|
94
|
-
end
|
95
|
-
end
|
96
|
-
```
|
97
|
-
|
98
|
-
|
99
|
-
|
@@ -0,0 +1,30 @@
|
|
1
|
+
## Node Server Rendering
|
2
|
+
|
3
|
+
### Warning: this is an experimental feature
|
4
|
+
|
5
|
+
The default server rendering exploits ExecJS to render react components.
|
6
|
+
Node server rendering allows you to use separate NodeJS process as a renderer. The process loads your configured server_bundle_js file and
|
7
|
+
then executes javascript to render the component inside its environment. The communication between rails and node occurs
|
8
|
+
via socket (`client/node/node.sock`)
|
9
|
+
|
10
|
+
### Getting started
|
11
|
+
|
12
|
+
To use node process just set `server_render_method = "NodeJS"` in `config/initializers/react_on_rails.rb`. To change back
|
13
|
+
to ExecJS set `server_render_method = "ExecJS"`
|
14
|
+
|
15
|
+
### Configuration
|
16
|
+
|
17
|
+
You need to configure the name of the server bundle in two places:
|
18
|
+
|
19
|
+
1. JavaScript: Change the name of server bundle adjust npm start script in `client/node/package.json`
|
20
|
+
2. Ruby: The configured server bundle file is defined in `config/react_on_rails.rb`, and you'll have a webpack file that creates this. You maybe using the same file for client rendering.
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
# This is the file used for server rendering of React when using `(prerender: true)`
|
24
|
+
# If you are never using server rendering, you may set this to "".
|
25
|
+
# If you are using the same file for client and server rendering, having this set probably does
|
26
|
+
# not affect performance.
|
27
|
+
config.server_bundle_js_file = "webpack-bundle.js"
|
28
|
+
```
|
29
|
+
|
30
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
## Rails assets
|
2
|
+
|
3
|
+
### Problem
|
4
|
+
When client js uses images in render methods, e.g. `<img src='...' />` or in css, e.g. `background-image: url(...)`
|
5
|
+
these assets fail to load. This happens because rails adds digest hashes to filenames
|
6
|
+
when compiling assets, e.g. `img1.jpg` becomes `img1-dbu097452jf2v2.jpg`.
|
7
|
+
|
8
|
+
When compiling its native css Rails transforms all urls and links to digested
|
9
|
+
versions, i.e. `background-image: image-url(img1.jpg)` becomes
|
10
|
+
`background-image: url(img1-dbu097452jf2v2.jpg)`. However this doesn't happen for js and
|
11
|
+
css files compiled by webpack on the client side, because they don't use
|
12
|
+
`image-url` and `asset-url` and therefore assets fail to load.
|
13
|
+
|
14
|
+
### Solution
|
15
|
+
|
16
|
+
Create symlinks of non-digested versions to digested versions when Rails assets compile.
|
17
|
+
The solution is implemented using `assets:precompile` after-hook. The assets for symlinking
|
18
|
+
are defined by `config.symlink_non_digested_assets_regex` in `config/initializers/react_on_rails.rb`.
|
19
|
+
To disable symlinks set this parameter to `nil`.
|
@@ -9,16 +9,50 @@ RSpec.configure do |config|
|
|
9
9
|
ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
|
10
10
|
```
|
11
11
|
|
12
|
-
You can pass an RSpec metatag as an optional second parameter to this helper method if you want this helper to run on examples other than where `js: true` (default). The helper will compile webpack files at most once per test run. The helper will not compile the webpack files unless they are out of date (stale).
|
12
|
+
You can pass an RSpec metatag as an optional second parameter to this helper method if you want this helper to run on examples other than where `js: true` (default). The helper will compile webpack files at most once per test run. The helper will not compile the webpack files unless they are out of date (stale). The helper is configurable in terms of what command is used to prepare the files.
|
13
13
|
|
14
14
|
Please take note of the following:
|
15
|
-
- This utility
|
16
|
-
- By default, the webpack processes look for the `app/assets/webpack` folders. If this folder is missing, is empty, or contains files with `mtime`s older than any of the files in your `client` folder, the helper will recompile your assets. You can override
|
15
|
+
- This utility uses your `npm_build_test_command' to build the static generated files. This command **must** not include the `--watch` option. If you have different server and client bundle files, this command **must** create all the bundles.
|
16
|
+
- By default, the webpack processes look for the `app/assets/webpack` folders (configured as setting `webpack_generated_files` in the `config/react_on_rails.rb`. If this folder is missing, is empty, or contains files in the `config.webpack_generated_files` list with `mtime`s older than any of the files in your `client` folder, the helper will recompile your assets. You can override the location of these files inside of `config/initializers/react_on_rails.rb` by passing a filepath (relative to the root of the app) to the `generated_assets_dir` configuration option.
|
17
17
|
|
18
|
-
|
18
|
+
The following `config/react_on_rails.rb` settings **must** match your setup:
|
19
|
+
```ruby
|
20
|
+
# Directory where your generated assets go. All generated assets must go to the same directory.
|
21
|
+
# Configure this in your webpack config files. This relative to your Rails root directory.
|
22
|
+
config.generated_assets_dir = File.join(%w(app assets webpack))
|
23
|
+
|
24
|
+
# Define the files we need to check for webpack compilation when running tests.
|
25
|
+
config.webpack_generated_files = %w( webpack-bundle.js )
|
26
|
+
|
27
|
+
# If you are using the ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
|
28
|
+
# with rspec then this controls what npm command is run
|
29
|
+
# to automatically refresh your webpack assets on every test run.
|
30
|
+
config.npm_build_test_command = "npm run build:test"
|
31
|
+
```
|
32
|
+
|
33
|
+
If you want to speed up the re-compiling process, you can call `npm run build:development` (per below script) to have webpack run in "watch" mode and recompile these files in the background, which will be much faster when making incremental changes than compiling from scratch, assuming you have your setup like this:
|
34
|
+
|
35
|
+
```
|
36
|
+
"scripts": {
|
37
|
+
"build:test": "webpack --config webpack.config.js",
|
38
|
+
"build:production": "NODE_ENV=production webpack --config webpack.config.js",
|
39
|
+
"build:development": "webpack -w --config webpack.config.js"
|
40
|
+
},
|
41
|
+
```
|
19
42
|
|
20
43
|
[spec/dummy](../../spec/dummy) contains examples of how to set the proc files for this purpose.
|
21
44
|
|
45
|
+
## Hot Reloading
|
46
|
+
If you're using the hot reloading setup, you'll be running a Webpack development server to provide the JavaScript and mabye CSS assets to your Rails app. If you're doing server rendering, you'll also have a webpack watch process to refresh the server rendering file. **If your server and client bundles are different**, and you run specs, the client bundle files will not be created until React on Rails detects it's out of date. Then your script to create all bundle files will redo the server bundle file. There's a few simple remedies for this situation:
|
47
|
+
|
48
|
+
1. Switch to using static compilation of the webpack bundle files. This way, you're running a Webpack watch process to generate the same files used for tests as well as developmentment. You should have a separate Procfile for doing development using a "static" setup, rather than a "hot" setup.
|
49
|
+
2. Change your Procfile for starting the hot reloading server to also run a webpack process to automatically rebuild a the client assets while also doing hot reloading for browser testing.
|
50
|
+
|
51
|
+
Note, none of these issues matter if you're using the same file for both server and client side rendering.
|
52
|
+
|
53
|
+
## Using RubyMine and other IDEs that save files right before invoking tests
|
54
|
+
We had previously tried to allow using a process check to see if a Webpack watch process would already be automatically compiling the files. However, we removed this as it proved to be fragile with various setups. Thus, you want to hit the save keystroke when you save a JavaScript file, and then run your tests. Yes, you might not do this in time, and the test runner may be building the same files as you Webpack watch processes. This will probably happen infrequently, but if this does become an issue, we can look into bring back this functionality ([#398](https://github.com/shakacode/react_on_rails/pull/398)).
|
55
|
+
|
22
56
|
If you want to use a testing framework other than RSpec, please submit let us know on the changes you need to do and we'll update the docs.
|
23
57
|
|
24
58
|
![2016-01-27_02-36-43](https://cloud.githubusercontent.com/assets/1118459/12611951/7c56d070-c4a4-11e5-8a80-9615f99960d9.png)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
## Developing with the Webpack Dev Server
|
2
|
+
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.
|
3
|
+
|
4
|
+
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).
|
5
|
+
|
6
|
+
```bash
|
7
|
+
foreman start -f Procfile.dev
|
8
|
+
```
|
9
|
+
|
10
|
+
Open your browser to [localhost:3000](http://localhost:3000). 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.
|
11
|
+
|
12
|
+
Note that **React-related error messages are possibly 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.
|
13
|
+
|
14
|
+
### Adding Additional Routes for the Dev Server
|
15
|
+
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%2Fserver-express.js).
|
16
|
+
|
@@ -12,8 +12,6 @@ You need both include `react-dom/server` and `react` as values for `entry`, like
|
|
12
12
|
// See use of 'vendor' in the CommonsChunkPlugin inclusion below.
|
13
13
|
vendor: [
|
14
14
|
'babel-core/polyfill',
|
15
|
-
'jquery',
|
16
|
-
'jquery-ujs',
|
17
15
|
'react',
|
18
16
|
'react-dom',
|
19
17
|
],
|
@@ -25,14 +23,6 @@ and you need to expose them:
|
|
25
23
|
// React is necessary for the client rendering:
|
26
24
|
{test: require.resolve('react'), loader: 'expose?React'},
|
27
25
|
{test: require.resolve('react-dom'), loader: 'expose?ReactDOM'},
|
28
|
-
{test: require.resolve('jquery'), loader: 'expose?jQuery'},
|
29
|
-
{test: require.resolve('jquery'), loader: 'expose?$'},
|
30
|
-
```
|
31
|
-
|
32
|
-
`webpack.server.config.js` is similar, but substitute:
|
33
|
-
|
34
|
-
```
|
35
|
-
entry: ['./yourCode', 'react-dom/server', 'react'],
|
36
26
|
```
|
37
27
|
|
38
28
|
and use this line rather than `{test: require.resolve('react-dom'), loader: 'expose?ReactDOM'},`:
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# ReactOnRails JavaScript API
|
2
|
+
The best source of docs is the main [ReactOnRails.js](node_package/src/ReactOnRails.js) file. Here's a quick summary. No guarantees that this won't be outdated!
|
3
|
+
|
4
|
+
```js
|
5
|
+
/**
|
6
|
+
* Main entry point to using the react-on-rails npm package. This is how Rails will be able to
|
7
|
+
* find you components for rendering.
|
8
|
+
* @param components (key is component name, value is component)
|
9
|
+
*/
|
10
|
+
register(components)
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Allows registration of store generators to be used by multiple react components on one Rails
|
14
|
+
* view. store generators are functions that take one arg, props, and return a store. Note that
|
15
|
+
* the setStore API is different in tha it's the actual store hydrated with props.
|
16
|
+
* @param stores (key is store name, value is the store generator)
|
17
|
+
*/
|
18
|
+
registerStore(stores)
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Allows retrieval of the store by name. This store will be hydrated by any Rails form props.
|
22
|
+
* Pass optional param throwIfMissing = false if you want to use this call to get back null if the
|
23
|
+
* store with name is not registered.
|
24
|
+
* @param name
|
25
|
+
* @param throwIfMissing Defaults to true. Set to false to have this call return undefined if
|
26
|
+
* there is no store with the given name.
|
27
|
+
* @returns Redux Store, possibly hydrated
|
28
|
+
*/
|
29
|
+
getStore(name, throwIfMissing = true )
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Set options for ReactOnRails, typically before you call ReactOnRails.register
|
33
|
+
* Available Options:
|
34
|
+
* `traceTurbolinks: true|false Gives you debugging messages on Turbolinks events
|
35
|
+
*/
|
36
|
+
setOptions(options)
|
37
|
+
```
|
@@ -0,0 +1,42 @@
|
|
1
|
+
## Hot Reloading View Helpers
|
2
|
+
The `env_javascript_include_tag` and `env_stylesheet_link_tag` support the usage of a webpack dev server for providing the JS and CSS assets during development mode. See the [shakacode/react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/) for a working example.
|
3
|
+
|
4
|
+
The key options are `static` and `hot` which specify what you want for static vs. hot. Both of these params are optional, and support either a single value, or an array.
|
5
|
+
|
6
|
+
static vs. hot is picked based on whether `ENV["REACT_ON_RAILS_ENV"] == "HOT"`
|
7
|
+
|
8
|
+
```erb
|
9
|
+
<%= env_stylesheet_link_tag(static: 'application_static',
|
10
|
+
hot: 'application_non_webpack',
|
11
|
+
media: 'all',
|
12
|
+
'data-turbolinks-track' => true) %>
|
13
|
+
|
14
|
+
<!-- These do not use turbolinks, so no data-turbolinks-track -->
|
15
|
+
<!-- This is to load the hot assets. -->
|
16
|
+
|
17
|
+
<!-- Note, you can have multiple files here. It's an array. -->
|
18
|
+
<%= env_javascript_include_tag(hot: ['http://localhost:3500/webpack-bundle.js]') %>
|
19
|
+
|
20
|
+
<!-- These do use turbolinks -->
|
21
|
+
<%= env_javascript_include_tag(static: 'application_static',
|
22
|
+
hot: 'application_non_webpack',
|
23
|
+
'data-turbolinks-track' => true) %>
|
24
|
+
```
|
25
|
+
|
26
|
+
See application.html.erb for usage example and [application.html.erb](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/app%2Fviews%2Flayouts%2Fapplication.html.erb)
|
27
|
+
|
28
|
+
Helper to set CSS and JS assets depending on if we want static or "hot", which means from the Webpack dev server.
|
29
|
+
|
30
|
+
In this example, `application_non_webpack` is simply a CSS asset pipeline file which includes styles not placed in the webpack build. The same can be said for `application_non_webpack` for JS files. Note, the suffix is not used in the helper calls.
|
31
|
+
|
32
|
+
We don't need styles from the webpack build, as those will come via the JavaScript include tags.
|
33
|
+
|
34
|
+
The key options are `static` and `hot` which specify what you want for static vs. hot. Both of
|
35
|
+
these params are optional, and support either a single value, or an array.
|
36
|
+
|
37
|
+
```erb
|
38
|
+
<%= env_stylesheet_link_tag(static: 'application_static',
|
39
|
+
hot: 'application_non_webpack',
|
40
|
+
media: 'all',
|
41
|
+
'data-turbolinks-track' => true) %>
|
42
|
+
```
|
@@ -0,0 +1,49 @@
|
|
1
|
+
- [Generator](#generator)
|
2
|
+
- [Understanding the Organization of the Generated Client Code](#understanding-the-organization-of-the-generated-client-code)
|
3
|
+
- [Redux](#redux)
|
4
|
+
- [Multiple React Components on a Page with One Store](#multiple-react-components-on-a-page-with-one-store)
|
5
|
+
- [Using Images and Fonts](#using-images-and-fonts)
|
6
|
+
|
7
|
+
The `react_on_rails:install` generator combined with the example pull requests of generator runs will get you up and running efficiently. There's a fair bit of setup with integrating Webpack with Rails. Defaults for options are such that the default is for the flag to be off. For example, the default for `-R` is that `redux` is off, and the default of `-b` is that `skip-bootstrap` is off.
|
8
|
+
|
9
|
+
Run `rails generate react_on_rails:install --help` for descriptions of all available options:
|
10
|
+
|
11
|
+
```
|
12
|
+
Usage:
|
13
|
+
rails generate react_on_rails:install [options]
|
14
|
+
|
15
|
+
Options:
|
16
|
+
-R, [--redux], [--no-redux] # Install Redux gems and Redux version of Hello World Example
|
17
|
+
|
18
|
+
Runtime options:
|
19
|
+
-f, [--force] # Overwrite files that already exist
|
20
|
+
-p, [--pretend], [--no-pretend] # Run but do not make any changes
|
21
|
+
-q, [--quiet], [--no-quiet] # Suppress status output
|
22
|
+
-s, [--skip], [--no-skip] # Skip files that already exist
|
23
|
+
|
24
|
+
Description:
|
25
|
+
Create react on rails files for install generator.
|
26
|
+
```
|
27
|
+
|
28
|
+
For a clear example of what each generator option will do, see our generator results repo: [Generator Results](https://github.com/shakacode/react_on_rails-generator-results/blob/master/README.md). Each pull request shows a git "diff" that highlights the changes that the generator has made. Another good option is to create a simple test app per the [Tutorial](docs/tutorial.md).
|
29
|
+
|
30
|
+
### Understanding the Organization of the Generated Client Code
|
31
|
+
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*.
|
32
|
+
|
33
|
+
Inside of the generated "HelloWorld" domain you will find the following folders:
|
34
|
+
|
35
|
+
+ `startup`: This contains the entry point files for webpack. It defaults to a single file that is used for server and client compilation, but if these need to be different, then you can create two webpack configurations with separate endpoints.
|
36
|
+
+ `containers`: "smart components" (components that have functionality and logic that is passed to child "dumb components").
|
37
|
+
+ `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.
|
38
|
+
|
39
|
+
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).
|
40
|
+
|
41
|
+
### Redux
|
42
|
+
If you have used the `--redux` generator option, you will notice the familiar additional redux folders in addition to the aforementioned folders. The Hello World example has also been modified to use Redux.
|
43
|
+
|
44
|
+
Note the organizational paradigm of "bundles". These are like application domains and are used for grouping your code into webpack bundles, in case you decide to create different bundles for deployment. This is also useful for separating out logical parts of your application. The concept is that each bundle will have it's own Redux store. If you have code that you want to reuse across bundles, including components and reducers, place them under `/client/app/lib`.
|
45
|
+
|
46
|
+
### Using Images and Fonts
|
47
|
+
The generator has amended the folders created in `client/assets/` to Rails's asset path. We recommend that if you have any existing assets that you want to use with your client code, you should move them to these folders and use webpack as normal. This allows webpack's development server to have access to your assets, as it will not be able to see any assets in the default Rails directories which are above the `/client` directory.
|
48
|
+
|
49
|
+
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.
|