react_on_rails 3.0.6 → 4.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/.travis.yml +1 -1
- data/CHANGELOG.md +19 -1
- data/Gemfile +12 -4
- data/PROJECTS.md +1 -0
- data/README.md +110 -8
- data/app/helpers/react_on_rails_helper.rb +103 -16
- data/docs/additional_reading/heroku_deployment.md +2 -2
- data/docs/additional_reading/hot-reloading-rails-development.md +32 -0
- data/lib/generators/USAGE +3 -3
- data/lib/react_on_rails.rb +1 -0
- data/lib/react_on_rails/configuration.rb +2 -3
- data/lib/react_on_rails/controller.rb +19 -0
- data/lib/react_on_rails/test_helper.rb +24 -5
- data/lib/react_on_rails/test_helper/ensure_assets_compiled.rb +6 -2
- data/lib/react_on_rails/test_helper/webpack_assets_compiler.rb +1 -1
- data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +9 -5
- data/lib/react_on_rails/test_helper/webpack_process_checker.rb +1 -1
- data/lib/react_on_rails/version.rb +1 -1
- data/package.json +1 -1
- data/rakelib/release.rake +0 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbaf8ec483e9950e41d61c2e22b62b325113b00a
|
4
|
+
data.tar.gz: 6e2da43df3e19adaffa7ff8a386fd39faa55c4b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f716fc038e89ab1f26049d01bc9cfce53717cd40f0705c94a92906aee8f1f340b1b9e1eeb6adddfcf9bb4cc889de3b2638645b7fb78990b543fda4933c80b3c
|
7
|
+
data.tar.gz: 6befd861e58a261de37c42eb332156bd67b125dbbe0823e6d2a42a59b02c0cd8fe4ed5ea49ded2e97d438829d48a206ffe73bd4d03048d6fc595d19fd2d5649d
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. Items under
|
|
4
4
|
Contributors: please follow the recommendations outlined at [keepachangelog.com](http://keepachangelog.com/). Please use the existing headings and styling as a guide, and add a link for the version diff at the bottom of the file. Also, please update the `Unreleased` link to compare to the latest release version.
|
5
5
|
## [Unreleased]
|
6
6
|
|
7
|
+
## [4.0.0.rc.1] - 2016-03-06
|
8
|
+
##### Added
|
9
|
+
- Added controller `module ReactOnRails::Controller`. Adds method `redux_store` to setup redux stores in the view.
|
10
|
+
- Added view helper `redux_store_hydration_data` to render the props on the application's layout, near the bottom. This allows for the client hydration data to be parsed after the server rendering, which may result in a faster load time.
|
11
|
+
- Added helpers `env_stylesheet_link_tag` and `env_javascript_include_tag` to support hot reloading Rails. See the [README.md](./README.md) for more details and see the example application in `spec/dummy`.
|
12
|
+
- The checker for outdated bundles before running tests will default to including the directory with `server_bundle_js_file`.
|
13
|
+
|
14
|
+
##### Fixed
|
15
|
+
- The test runner assets up to date checker might see only the server rendering file, and assume that all assets are up to date.
|
16
|
+
- Lots of doc updates!
|
17
|
+
- Improved the **spec/dummy** sample app so that it supports CSS modules, hot reloading, etc, and it can server as a template for a new ReactOnRails installation.
|
18
|
+
|
19
|
+
##### Breaking Changes
|
20
|
+
- Deprecated `redux_store` called from views. Call this method from your controller actions and place `redux_store_hydration_data` on your layout, near the bottom.
|
21
|
+
- Removed the config default of the `config.server_bundle_js_file`. The default is blank, meaning no server rendering.
|
22
|
+
|
23
|
+
|
7
24
|
## [3.0.6] - 2016-03-01
|
8
25
|
##### Fixed
|
9
26
|
- Improved errors when registered store is not found. See [#301](https://github.com/shakacode/react_on_rails/pull/301) by [justin808](https://github.com/justin808).
|
@@ -192,7 +209,8 @@ Best done with Object destructing:
|
|
192
209
|
|
193
210
|
##### Fixed
|
194
211
|
- Fix several generator related issues.
|
195
|
-
[Unreleased]: https://github.com/shakacode/react_on_rails/compare/3.0.
|
212
|
+
[Unreleased]: https://github.com/shakacode/react_on_rails/compare/3.0.6...master
|
213
|
+
[3.0.6]: https://github.com/shakacode/react_on_rails/compare/3.0.5...3.0.6
|
196
214
|
[3.0.5]: https://github.com/shakacode/react_on_rails/compare/3.0.4...3.0.5
|
197
215
|
[3.0.4]: https://github.com/shakacode/react_on_rails/compare/3.0.3...3.0.4
|
198
216
|
[3.0.3]: https://github.com/shakacode/react_on_rails/compare/3.0.2...3.0.3
|
data/Gemfile
CHANGED
@@ -8,8 +8,6 @@ gemspec
|
|
8
8
|
# bundle install from a single Gemfile. Therefore, all gems that we will need for any dummy/example
|
9
9
|
# app have to be manually added to this file.
|
10
10
|
gem "bootstrap-sass"
|
11
|
-
gem "capybara"
|
12
|
-
gem "capybara-screenshot"
|
13
11
|
gem "chromedriver-helper"
|
14
12
|
gem "coffee-rails", "~> 4.1.0"
|
15
13
|
gem "jbuilder", "~> 2.0"
|
@@ -19,13 +17,11 @@ gem "poltergeist"
|
|
19
17
|
gem "puma"
|
20
18
|
gem "rails", "4.2.5"
|
21
19
|
gem "rails_12factor"
|
22
|
-
gem "rspec-rails"
|
23
20
|
gem "rubocop", require: false
|
24
21
|
gem "ruby-lint", require: false
|
25
22
|
gem "sass-rails", "~> 5.0"
|
26
23
|
gem "scss_lint", require: false
|
27
24
|
gem "sdoc", "~> 0.4.0", group: :doc
|
28
|
-
gem "selenium-webdriver"
|
29
25
|
gem "spring"
|
30
26
|
gem "sqlite3"
|
31
27
|
gem "therubyracer"
|
@@ -36,3 +32,15 @@ else
|
|
36
32
|
end
|
37
33
|
gem "uglifier", ">= 2.7.2"
|
38
34
|
gem "web-console", "~> 2.0", group: :development
|
35
|
+
|
36
|
+
# below are copied from spec/dummy/Gemfile
|
37
|
+
gem "rspec-rails"
|
38
|
+
gem "coveralls", require: false
|
39
|
+
gem "capybara"
|
40
|
+
gem "capybara-screenshot"
|
41
|
+
gem "capybara-webkit"
|
42
|
+
gem "chromedriver-helper"
|
43
|
+
gem "generator_spec"
|
44
|
+
gem "launchy"
|
45
|
+
gem "poltergeist"
|
46
|
+
gem "selenium-webdriver"
|
data/PROJECTS.md
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
* **[GuavaPass](https://guavapass.com/)**: Coaching client of [ShakaCode](http://www.shakacode.com) and React on Rails fan!
|
8
8
|
* **Friends and Guests**, the signature product of [ShakaCode](http://www.shakacode.com), which is a "Social Network Connecting Hosts and Guests". *Coming soon!*
|
9
9
|
* **[Madrone Analytics](http://madroneco.com/)**: The original client of [ShakaCode](http://www.shakacode.com) that led to the development of React on Rails, as described in [Fast Rich Client Rails Development With Webpack and the ES6 Transpiler](http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/).
|
10
|
+
* **[Pivotal Tracker](http://www.pivotaltracker.com/)**: The first (and most-loved) agile project management tool built on Rails. React on Rails has greatly simplified integration and workflow for our React components in Rails!
|
10
11
|
|
11
12
|
--------
|
12
13
|
|
data/README.md
CHANGED
@@ -75,7 +75,8 @@ Please see [Getting Started](#getting-started) for how to set up your Rails proj
|
|
75
75
|
- [Client-Side Rendering vs. Server-Side Rendering](#client-side-rendering-vs-server-side-rendering)
|
76
76
|
- [Building the Bundles](#building-the-bundles)
|
77
77
|
- [Globally Exposing Your React Components](#globally-exposing-your-react-components)
|
78
|
-
- [
|
78
|
+
- [ReactOnRails View Helpers API](#reactonrails-view-helpers-api)
|
79
|
+
- [ReactOnRails JavaScript API](#reactonrails-javascript-api)
|
79
80
|
- [Redux](#redux)
|
80
81
|
- [React-Router](#react-router)
|
81
82
|
+ [Generator](#generator)
|
@@ -220,12 +221,12 @@ Place your JavaScript code inside of the provided `client/app` folder. Use modul
|
|
220
221
|
|
221
222
|
In general, you may want different initialization for your server rendered components.
|
222
223
|
|
223
|
-
|
224
|
+
## ReactOnRails View Helpers API
|
224
225
|
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.
|
225
226
|
|
226
227
|
This is how you actually render the React components you exposed to `window` inside of `clientRegistration` (and `global` inside of `serverRegistration` if you are server rendering).
|
227
228
|
|
228
|
-
|
229
|
+
### react_component
|
229
230
|
`react_component(component_name, options = {})`
|
230
231
|
|
231
232
|
+ **component_name:** Can be a React component, created using a ES6 class, or `React.createClass`, or a generator function that returns a React component.
|
@@ -238,7 +239,10 @@ This is how you actually render the React components you exposed to `window` ins
|
|
238
239
|
+ **raise_on_prerender_error:** Default is false. True will throw an error on the server side rendering. Your controller will have to handle the error.
|
239
240
|
+ Any other options are passed to the content tag, including the id
|
240
241
|
|
241
|
-
|
242
|
+
### redux_store
|
243
|
+
#### Controller Extension
|
244
|
+
Include the module ReactOnRails::Controller in your controller, probably in ApplicationController. This will provide the following controller method, which you can call in your controller actions:
|
245
|
+
|
242
246
|
`redux_store(store_name, props = {})`
|
243
247
|
|
244
248
|
+ **store_name:** A name for the store. You'll refer to this name in 2 places in your JavaScript:
|
@@ -246,10 +250,23 @@ This is how you actually render the React components you exposed to `window` ins
|
|
246
250
|
2. In your component definition, you'll call `ReactOnRails.getStore('storeName')` to get the hydrated Redux store to attach to your components.
|
247
251
|
+ **props:** ReactOnRails takes care of setting up the hydration of your store with props from the view.
|
248
252
|
|
249
|
-
|
253
|
+
For an example, see [spec/dummy/app/controllers/pages_controller.rb](spec/dummy/app/controllers/pages_controller.rb).
|
254
|
+
|
255
|
+
#### View Helper
|
256
|
+
`redux_store_hydration_data`
|
257
|
+
|
258
|
+
Place this view helper (no parameters) at the end of your shared layout. This tell ReactOnRails where to client render the redux store hydration data. Since we're going to be setting up the stores in the controllers, we need to know where on the view to put the client side rendering of this hydration data, which is a hidden div with a matching class that contains a data props. For an example, see [spec/dummy/app/views/layouts/application.html.erb](spec/dummy/app/views/layouts/application.html.erb).
|
259
|
+
|
260
|
+
#### Redux Store Notes
|
261
|
+
Note, you don't need to separately initialize your redux store. However, it's recommended for the two following use cases:
|
262
|
+
|
263
|
+
1. You want to have multiple components that access the same store.
|
264
|
+
2. You want to place the props to hydrate the client side stores at the very end of your HTML, so the browser can render all earlier HTML first. This is particularly useful if your props will be large.
|
265
|
+
|
266
|
+
### Generator Functions
|
250
267
|
Why would you create a function that returns a React compnent? For example, you may want the ability to use the passed-in props to initialize a redux store or setup react-router. Or you may want to return different components depending on what's in the props. ReactOnRails will automatically detect a registered generator function.
|
251
268
|
|
252
|
-
|
269
|
+
### server_render_js
|
253
270
|
`server_render_js(js_expression, options = {})`
|
254
271
|
|
255
272
|
+ js_expression, like 2 + 3, and not a block of js code. If you have more than one line that needs to be executed, wrap it in an [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression). JS exceptions will be caught and console messages handled properly
|
@@ -257,8 +274,93 @@ Why would you create a function that returns a React compnent? For example, you
|
|
257
274
|
|
258
275
|
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.
|
259
276
|
|
277
|
+
## ReactOnRails JavaScript API
|
278
|
+
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!
|
279
|
+
|
280
|
+
```js
|
281
|
+
/**
|
282
|
+
* Main entry point to using the react-on-rails npm package. This is how Rails will be able to
|
283
|
+
* find you components for rendering.
|
284
|
+
* @param components (key is component name, value is component)
|
285
|
+
*/
|
286
|
+
register(components)
|
287
|
+
|
288
|
+
/**
|
289
|
+
* Allows registration of store generators to be used by multiple react components on one Rails
|
290
|
+
* view. store generators are functions that take one arg, props, and return a store. Note that
|
291
|
+
* the setStore API is different in tha it's the actual store hydrated with props.
|
292
|
+
* @param stores (key is store name, value is the store generator)
|
293
|
+
*/
|
294
|
+
registerStore(stores)
|
295
|
+
|
296
|
+
/**
|
297
|
+
* Allows retrieval of the store by name. This store will be hydrated by any Rails form props.
|
298
|
+
* Pass optional param throwIfMissing = false if you want to use this call to get back null if the
|
299
|
+
* store with name is not registered.
|
300
|
+
* @param name
|
301
|
+
* @param throwIfMissing Defaults to true. Set to false to have this call return undefined if
|
302
|
+
* there is no store with the given name.
|
303
|
+
* @returns Redux Store, possibly hydrated
|
304
|
+
*/
|
305
|
+
getStore(name, throwIfMissing = true )
|
306
|
+
|
307
|
+
/**
|
308
|
+
* Set options for ReactOnRails, typically before you call ReactOnRails.register
|
309
|
+
* Available Options:
|
310
|
+
* `traceTurbolinks: true|false Gives you debugging messages on Turbolinks events
|
311
|
+
*/
|
312
|
+
setOptions(options)
|
313
|
+
```
|
314
|
+
|
315
|
+
## Hot Reloading View Helpers
|
316
|
+
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.
|
317
|
+
|
318
|
+
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.
|
319
|
+
|
320
|
+
static vs. hot is picked based on whether ENV["REACT_ON_RAILS_ENV"] == "HOT"
|
321
|
+
|
322
|
+
```erb
|
323
|
+
<%= env_stylesheet_link_tag(static: 'application_static',
|
324
|
+
hot: 'application_non_webpack',
|
325
|
+
media: 'all',
|
326
|
+
'data-turbolinks-track' => true) %>
|
327
|
+
|
328
|
+
<!-- These do not use turbolinks, so no data-turbolinks-track -->
|
329
|
+
<!-- This is to load the hot assets. -->
|
330
|
+
<%= env_javascript_include_tag(hot: ['http://localhost:3500/vendor-bundle.js',
|
331
|
+
'http://localhost:3500/app-bundle.js']) %>
|
332
|
+
|
333
|
+
<!-- These do use turbolinks -->
|
334
|
+
<%= env_javascript_include_tag(static: 'application_static',
|
335
|
+
hot: 'application_non_webpack',
|
336
|
+
'data-turbolinks-track' => true) %>
|
337
|
+
```
|
338
|
+
|
339
|
+
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)
|
340
|
+
|
341
|
+
**env_javascript_include_tag(args = {})**
|
342
|
+
|
343
|
+
Helper to set CSS assets depending on if we want static or "hot", which means from the Webpack dev server.
|
344
|
+
|
345
|
+
In this example, application_non_webpack is simply a CSS asset pipeline file which includes styles not placed in the webpack build.
|
346
|
+
|
347
|
+
We don't need styles from the webpack build, as those will come via the JavaScript include tags.
|
348
|
+
|
349
|
+
The key options are `static` and `hot` which specify what you want for static vs. hot. Both of
|
350
|
+
these params are optional, and support either a single value, or an array.
|
351
|
+
|
352
|
+
```erb
|
353
|
+
<%= env_stylesheet_link_tag(static: 'application_static',
|
354
|
+
hot: 'application_non_webpack',
|
355
|
+
media: 'all',
|
356
|
+
'data-turbolinks-track' => true) %>
|
357
|
+
```
|
358
|
+
|
359
|
+
**env_stylesheet_link_tag(args = {})**
|
360
|
+
|
361
|
+
|
260
362
|
## Generator
|
261
|
-
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`
|
363
|
+
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.
|
262
364
|
|
263
365
|
Run `rails generate react_on_rails:install --help` for descriptions of all available options:
|
264
366
|
|
@@ -380,7 +482,7 @@ Bootstrap integration is enabled by default, but can be disabled by passing the
|
|
380
482
|
The React on Rails generator can add linters and their recommended accompanying configurations to your project. There are two classes of linters: ruby linters and JavaScript linters.
|
381
483
|
|
382
484
|
##### JavaScript Linters
|
383
|
-
JavaScript linters are **enabled by default**, but can be disabled by passing the `--skip-js-linters` flag (alias `j`) , and those that run in Node have been
|
485
|
+
JavaScript linters are **enabled by default**, but can be disabled by passing the `--skip-js-linters` flag (alias `j`) , and those that run in Node have been added to `client/package.json` under `devDependencies`.
|
384
486
|
|
385
487
|
##### Ruby Linters
|
386
488
|
Ruby linters are **disabled by default**, but can be enabled by passing the `--ruby-linters` flag when generating. These linters have been added to your Gemfile in addition to the appropriate Rake tasks.
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# rubocop:disable Metrics/ModuleLength
|
1
2
|
# NOTE:
|
2
3
|
# For any heredoc JS:
|
3
4
|
# 1. The white spacing in this file matters!
|
@@ -5,6 +6,57 @@
|
|
5
6
|
require "react_on_rails/prerender_error"
|
6
7
|
|
7
8
|
module ReactOnRailsHelper
|
9
|
+
# The env_javascript_include_tag and env_stylesheet_link_tag support the usage of a webpack
|
10
|
+
# dev server for providing the JS and CSS assets during development mode. See
|
11
|
+
# https://github.com/shakacode/react-webpack-rails-tutorial/ for a working example.
|
12
|
+
#
|
13
|
+
# The key options are `static` and `hot` which specify what you want for static vs. hot. Both of
|
14
|
+
# these params are optional, and support either a single value, or an array.
|
15
|
+
#
|
16
|
+
# static vs. hot is picked based on whether
|
17
|
+
# ENV["REACT_ON_RAILS_ENV"] == "HOT"
|
18
|
+
#
|
19
|
+
# <%= env_stylesheet_link_tag(static: 'application_static',
|
20
|
+
# hot: 'application_non_webpack',
|
21
|
+
# media: 'all',
|
22
|
+
# 'data-turbolinks-track' => true) %>
|
23
|
+
#
|
24
|
+
# <!-- These do not use turbolinks, so no data-turbolinks-track -->
|
25
|
+
# <!-- This is to load the hot assets. -->
|
26
|
+
# <%= env_javascript_include_tag(hot: ['http://localhost:3500/vendor-bundle.js',
|
27
|
+
# 'http://localhost:3500/app-bundle.js']) %>
|
28
|
+
#
|
29
|
+
# <!-- These do use turbolinks -->
|
30
|
+
# <%= env_javascript_include_tag(static: 'application_static',
|
31
|
+
# hot: 'application_non_webpack',
|
32
|
+
# 'data-turbolinks-track' => true) %>
|
33
|
+
# See application.html.erb for usage example
|
34
|
+
# https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/app%2Fviews%2Flayouts%2Fapplication.html.erb
|
35
|
+
def env_javascript_include_tag(args = {})
|
36
|
+
send_tag_method(:javascript_include_tag, args)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Helper to set CSS assets depending on if we want static or "hot", which means from the
|
40
|
+
# Webpack dev server.
|
41
|
+
#
|
42
|
+
# In this example, application_non_webpack is simply a CSS asset pipeline file which includes
|
43
|
+
# styles not placed in the webpack build.
|
44
|
+
#
|
45
|
+
# We don't need styles from the webpack build, as those will come via the JavaScript include
|
46
|
+
# tags.
|
47
|
+
#
|
48
|
+
# The key options are `static` and `hot` which specify what you want for static vs. hot. Both of
|
49
|
+
# these params are optional, and support either a single value, or an array.
|
50
|
+
#
|
51
|
+
# <%= env_stylesheet_link_tag(static: 'application_static',
|
52
|
+
# hot: 'application_non_webpack',
|
53
|
+
# media: 'all',
|
54
|
+
# 'data-turbolinks-track' => true) %>
|
55
|
+
#
|
56
|
+
def env_stylesheet_link_tag(args = {})
|
57
|
+
send_tag_method(:stylesheet_link_tag, args)
|
58
|
+
end
|
59
|
+
|
8
60
|
# react_component_name: can be a React component, created using a ES6 class, or
|
9
61
|
# React.createClass, or a
|
10
62
|
# `generator function` that returns a React component
|
@@ -89,28 +141,41 @@ module ReactOnRailsHelper
|
|
89
141
|
# IMPORTANT: Ensure that we mark string as html_safe to avoid escaping.
|
90
142
|
<<-HTML.html_safe
|
91
143
|
#{component_specification_tag}
|
92
|
-
#{rendered_output}
|
93
|
-
#{replay_console(options) ? console_script : ''}
|
144
|
+
#{rendered_output}
|
145
|
+
#{replay_console(options) ? console_script : ''}
|
94
146
|
HTML
|
95
147
|
end
|
96
148
|
|
149
|
+
# Deprecated: Use `redux_store` via including ReactOnRails::Controller in your controller and calling
|
150
|
+
# redux_store.
|
151
|
+
#
|
97
152
|
# Separate initialization of store from react_component allows multiple react_component calls to
|
98
153
|
# use the same Redux store.
|
99
154
|
#
|
100
155
|
# store_name: name of the store, corresponding to your call to ReactOnRails.registerStores in your
|
101
156
|
# JavaScript code.
|
102
|
-
# props: Ruby Hash or JSON string which contains the properties to pass to the redux
|
157
|
+
# props: Ruby Hash or JSON string which contains the properties to pass to the redux store.
|
103
158
|
def redux_store(store_name, props = {})
|
159
|
+
warn "[DEPRECATION] `redux_store` within a view is deprecated. Please move to call "\
|
160
|
+
"to redux store to your controller action."
|
104
161
|
redux_store_data = { store_name: store_name,
|
105
162
|
props: props }
|
106
163
|
@registered_stores ||= []
|
107
164
|
@registered_stores << redux_store_data
|
108
165
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
166
|
+
render_redux_store_data(redux_store_data)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Place this view helper (no parameters) at the end of your shared layout. This tell
|
170
|
+
# ReactOnRails where to client render the redux store hydration data. Since we're going
|
171
|
+
# to be setting up the stores in the controllers, we need to know where on the view to put the
|
172
|
+
# client side rendering of this hydration data, which is a hidden div with a matching class
|
173
|
+
# that contains a data props.
|
174
|
+
def redux_store_hydration_data
|
175
|
+
return if @registered_stores_via_controller.blank?
|
176
|
+
@registered_stores_via_controller.reduce("") do |accum, redux_store_data|
|
177
|
+
accum << render_redux_store_data(redux_store_data)
|
178
|
+
end.html_safe
|
114
179
|
end
|
115
180
|
|
116
181
|
def sanitized_props_string(props)
|
@@ -165,6 +230,14 @@ module ReactOnRailsHelper
|
|
165
230
|
|
166
231
|
private
|
167
232
|
|
233
|
+
def render_redux_store_data(redux_store_data)
|
234
|
+
content_tag(:div,
|
235
|
+
"",
|
236
|
+
class: "js-react-on-rails-store",
|
237
|
+
style: ReactOnRails.configuration.skip_display_none ? nil : "display:none",
|
238
|
+
data: redux_store_data)
|
239
|
+
end
|
240
|
+
|
168
241
|
def next_react_component_index
|
169
242
|
@react_component_index ||= -1
|
170
243
|
@react_component_index += 1
|
@@ -206,12 +279,12 @@ module ReactOnRailsHelper
|
|
206
279
|
if result["hasErrors"] && raise_on_prerender_error(options)
|
207
280
|
# We caught this exception on our backtrace handler
|
208
281
|
# rubocop:disable Style/RaiseArgs
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
282
|
+
raise ReactOnRails::PrerenderError.new(component_name: react_component_name,
|
283
|
+
# Sanitize as this might be browser logged
|
284
|
+
props: sanitized_props_string(props),
|
285
|
+
err: nil,
|
286
|
+
js_code: wrapper_js,
|
287
|
+
console_messages: result["consoleReplayScript"])
|
215
288
|
# rubocop:enable Style/RaiseArgs
|
216
289
|
end
|
217
290
|
result
|
@@ -227,9 +300,12 @@ module ReactOnRailsHelper
|
|
227
300
|
end
|
228
301
|
|
229
302
|
def initialize_redux_stores
|
230
|
-
return "" unless @registered_stores.present?
|
303
|
+
return "" unless @registered_stores.present? || @registered_stores_via_controller.present?
|
231
304
|
declarations = "var reduxProps, store, storeGenerator;\n"
|
232
|
-
|
305
|
+
|
306
|
+
all_stores = (@registered_stores || []) + (@registered_stores_via_controller || [])
|
307
|
+
|
308
|
+
result = all_stores.each_with_object(declarations) do |redux_store_data, memo|
|
233
309
|
store_name = redux_store_data[:store_name]
|
234
310
|
props = props_string(redux_store_data[:props])
|
235
311
|
memo << <<-JS
|
@@ -290,4 +366,15 @@ ReactOnRails.setStore('#{store_name}', store);
|
|
290
366
|
end
|
291
367
|
[final_options, props]
|
292
368
|
end
|
369
|
+
|
370
|
+
def use_hot_reloading?
|
371
|
+
ENV["REACT_ON_RAILS_ENV"] == "HOT"
|
372
|
+
end
|
373
|
+
|
374
|
+
def send_tag_method(tag_method_name, args)
|
375
|
+
asset_type = use_hot_reloading? ? :hot : :static
|
376
|
+
assets = Array(args[asset_type])
|
377
|
+
options = args.delete_if { |key, _value| %i(hot static).include?(key) }
|
378
|
+
send(tag_method_name, *assets, options) unless assets.empty?
|
379
|
+
end
|
293
380
|
end
|
@@ -18,9 +18,9 @@ Assuming you have downloaded and installed the Heroku command-line utility and h
|
|
18
18
|
heroku buildpacks:set https://github.com/heroku/heroku-buildpack-multi
|
19
19
|
```
|
20
20
|
|
21
|
-
Heroku will now be able to use the multiple buildpacks specified in `.buildpacks`.
|
21
|
+
Heroku will now be able to use the multiple buildpacks specified in `.buildpacks`.
|
22
22
|
|
23
|
-
|
23
|
+
For more information, see [Using Multiple Buildpacks for an App](https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app)
|
24
24
|
|
25
25
|
## Fresh Rails Install
|
26
26
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Hot Reloading of Assets For Rails Development
|
2
|
+
|
3
|
+
This document outlines the steps to setup your React On Rails Environment so that you can experience the pleasure of hot reloading of JavaScript and Sass during your Rails development work. There are 2 examples of this setup:
|
4
|
+
1. [spec/dummy](../spec/dummy): Simpler setup used for integration testing this gem.
|
5
|
+
1. [shakacode/react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/). Full featured setup using Twitter bootstrap.
|
6
|
+
|
7
|
+
## High Level Strategy
|
8
|
+
|
9
|
+
We'll use a Webpack Dev server on port 3500 to provide the assets to Rails, rather than the asset pipeline, and only during development mode. This is configured via the `Procfile.hot`.
|
10
|
+
|
11
|
+
`Procfile.static` provides an alternative that uses "static" assets, similar to a production deployment.
|
12
|
+
|
13
|
+
The secret sauce is in the [app/views/layouts/application.html.erb](spec/dummy/app/views/layouts/application.html.erb) where it uses view helpes to configure the correct assets to load, being either the "hot" assets or the "static" assets.
|
14
|
+
|
15
|
+
## Places to Configure (Files to Examine)
|
16
|
+
|
17
|
+
1. See the Webpack config files. Note, these examples are now setup for using [CSS Modules](https://github.com/css-modules/css-modules).
|
18
|
+
1. [client/webpack.client.base.config.js](spec/dummy/client/webpack.client.base.config.js): Common configuration for hot or static assets.
|
19
|
+
1. [client/webpack.client.hot.config.js](spec/dummy/client/webpack.client.hot.config.js): Setup for hot loading, using react-transform-hmr.
|
20
|
+
1. [client/webpack.client.static.config.js](spec/dummy/client/webpack.client.static.config.js): Setup for static loading, as is done in a production deployment.
|
21
|
+
1. [app/views/layouts/application.html.erb](spec/dummy/app/views/layouts/application.html.erb): Uses the view helpers `env_stylesheet_link_tag` and `env_javascript_include_tag` which will either do the hot reloading or the static loading.
|
22
|
+
1. See the Procfiles: [Procfile.hot](spec/dummy/Procfile.hot) and [Procfile.static](spec/dummy/Procfile.static). These:
|
23
|
+
1. Start the webpack processes, depending on the mode or HOT or not.
|
24
|
+
2. Start the rails server, setting an ENV value of REACT_ON_RAILS_ENV to HOT if we're hot loading or else setting this to blank.
|
25
|
+
1. Configure the file Rails asset pipeline files:
|
26
|
+
1. [app/assets/javascripts/application_static.js.erb](spec/dummy/app/assets/javascripts/application_static.js.erb): We have to only specify the `vendor-bundle` and `app-bundle` if we're not HOT loading, as Sprockets will throw an error if that is the case. Note the use of `require_asset`.
|
27
|
+
1. [app/assets/stylesheets/application_static.js.erb](spec/dummy/app/assets/stylesheets/application_static.scss.erb): We have to only specify the `vendor-bundle` and `app-bundle` if we're not HOT loading, as Sprockets will throw an error if that is the case. Note the conditional around the @import.
|
28
|
+
1. Be sure your [config/initializers/assets.rb](spec/dummy/config/initializers/assets.rb) is configured to include the webpack generated files.
|
29
|
+
1. Copy the [client/server-rails-hot.js](spec/dummy/client/server-rails-hot.js) to the [client](client) directory.
|
30
|
+
1. Copy the scripts in the top level and client level `package.json` files:
|
31
|
+
1. Top Level: [package.json](spec/dummy/package.json)
|
32
|
+
1. Client Level: [package.json](spec/dummy/client/package.json)
|
data/lib/generators/USAGE
CHANGED
@@ -2,9 +2,9 @@ Description:
|
|
2
2
|
|
3
3
|
The react_on_rails:install generator combined with the example pull requests of
|
4
4
|
generator runs will get you up and running efficiently. There's a fair bit of
|
5
|
-
setup involved when
|
5
|
+
setup involved when integrating Webpack with Rails. Defaults for options
|
6
6
|
are such that the default is for the flag to be off. For example, the default for
|
7
|
-
`-R` is that redux is off, and the default of -b
|
7
|
+
`-R` is that redux is off, and the default of -b is that skip-bootstrap is off.
|
8
8
|
|
9
9
|
* Redux
|
10
10
|
|
@@ -83,7 +83,7 @@ are such that the default is for the flag to be off. For example, the default fo
|
|
83
83
|
* JavaScript Linters
|
84
84
|
|
85
85
|
JavaScript linters are enabled by default, but can be disabled by passing the
|
86
|
-
--skip-js-linters flag (alias j), and those that run in Node have been
|
86
|
+
--skip-js-linters flag (alias j), and those that run in Node have been added to
|
87
87
|
`client/package.json` under devDependencies.
|
88
88
|
|
89
89
|
* Ruby Linters
|
data/lib/react_on_rails.rb
CHANGED
@@ -4,14 +4,13 @@ module ReactOnRails
|
|
4
4
|
end
|
5
5
|
|
6
6
|
DEFAULT_GENERATED_ASSETS_DIRS = [
|
7
|
-
%w(app assets
|
8
|
-
%w(app assets javascripts stylesheets generated)
|
7
|
+
%w(app assets webpack)
|
9
8
|
].map { |dirs| File.join(*dirs) }.freeze
|
10
9
|
|
11
10
|
def self.configuration
|
12
11
|
@configuration ||= Configuration.new(
|
13
12
|
generated_assets_dirs: DEFAULT_GENERATED_ASSETS_DIRS,
|
14
|
-
server_bundle_js_file:
|
13
|
+
server_bundle_js_file: "",
|
15
14
|
prerender: false,
|
16
15
|
replay_console: true,
|
17
16
|
logging_on_server: true,
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ReactOnRails
|
2
|
+
module Controller
|
3
|
+
# Separate initialization of store from react_component allows multiple react_component calls to
|
4
|
+
# use the same Redux store.
|
5
|
+
#
|
6
|
+
# store_name: name of the store, corresponding to your call to ReactOnRails.registerStores in your
|
7
|
+
# JavaScript code.
|
8
|
+
# props: Ruby Hash or JSON string which contains the properties to pass to the redux store.
|
9
|
+
#
|
10
|
+
# Be sure to include view helper `redux_store_hydration_data` at the end of your layout or view
|
11
|
+
# or else there will be no client side hydration of your stores.
|
12
|
+
def redux_store(store_name, props)
|
13
|
+
redux_store_data = { store_name: store_name,
|
14
|
+
props: props }
|
15
|
+
@registered_stores_via_controller ||= []
|
16
|
+
@registered_stores_via_controller << redux_store_data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -38,20 +38,39 @@ module ReactOnRails
|
|
38
38
|
# defaults to ReactOnRails::TestHelper::WebpackProcessChecker
|
39
39
|
# webpack_assets_compiler: provide one method: `def compile`
|
40
40
|
# defaults to ReactOnRails::TestHelper::WebpackAssetsCompiler
|
41
|
+
# server_bundle_js_file: The server rendering file, defaulting to server_bundle_js_file in
|
42
|
+
# your config
|
41
43
|
# client_dir and compiled_dirs are passed into the default webpack_assets_status_checker if you
|
42
44
|
# don't provide one.
|
43
45
|
def self.ensure_assets_compiled(webpack_assets_status_checker: nil,
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
webpack_assets_compiler: nil,
|
47
|
+
webpack_process_checker: nil,
|
48
|
+
client_dir: nil,
|
49
|
+
compiled_dirs: nil,
|
50
|
+
server_bundle_js_file: nil)
|
48
51
|
|
49
52
|
if webpack_assets_status_checker.nil?
|
50
53
|
client_dir ||= Rails.root.join("client")
|
51
54
|
compiled_dirs ||= ReactOnRails.configuration.generated_assets_dirs
|
55
|
+
server_bundle_js_file ||= ReactOnRails.configuration.server_bundle_js_file
|
56
|
+
|
57
|
+
if server_bundle_js_file.present?
|
58
|
+
dir = File.dirname(server_bundle_js_file)
|
59
|
+
compiled_dirs ||= []
|
60
|
+
compiled_dirs << dir unless compiled_dirs.include?(dir)
|
61
|
+
end
|
52
62
|
webpack_assets_status_checker ||=
|
53
63
|
WebpackAssetsStatusChecker.new(client_dir: client_dir,
|
54
|
-
compiled_dirs: compiled_dirs
|
64
|
+
compiled_dirs: compiled_dirs,
|
65
|
+
server_bundle_js_file: server_bundle_js_file)
|
66
|
+
|
67
|
+
unless @printed_once
|
68
|
+
puts
|
69
|
+
puts "====> React On Rails: Checking dirs for outdated/missing bundles: "\
|
70
|
+
"#{webpack_assets_status_checker.compiled_dirs}"
|
71
|
+
puts
|
72
|
+
@printed_once = true
|
73
|
+
end
|
55
74
|
end
|
56
75
|
|
57
76
|
webpack_assets_compiler ||= WebpackAssetsCompiler.new
|
@@ -53,8 +53,11 @@ module ReactOnRails
|
|
53
53
|
def puts_max_iterations_message(loop_count)
|
54
54
|
if loop_count == MAX_TIME_TO_WAIT
|
55
55
|
stale_files = webpack_assets_status_checker.whats_not_up_to_date.join("\n")
|
56
|
-
|
57
|
-
|
56
|
+
if stale_files.empty?
|
57
|
+
puts "Please check your config value for `config.generated_assets_dirs`."
|
58
|
+
puts "We're not finding your generated files for test runs."
|
59
|
+
else
|
60
|
+
puts <<-MSG
|
58
61
|
|
59
62
|
Even though we detected the webpack watch processes are running, we found files modified that are
|
60
63
|
not causing a rebuild of your generated files:
|
@@ -66,6 +69,7 @@ your webpack files: #{webpack_assets_status_checker.client_dir}
|
|
66
69
|
|
67
70
|
To be sure, we will now rebuild your generated files.
|
68
71
|
MSG
|
72
|
+
end
|
69
73
|
end
|
70
74
|
end
|
71
75
|
end
|
@@ -24,7 +24,7 @@ https://github.com/shakacode/react_on_rails/blob/master/docs/additional_reading/
|
|
24
24
|
|
25
25
|
build_output = `cd client && npm run build:#{type}`
|
26
26
|
|
27
|
-
|
27
|
+
raise "Error in building assets!\n#{build_output}" unless Utils.last_process_completed_successfully?
|
28
28
|
|
29
29
|
puts "Completed building Webpack #{type}-rendering assets."
|
30
30
|
end
|
@@ -6,16 +6,16 @@ require "fileutils"
|
|
6
6
|
module ReactOnRails
|
7
7
|
module TestHelper
|
8
8
|
class WebpackAssetsStatusChecker
|
9
|
-
attr_reader :client_dir, :compiled_dirs
|
9
|
+
attr_reader :client_dir, :compiled_dirs, :server_bundle_js_file
|
10
10
|
|
11
11
|
def initialize(args = {})
|
12
12
|
@compiled_dirs = args.fetch(:compiled_dirs)
|
13
13
|
@client_dir = args.fetch(:client_dir)
|
14
|
+
@server_bundle_js_file = args.fetch(:server_bundle_js_file)
|
14
15
|
@last_stale_files = ""
|
15
16
|
end
|
16
17
|
|
17
18
|
def up_to_date?
|
18
|
-
# binding.pry
|
19
19
|
return false unless assets_exist?
|
20
20
|
all_compiled_assets.all? do |asset|
|
21
21
|
FileUtils.uptodate?(asset, client_files)
|
@@ -46,7 +46,11 @@ module ReactOnRails
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def all_compiled_assets
|
49
|
-
make_file_list(make_globs(compiled_dirs)).to_ary
|
49
|
+
file_list = make_file_list(make_globs(compiled_dirs)).to_ary
|
50
|
+
if file_list && !file_list.empty?
|
51
|
+
file_list.delete(server_bundle_js_file)
|
52
|
+
end
|
53
|
+
file_list
|
50
54
|
end
|
51
55
|
|
52
56
|
def client_files
|
@@ -58,12 +62,12 @@ module ReactOnRails
|
|
58
62
|
end
|
59
63
|
|
60
64
|
def assets_exist?
|
61
|
-
all_compiled_assets.
|
65
|
+
!all_compiled_assets.empty?
|
62
66
|
end
|
63
67
|
|
64
68
|
def make_file_list(glob)
|
65
69
|
FileList.new(glob) do |fl|
|
66
|
-
fl.exclude(%r{/node_modules
|
70
|
+
fl.exclude(%r{/node_modules})
|
67
71
|
fl.exclude(".DS_Store")
|
68
72
|
fl.exclude(".keep")
|
69
73
|
fl.exclude("thumbs.db")
|
@@ -22,7 +22,7 @@ module ReactOnRails
|
|
22
22
|
# We only want to do this if server rendering is enabled.
|
23
23
|
def fail_if_only_running_for_one_type(client_running, server_running)
|
24
24
|
return unless client_running ^ server_running
|
25
|
-
|
25
|
+
raise "\n\nError: detected webpack is not running for both types of assets:\n"\
|
26
26
|
"***Webpack Client Process Running?: #{client_running}\n"\
|
27
27
|
"***Webpack Server Process Running?: #{server_running}"
|
28
28
|
end
|
data/package.json
CHANGED
data/rakelib/release.rake
CHANGED
@@ -32,7 +32,6 @@ task :release, [:gem_version, :dry_run, :tools_install] do |_t, args|
|
|
32
32
|
args_hash = args.to_hash
|
33
33
|
|
34
34
|
is_dry_run = ReactOnRails::Utils.object_to_boolean(args_hash[:dry_run])
|
35
|
-
should_install_tools = ReactOnRails::Utils.object_to_boolean(args_hash.fetch(:tools_install, true))
|
36
35
|
|
37
36
|
gem_version = args_hash.fetch(:gem_version, "")
|
38
37
|
|
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:
|
4
|
+
version: 4.0.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Gordon
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: connection_pool
|
@@ -319,6 +319,7 @@ files:
|
|
319
319
|
- docs/LICENSE
|
320
320
|
- docs/additional_reading/babel.md
|
321
321
|
- docs/additional_reading/heroku_deployment.md
|
322
|
+
- docs/additional_reading/hot-reloading-rails-development.md
|
322
323
|
- docs/additional_reading/manual_installation.md
|
323
324
|
- docs/additional_reading/node_dependencies_and_npm.md
|
324
325
|
- docs/additional_reading/optional_configuration.md
|
@@ -409,6 +410,7 @@ files:
|
|
409
410
|
- lib/generators/react_on_rails/templates/ruby_linters/ruby-lint.yml.tt
|
410
411
|
- lib/react_on_rails.rb
|
411
412
|
- lib/react_on_rails/configuration.rb
|
413
|
+
- lib/react_on_rails/controller.rb
|
412
414
|
- lib/react_on_rails/engine.rb
|
413
415
|
- lib/react_on_rails/git_utils.rb
|
414
416
|
- lib/react_on_rails/prerender_error.rb
|
@@ -455,9 +457,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
455
457
|
version: '0'
|
456
458
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
457
459
|
requirements:
|
458
|
-
- - "
|
460
|
+
- - ">"
|
459
461
|
- !ruby/object:Gem::Version
|
460
|
-
version:
|
462
|
+
version: 1.3.1
|
461
463
|
requirements: []
|
462
464
|
rubyforge_project:
|
463
465
|
rubygems_version: 2.4.8
|