react_on_rails 12.0.0 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +12 -2
- data/.eslintrc +2 -1
- data/.github/workflows/lint-js-and-ruby.yml +53 -0
- data/.github/workflows/main.yml +178 -0
- data/.github/workflows/package-js-tests.yml +35 -0
- data/.github/workflows/rspec-package-specs.yml +45 -0
- data/.prettierrc +0 -3
- data/.rubocop.yml +47 -38
- data/.travis.yml +8 -4
- data/CHANGELOG.md +58 -28
- data/CONTRIBUTING.md +4 -3
- data/Gemfile +1 -33
- data/Gemfile.development_dependencies +51 -0
- data/NEWS.md +5 -0
- data/README.md +116 -105
- data/SUMMARY.md +1 -1
- data/docs/{basics → additional-details}/generator-details.md +1 -6
- data/docs/{outdated → additional-details}/manual-installation-overview.md +6 -6
- data/docs/additional-details/recommended-project-structure.md +69 -0
- data/docs/additional-details/upgrade-webpacker-v3-to-v4.md +10 -0
- data/docs/api/javascript-api.md +5 -5
- data/docs/api/redux-store-api.md +5 -5
- data/docs/api/view-helpers-api.md +11 -12
- data/docs/basics/client-vs-server-rendering.md +4 -2
- data/docs/basics/configuration.md +43 -26
- data/docs/basics/deployment.md +2 -2
- data/docs/basics/hmr-and-hot-reloading-with-the-webpack-dev-server.md +64 -9
- data/docs/{outdated → basics}/how-react-on-rails-works.md +8 -9
- data/docs/basics/installation-into-an-existing-rails-app.md +13 -6
- data/docs/basics/react-server-rendering.md +8 -5
- data/docs/basics/render-functions-and-railscontext.md +1 -1
- data/docs/basics/rspec-configuration.md +10 -10
- data/docs/{tutorial.md → basics/tutorial.md} +28 -30
- data/docs/basics/upgrading-react-on-rails.md +52 -15
- data/docs/basics/webpack-configuration.md +14 -22
- data/docs/contributor-info/linters.md +5 -6
- data/docs/contributor-info/pull-requests.md +2 -4
- data/docs/contributor-info/releasing.md +1 -1
- data/docs/home.md +382 -0
- data/docs/{outdated → javascript}/code-splitting.md +8 -8
- data/docs/javascript/converting-from-custom-webpack-config-to-rails-webpacker-config.md +10 -0
- data/docs/{additional-reading → javascript}/images.md +5 -6
- data/docs/{additional-reading → javascript}/react-router.md +1 -1
- data/docs/{additional-reading → javascript}/server-rendering-tips.md +4 -1
- data/docs/{articles.md → misc/articles.md} +1 -1
- data/docs/misc/doctrine.md +5 -6
- data/docs/outdated/deferred-rendering.md +39 -0
- data/docs/outdated/rails-assets-relative-paths.md +3 -3
- data/docs/outdated/rails-assets.md +8 -8
- data/docs/outdated/rails3.md +2 -2
- data/docs/{additional-reading → rails}/convert-rails-5-api-only-app.md +1 -1
- data/docs/rails-webpacker-react-integration-options.md +182 -0
- data/docs/testimonials/testimonials.md +6 -6
- data/lib/generators/react_on_rails/base_generator.rb +8 -1
- data/lib/generators/react_on_rails/dev_tests_generator.rb +1 -1
- data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +8 -2
- data/lib/generators/react_on_rails/templates/dev_tests/spec/simplecov_helper.rb +1 -1
- data/lib/generators/react_on_rails/templates/dev_tests/spec/{features → system}/hello_world_spec.rb +2 -2
- data/lib/react_on_rails/configuration.rb +2 -0
- data/lib/react_on_rails/git_utils.rb +3 -3
- data/lib/react_on_rails/helper.rb +23 -17
- data/lib/react_on_rails/locales/base.rb +3 -3
- data/lib/react_on_rails/locales/to_js.rb +0 -4
- data/lib/react_on_rails/locales/to_json.rb +0 -4
- data/lib/react_on_rails/prerender_error.rb +1 -1
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +6 -6
- data/lib/react_on_rails/test_helper/webpack_assets_compiler.rb +1 -1
- data/lib/react_on_rails/test_helper.rb +2 -0
- data/lib/react_on_rails/utils.rb +24 -4
- data/lib/react_on_rails/version.rb +1 -1
- data/lib/react_on_rails/webpacker_utils.rb +9 -5
- data/lib/tasks/assets.rake +35 -14
- data/package.json +24 -29
- data/rakelib/docker.rake +0 -5
- data/rakelib/examples.rake +1 -1
- data/rakelib/lint.rake +4 -10
- data/rakelib/release.rake +28 -16
- data/rakelib/run_rspec.rake +10 -11
- data/rakelib/task_helpers.rb +16 -4
- data/react_on_rails.gemspec +3 -17
- data/yarn.lock +2272 -4960
- metadata +50 -224
- data/docs/additional-reading/upgrade-webpacker-v3-to-v4.md +0 -10
- data/docs/additional-reading/webpack-dev-server.md +0 -15
- data/docs/basics/recommended-project-structure.md +0 -77
- data/ruby-lint.yml +0 -25
- /data/docs/{basics → additional-details}/migrating-from-react-rails.md +0 -0
- /data/docs/{additional-reading → additional-details}/updating-dependencies.md +0 -0
- /data/docs/{additional-reading → deployment}/elastic-beanstalk.md +0 -0
- /data/docs/{basics → deployment}/heroku-deployment.md +0 -0
- /data/docs/{additional-reading → javascript}/angular-js-integration-migration.md +0 -0
- /data/docs/{additional-reading → javascript}/asset-pipeline.md +0 -0
- /data/docs/{additional-reading → javascript}/capistrano-deployment.md +0 -0
- /data/docs/{additional-reading → javascript}/credits.md +0 -0
- /data/docs/{additional-reading → javascript}/foreman-issues.md +0 -0
- /data/docs/{additional-reading → javascript}/node-dependencies-and-npm.md +0 -0
- /data/docs/{additional-reading → javascript}/react-and-redux.md +0 -0
- /data/docs/{additional-reading → javascript}/react-helmet.md +0 -0
- /data/docs/{additional-reading → javascript}/troubleshooting-when-using-webpacker.md +0 -0
- /data/docs/{additional-reading → javascript}/webpack-v1-notes.md +0 -0
- /data/docs/{additional-reading → javascript}/webpack.md +0 -0
- /data/docs/{coding-style → misc}/style.md +0 -0
- /data/docs/{additional-reading → misc}/tips.md +0 -0
- /data/docs/{additional-reading → rails}/rails-engine-integration.md +0 -0
- /data/docs/{additional-reading → rails}/rails_view_rendering_from_inline_javascript.md +0 -0
- /data/docs/{additional-reading → rails}/turbolinks.md +0 -0
|
@@ -77,7 +77,7 @@ Note: _You can output these files in the asset pipeline wherever you see fit. My
|
|
|
77
77
|
|
|
78
78
|
Lastly, we will set the publicPath to our file(s). This will be the endpoint on our rails web server that you can visit to reach the asset (if you don't know how this works, read the [intro](#using-webpack-bundled-assets-with-the-rails-asset-pipeline)). If you've been following the previous steps, you know that we set our outputPath for our assets to be absolute at `app/assets/webpack/webpack-assets/`, which your rails app should end up hosting at `/assets/webpack-assets/file-name+hash.ext` when the server is run.
|
|
79
79
|
|
|
80
|
-
Note: _If you're having a hard time figuring out what an asset's path will be on your rails server, simply run `rake assets:precompile` and `cd public/`. The path from there to your file will then be the path/url on your web server to that asset. On top of this, it is also a good idea to check out [this doc](docs/outdated/rails-assets
|
|
80
|
+
Note: _If you're having a hard time figuring out what an asset's path will be on your rails server, simply run `rake assets:precompile` and `cd public/`. The path from there to your file will then be the path/url on your web server to that asset. On top of this, it is also a good idea to check out [this doc](https://www.shakacode.com/react-on-rails/docs/outdated/rails-assets) to understand how `react_on_rails` allows us to access these files after precompilation, when Rails applies another hash onto the asset._
|
|
81
81
|
|
|
82
82
|
Our publicPath setting will match the path to our outputted assets on our rails web server. Given our assets in this example will be outputted to `/app/assets/webpack/webpack-assets/` and hosted at `/assets/webpack-assets/`, our publicPath would be:
|
|
83
83
|
|
|
@@ -179,7 +179,7 @@ module.exports = {
|
|
|
179
179
|
// The important stuff
|
|
180
180
|
test: /\.(jpg|jpeg|png)(\?.*)?$/, // Load only .jpg .jpeg, and .png files
|
|
181
181
|
use: {
|
|
182
|
-
loader: 'file-loader',
|
|
182
|
+
loader: 'file-loader',
|
|
183
183
|
options: {
|
|
184
184
|
name: '[name][md5:hash].[ext]', // Name of bundled asset
|
|
185
185
|
outputPath: 'webpack-assets/', // Output location for assets. Final: `app/assets/webpack/webpack-assets/`
|
|
@@ -192,4 +192,4 @@ module.exports = {
|
|
|
192
192
|
};
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
-
If you'd like to understand how react_on_rails handles these bundled assets after asset precompilation and in production mode, check out: [Rails Assets](docs/outdated/rails-assets
|
|
195
|
+
If you'd like to understand how react_on_rails handles these bundled assets after asset precompilation and in production mode, check out: [Rails Assets](https://www.shakacode.com/react-on-rails/docs/outdated/rails-assets).
|
|
@@ -13,24 +13,24 @@ CSS and fonts for CSS. However, this applies to any file that might be processed
|
|
|
13
13
|
Webpack file loader.
|
|
14
14
|
|
|
15
15
|
## The Problem
|
|
16
|
-
To understand the problem, it helps to read this article:
|
|
16
|
+
To understand the problem, it helps to read this article:
|
|
17
17
|
[What is fingerprinting and why should I care](http://guides.rubyonrails.org/asset_pipeline.html#what-is-fingerprinting-and-why-should-i-care-questionmark)
|
|
18
18
|
Basically, when Rails prepares assets for production deployments, it also adds a digest
|
|
19
|
-
to the file names. E.g., `img1.jpg` becomes `img1-dbu097452jf2v2.jpg`.
|
|
19
|
+
to the file names. E.g., `img1.jpg` becomes `img1-dbu097452jf2v2.jpg`.
|
|
20
20
|
|
|
21
|
-
When compiling its native css Rails transforms all urls and links to digested
|
|
22
|
-
versions, i.e. `background-image: image-url(img1.jpg)` becomes
|
|
23
|
-
`background-image: url(img1-dbu097452jf2v2.jpg)`. However this doesn't happen for js and
|
|
24
|
-
css files compiled by webpack on the client side, because they don't use
|
|
21
|
+
When compiling its native css Rails transforms all urls and links to digested
|
|
22
|
+
versions, i.e. `background-image: image-url(img1.jpg)` becomes
|
|
23
|
+
`background-image: url(img1-dbu097452jf2v2.jpg)`. However this doesn't happen for js and
|
|
24
|
+
css files compiled by webpack on the client side, because they don't use
|
|
25
25
|
`image-url` and `asset-url`. Without some fix, these assets would fail to load.
|
|
26
26
|
|
|
27
|
-
When Webpack's client JavaScript uses images in render methods, e.g. `<img src='...' />` or
|
|
27
|
+
When Webpack's client JavaScript uses images in render methods, e.g. `<img src='...' />` or
|
|
28
28
|
in css, e.g. `background-image: url(...)` The code (such as the CSS) generated by the Webpack
|
|
29
29
|
will have the Webpack digested name (MD5 hash). Since the Webpack generated CSS expects
|
|
30
30
|
just one level of "digesting", this "double-digesting" from Rails will cause such these assets
|
|
31
31
|
fail to load.
|
|
32
32
|
|
|
33
|
-
_If you are interested in learning how to use assets in your React components, read this doc: [Webpack, the Asset Pipeline, and Using Assets w/ React](
|
|
33
|
+
_If you are interested in learning how to use assets in your React components, read this doc: [Webpack, the Asset Pipeline, and Using Assets w/ React](https://www.shakacode.com/react-on-rails/docs/outdated/rails-assets-relative-paths)_
|
|
34
34
|
|
|
35
35
|
## The Solution: Symlink Original File Names to New File Names
|
|
36
36
|
_Note, this solution was removed in v14. If you're intersted in this symlink solution, please create
|
data/docs/outdated/rails3.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Rails 3
|
|
2
2
|
|
|
3
|
-
* Please let us know if you find any issues with Rails 3.
|
|
3
|
+
* Please let us know if you find any issues with Rails 3.
|
|
4
4
|
* Rails 3 is confirmed to work up with versions up to 6.8.x.
|
|
5
5
|
* We are not testing it for new releases. If you find an issue, you will have to submit a PR to get it fixed.
|
|
6
6
|
|
|
7
7
|
## Known Issues
|
|
8
8
|
|
|
9
|
-
1. If you do not skip bootstrap for the generator, you cannot generate a working app, as bootstrap-sass does not
|
|
9
|
+
1. If you do not skip bootstrap for the generator, you cannot generate a working app, as bootstrap-sass does not support Rails 3, or at least the version we're using.
|
|
@@ -16,4 +16,4 @@ Rails will start creating the app and will skip the files you have already creat
|
|
|
16
16
|
3. If it is removeing some of your code then press "n" and add all additions manually
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
3. Run `bundle install` and follow [the instructions for installing into an existing Rails app](
|
|
19
|
+
3. Run `bundle install` and follow [the instructions for installing into an existing Rails app](https://www.shakacode.com/react-on-rails/docs/basics/installation-into-an-existing-rails-app)
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Rails/Webpacker React Integration Options
|
|
2
|
+
|
|
3
|
+
You only _need_ props hydration if you need SSR. However, there's no good reason to
|
|
4
|
+
have your app make a second round trip to the Rails server to get initialization props.
|
|
5
|
+
|
|
6
|
+
**Server-Side Rendering (SSR)** results in Rails rendering HTML for your React components. The main reasons to use SSR are better SEO and pages display more quickly.
|
|
7
|
+
|
|
8
|
+
These gems provide advanced integration of React with [rails/webpacker](https://github.com/rails/webpacker):
|
|
9
|
+
|
|
10
|
+
| Gem | Props Hydration | Server-Side-Rendering (SSR) | SSR with HMR | SSR with React-Router | SSR with Code Splitting | Node SSR |
|
|
11
|
+
| --- | --------------- | --- | --------------------- | ----------------------| ------------------------|----|
|
|
12
|
+
| [shakacode/react_on_rails](https://github.com/shakacode/react_on_rails) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
13
|
+
| [react-rails](https://github.com/reactjs/react-rails) | ✅ | ✅ | | | | | |
|
|
14
|
+
| [webpacker-react](https://github.com/renchap/webpacker-react) | ✅ | | | | | | |
|
|
15
|
+
|
|
16
|
+
Note, Node SSR for React on Rails requires [React on Rails Pro](https://www.shakacode.com/react-on-rails-pro).
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
As mentioned, you don't _need_ to use a gem to integrate Rails with React.
|
|
21
|
+
|
|
22
|
+
If you're not concerned with view helpers to pass props or server rendering, can do it yourself:
|
|
23
|
+
|
|
24
|
+
```erb
|
|
25
|
+
<%# views/layouts/application.html.erb %>
|
|
26
|
+
|
|
27
|
+
<%= content_tag :div,
|
|
28
|
+
id: "hello-react",
|
|
29
|
+
data: {
|
|
30
|
+
message: 'Hello!',
|
|
31
|
+
name: 'David'
|
|
32
|
+
}.to_json do %>
|
|
33
|
+
<% end %>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
// app/javascript/packs/hello_react.js
|
|
38
|
+
|
|
39
|
+
const Hello = props => (
|
|
40
|
+
<div className='react-app-wrapper'>
|
|
41
|
+
<img src={clockIcon} alt="clock" />
|
|
42
|
+
<h5 className='hello-react'>
|
|
43
|
+
{props.message} {props.name}!
|
|
44
|
+
</h5>
|
|
45
|
+
</div>
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
// Render component with data
|
|
49
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
50
|
+
const node = document.getElementById('hello-react')
|
|
51
|
+
const data = JSON.parse(node.getAttribute('data'))
|
|
52
|
+
|
|
53
|
+
ReactDOM.render(<Hello {...data} />, node)
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
----
|
|
58
|
+
|
|
59
|
+
## HMR and React Hot Reloading
|
|
60
|
+
|
|
61
|
+
Before turning HMR on, consider upgrading to the latest stable gems and packages:
|
|
62
|
+
https://github.com/rails/webpacker#upgrading
|
|
63
|
+
|
|
64
|
+
Configure `config/webpacker.yml` file:
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
development:
|
|
68
|
+
extract_css: false
|
|
69
|
+
dev_server:
|
|
70
|
+
hmr: true
|
|
71
|
+
inline: true
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This basic configuration alone will have HMR working with the default webpacker setup. However, an code saves will trigger a full page refresh each time you save a file.
|
|
75
|
+
|
|
76
|
+
Webpack's HMR allows the replacement of modules for React in-place without reloading the browser. To do this, you have two options:
|
|
77
|
+
|
|
78
|
+
1. Steps below for the [github.com/pmmmwh/react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin).
|
|
79
|
+
1. Deprecated steps below for using the [github.com/gaearon/react-hot-loader](https://github.com/gaearon/react-hot-loader).
|
|
80
|
+
|
|
81
|
+
### React Refresh Webpack Plugin
|
|
82
|
+
[github.com/pmmmwh/react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin)
|
|
83
|
+
|
|
84
|
+
You can see an example commit of adding this [here](https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/commit/7e53803fce7034f5ecff335db1f400a5743a87e7).
|
|
85
|
+
|
|
86
|
+
1. Add react refresh packages:
|
|
87
|
+
`yarn add @pmmmwh/react-refresh-webpack-plugin react-refresh -D`
|
|
88
|
+
2. Update `babel.config.js` adding
|
|
89
|
+
```js
|
|
90
|
+
plugins: [
|
|
91
|
+
process.env.WEBPACK_DEV_SERVER && 'react-refresh/babel',
|
|
92
|
+
// other plugins
|
|
93
|
+
```
|
|
94
|
+
3. Update `config/webpack/development.js`, only including the plugin if running the WEBPACK_DEV_SERVER
|
|
95
|
+
```js
|
|
96
|
+
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
|
97
|
+
const environment = require('./environment')
|
|
98
|
+
|
|
99
|
+
const isWebpackDevServer = process.env.WEBPACK_DEV_SERVER;
|
|
100
|
+
|
|
101
|
+
//plugins
|
|
102
|
+
if (isWebpackDevServer) {
|
|
103
|
+
environment.plugins.append(
|
|
104
|
+
'ReactRefreshWebpackPlugin',
|
|
105
|
+
new ReactRefreshWebpackPlugin({
|
|
106
|
+
overlay: {
|
|
107
|
+
sockPort: 3035
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### React Hot Loader (Deprecated)
|
|
115
|
+
|
|
116
|
+
1. Add the `react-hot-loader` and ` @hot-loader/react-dom` npm packages.
|
|
117
|
+
```sh
|
|
118
|
+
yarn add --dev react-hot-loader @hot-loader/react-dom
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
2. Update your babel config, `babel.config.js`. Add the plugin `react-hot-loader/babel`
|
|
122
|
+
with option `"safetyNet": false`:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
{
|
|
126
|
+
"plugins": [
|
|
127
|
+
[
|
|
128
|
+
"react-hot-loader/babel",
|
|
129
|
+
{
|
|
130
|
+
"safetyNet": false
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
3. Add changes like this to your entry points:
|
|
138
|
+
|
|
139
|
+
```diff
|
|
140
|
+
// app/javascript/app.jsx
|
|
141
|
+
|
|
142
|
+
import React from 'react';
|
|
143
|
+
+ import { hot } from 'react-hot-loader/root';
|
|
144
|
+
|
|
145
|
+
const App = () => <SomeComponent(s) />
|
|
146
|
+
|
|
147
|
+
- export default App;
|
|
148
|
+
+ export default hot(App);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
4. Adjust your webpack configuration for development so that `sourceMapContents` option for the sass
|
|
152
|
+
loader is `false`:
|
|
153
|
+
|
|
154
|
+
```diff
|
|
155
|
+
// config/webpack/development.js
|
|
156
|
+
|
|
157
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
|
158
|
+
|
|
159
|
+
const environment = require('./environment')
|
|
160
|
+
|
|
161
|
+
// allows for editing sass/scss files directly in browser
|
|
162
|
+
+ if (!module.hot) {
|
|
163
|
+
+ environment.loaders.get('sass').use.find(item => item.loader === 'sass-loader').options.sourceMapContents = false
|
|
164
|
+
+ }
|
|
165
|
+
+
|
|
166
|
+
module.exports = environment.toWebpackConfig()
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
5. Adjust your `config/webpack/environment.js` for a
|
|
170
|
+
|
|
171
|
+
```diff
|
|
172
|
+
// config/webpack/environment.js
|
|
173
|
+
|
|
174
|
+
// ...
|
|
175
|
+
|
|
176
|
+
// Fixes: React-Hot-Loader: react-🔥-dom patch is not detected. React 16.6+ features may not work.
|
|
177
|
+
// https://github.com/gaearon/react-hot-loader/issues/1227#issuecomment-482139583
|
|
178
|
+
+ environment.config.merge({ resolve: { alias: { 'react-dom': '@hot-loader/react-dom' } } });
|
|
179
|
+
|
|
180
|
+
module.exports = environment;
|
|
181
|
+
```
|
|
182
|
+
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Testimonials
|
|
2
|
-
# [HVMN Testimonial, Written by Paul Benigeri, October 12, 2018](
|
|
2
|
+
# [HVMN Testimonial, Written by Paul Benigeri, October 12, 2018](https://www.shakacode.com/react-on-rails/docs/testimonials/hvmn)
|
|
3
3
|
|
|
4
4
|
> The price we paid for the consultation + the React on Rails pro license has already been made back a couple of times from hosting fees alone. The entire process was super hands off, and our core team was able to focus on shipping new feature during that sprint.
|
|
5
5
|
|
|
6
|
-
Full writeup [here](
|
|
6
|
+
Full writeup [here](https://www.shakacode.com/react-on-rails/docs/testimonials/hvmn).
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
# [Leora from ResortPass](
|
|
10
|
+
# [Leora from ResortPass](https://www.shakacode.com/react-on-rails/docs/testimonials/resortpass), December 10, 2018
|
|
11
11
|
|
|
12
|
-
Justin and his team were instrumental in assisting us in setting design foundations and standards for our transition to a react on rails application. Just three months of work with the team at Shaka code and we have a main page of our application server-side rendering at exponentially improved speeds.
|
|
12
|
+
Justin and his team were instrumental in assisting us in setting design foundations and standards for our transition to a react on rails application. Just three months of work with the team at Shaka code and we have a main page of our application server-side rendering at exponentially improved speeds.
|
|
13
13
|
|
|
14
|
-
Full writeup [here](
|
|
14
|
+
Full writeup [here](https://www.shakacode.com/react-on-rails/docs/testimonials/resortpass).
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -25,4 +25,4 @@ From Kyle Maune of Cooper Aerial, May 4, 2018
|
|
|
25
25
|
|
|
26
26
|

|
|
27
27
|
|
|
28
|
-
For more testimonials, see [Live Projects](PROJECTS.md) and [Kudos](KUDOS.md).
|
|
28
|
+
For more testimonials, see [Live Projects](https://github.com/shakacode/react_on_rails/tree/master/PROJECTS.md) and [Kudos](https://github.com/shakacode/react_on_rails/tree/master/KUDOS.md).
|
|
@@ -43,7 +43,14 @@ module ReactOnRails
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def add_yarn_dependencies
|
|
46
|
-
|
|
46
|
+
major_minor_patch_only = /\A\d+\.\d+\.\d+\z/.freeze
|
|
47
|
+
if ReactOnRails::VERSION.match?(major_minor_patch_only)
|
|
48
|
+
run "yarn add react-on-rails@#{ReactOnRails::VERSION} --exact"
|
|
49
|
+
else
|
|
50
|
+
# otherwise add latest
|
|
51
|
+
puts "Adding the lastest react-on-rails NPM module. Double check this is correct in package.json"
|
|
52
|
+
run "yarn add react-on-rails --exact"
|
|
53
|
+
end
|
|
47
54
|
end
|
|
48
55
|
|
|
49
56
|
def append_to_spec_rails_helper
|
|
@@ -13,9 +13,11 @@ require_relative "spec_helper"
|
|
|
13
13
|
require "rspec/rails"
|
|
14
14
|
require "capybara/rspec"
|
|
15
15
|
require "capybara/rails"
|
|
16
|
-
Capybara.javascript_driver = :selenium_chrome
|
|
17
16
|
Capybara.register_driver :selenium_chrome do |app|
|
|
18
|
-
|
|
17
|
+
options = Selenium::WebDriver::Chrome::Options.new
|
|
18
|
+
options.add_argument("--headless")
|
|
19
|
+
options.add_argument("--disable-gpu")
|
|
20
|
+
Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
# Requires supporting ruby files with custom matchers and macros, etc, in
|
|
@@ -38,6 +40,10 @@ end
|
|
|
38
40
|
# ActiveRecord::Migration.maintain_test_schema!
|
|
39
41
|
|
|
40
42
|
RSpec.configure do |config|
|
|
43
|
+
config.before(:each, type: :system, js: true) do
|
|
44
|
+
driven_by :selenium_chrome
|
|
45
|
+
end
|
|
46
|
+
|
|
41
47
|
# Ensure that if we are running js tests, we are using latest webpack assets
|
|
42
48
|
# This will use the defaults of :js and :server_rendering meta tags
|
|
43
49
|
ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
|
data/lib/generators/react_on_rails/templates/dev_tests/spec/{features → system}/hello_world_spec.rb
RENAMED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "../rails_helper"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
describe "Hello World", js: true do
|
|
6
|
+
it "the hello world example works" do
|
|
7
7
|
visit "/hello_world"
|
|
8
8
|
expect(heading).to have_text("Hello World")
|
|
9
9
|
expect(message).to have_text("Stranger")
|
|
@@ -53,6 +53,7 @@ module ReactOnRails
|
|
|
53
53
|
:server_render_method, :random_dom_id,
|
|
54
54
|
:same_bundle_for_client_and_server
|
|
55
55
|
|
|
56
|
+
# rubocop:disable Metrics/AbcSize
|
|
56
57
|
def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
|
|
57
58
|
replay_console: nil,
|
|
58
59
|
trace: nil, development_mode: nil,
|
|
@@ -98,6 +99,7 @@ module ReactOnRails
|
|
|
98
99
|
|
|
99
100
|
self.server_render_method = server_render_method
|
|
100
101
|
end
|
|
102
|
+
# rubocop:enable Metrics/AbcSize
|
|
101
103
|
|
|
102
104
|
# on ReactOnRails
|
|
103
105
|
def setup_config_values
|
|
@@ -10,10 +10,10 @@ module ReactOnRails
|
|
|
10
10
|
status = `git status --porcelain`
|
|
11
11
|
return false if $CHILD_STATUS.success? && status.empty?
|
|
12
12
|
|
|
13
|
-
error = if
|
|
14
|
-
"You do not have Git installed. Please install Git, and commit your changes before continuing"
|
|
15
|
-
else
|
|
13
|
+
error = if $CHILD_STATUS.success?
|
|
16
14
|
"You have uncommitted code. Please commit or stash your changes before continuing"
|
|
15
|
+
else
|
|
16
|
+
"You do not have Git installed. Please install Git, and commit your changes before continuing"
|
|
17
17
|
end
|
|
18
18
|
message_handler.add_error(error)
|
|
19
19
|
true
|
|
@@ -17,13 +17,13 @@ module ReactOnRails
|
|
|
17
17
|
|
|
18
18
|
COMPONENT_HTML_KEY = "componentHtml"
|
|
19
19
|
|
|
20
|
-
# react_component_name: can be a React function or class component or a "
|
|
21
|
-
# "
|
|
20
|
+
# react_component_name: can be a React function or class component or a "Render-Function".
|
|
21
|
+
# "Render-Functions" differ from a React function in that they take two parameters, the
|
|
22
22
|
# props and the railsContext, like this:
|
|
23
23
|
#
|
|
24
24
|
# let MyReactComponentApp = (props, railsContext) => <MyReactComponent {...props}/>;
|
|
25
25
|
#
|
|
26
|
-
# Alternately, you can define the
|
|
26
|
+
# Alternately, you can define the Render-Function with an additional property
|
|
27
27
|
# `.renderFunction = true`:
|
|
28
28
|
#
|
|
29
29
|
# let MyReactComponentApp = (props) => <MyReactComponent {...props}/>;
|
|
@@ -32,8 +32,8 @@ module ReactOnRails
|
|
|
32
32
|
# Exposing the react_component_name is necessary to both a plain ReactComponent as well as
|
|
33
33
|
# a generator:
|
|
34
34
|
# See README.md for how to "register" your react components.
|
|
35
|
-
# See spec/dummy/client/app/
|
|
36
|
-
# spec/dummy/client/app/
|
|
35
|
+
# See spec/dummy/client/app/packs/server-bundle.js and
|
|
36
|
+
# spec/dummy/client/app/packs/client-bundle.js for examples of this.
|
|
37
37
|
#
|
|
38
38
|
# options:
|
|
39
39
|
# props: Ruby Hash or JSON string which contains the properties to pass to the react object. Do
|
|
@@ -57,14 +57,15 @@ module ReactOnRails
|
|
|
57
57
|
server_rendered_html = internal_result[:result]["html"]
|
|
58
58
|
console_script = internal_result[:result]["consoleReplayScript"]
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
case server_rendered_html
|
|
61
|
+
when String
|
|
61
62
|
build_react_component_result_for_server_rendered_string(
|
|
62
63
|
server_rendered_html: server_rendered_html,
|
|
63
64
|
component_specification_tag: internal_result[:tag],
|
|
64
65
|
console_script: console_script,
|
|
65
66
|
render_options: internal_result[:render_options]
|
|
66
67
|
)
|
|
67
|
-
|
|
68
|
+
when Hash
|
|
68
69
|
msg = <<~MSG
|
|
69
70
|
Use react_component_hash (not react_component) to return a Hash to your ruby view code. See
|
|
70
71
|
https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/client/app/startup/ReactHelmetServerApp.jsx
|
|
@@ -79,7 +80,7 @@ module ReactOnRails
|
|
|
79
80
|
Value:
|
|
80
81
|
#{server_rendered_html}
|
|
81
82
|
|
|
82
|
-
If you're trying to use a
|
|
83
|
+
If you're trying to use a Render-Function to return a Hash to your ruby view code, then use
|
|
83
84
|
react_component_hash instead of react_component and see
|
|
84
85
|
https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/client/app/startup/ReactHelmetServerApp.jsx
|
|
85
86
|
for an example of the JavaScript code.
|
|
@@ -93,7 +94,7 @@ module ReactOnRails
|
|
|
93
94
|
# It is exactly like react_component except for the following:
|
|
94
95
|
# 1. prerender: true is automatically added, as this method doesn't make sense for client only
|
|
95
96
|
# rendering.
|
|
96
|
-
# 2. Your JavaScript
|
|
97
|
+
# 2. Your JavaScript Render-Function for server rendering must return an Object rather than a React component.
|
|
97
98
|
# 3. Your view code must expect an object and not a string.
|
|
98
99
|
#
|
|
99
100
|
# Here is an example of the view code:
|
|
@@ -124,10 +125,10 @@ module ReactOnRails
|
|
|
124
125
|
)
|
|
125
126
|
else
|
|
126
127
|
msg = <<~MSG
|
|
127
|
-
|
|
128
|
+
Render-Function used by react_component_hash for #{component_name} is expected to return
|
|
128
129
|
an Object. See https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/client/app/startup/ReactHelmetServerApp.jsx
|
|
129
130
|
for an example of the JavaScript code.
|
|
130
|
-
Note, your
|
|
131
|
+
Note, your Render-Function must either take 2 params or have the property
|
|
131
132
|
`.renderFunction = true` added to it to distinguish it from a React Function Component.
|
|
132
133
|
MSG
|
|
133
134
|
raise ReactOnRails::Error, msg
|
|
@@ -169,7 +170,7 @@ module ReactOnRails
|
|
|
169
170
|
def redux_store_hydration_data
|
|
170
171
|
return if @registered_stores_defer_render.blank?
|
|
171
172
|
|
|
172
|
-
@registered_stores_defer_render.reduce(""
|
|
173
|
+
@registered_stores_defer_render.reduce(+"") do |accum, redux_store_data|
|
|
173
174
|
accum << render_redux_store_data(redux_store_data)
|
|
174
175
|
end.html_safe
|
|
175
176
|
end
|
|
@@ -240,10 +241,10 @@ module ReactOnRails
|
|
|
240
241
|
end
|
|
241
242
|
|
|
242
243
|
# This is the definitive list of the default values used for the rails_context, which is the
|
|
243
|
-
# second parameter passed to both component and store
|
|
244
|
+
# second parameter passed to both component and store Render-Functions.
|
|
244
245
|
# This method can be called from views and from the controller, as `helpers.rails_context`
|
|
245
246
|
#
|
|
246
|
-
# rubocop:disable Metrics/AbcSize
|
|
247
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
247
248
|
def rails_context(server_side: true)
|
|
248
249
|
# ALERT: Keep in sync with node_package/src/types/index.ts for the properties of RailsContext
|
|
249
250
|
@rails_context ||= begin
|
|
@@ -254,8 +255,13 @@ module ReactOnRails
|
|
|
254
255
|
i18nLocale: I18n.locale,
|
|
255
256
|
i18nDefaultLocale: I18n.default_locale,
|
|
256
257
|
rorVersion: ReactOnRails::VERSION,
|
|
258
|
+
# TODO: v13 just use the version if existing
|
|
257
259
|
rorPro: ReactOnRails::Utils.react_on_rails_pro?
|
|
258
260
|
}
|
|
261
|
+
if ReactOnRails::Utils.react_on_rails_pro?
|
|
262
|
+
result[:rorProVersion] = ReactOnRails::Utils.react_on_rails_pro_version
|
|
263
|
+
end
|
|
264
|
+
|
|
259
265
|
if defined?(request) && request.present?
|
|
260
266
|
# Check for encoding of the request's original_url and try to force-encoding the
|
|
261
267
|
# URLs as UTF-8. This situation can occur in browsers that do not encode the
|
|
@@ -291,7 +297,7 @@ module ReactOnRails
|
|
|
291
297
|
|
|
292
298
|
@rails_context.merge(serverSide: server_side)
|
|
293
299
|
end
|
|
294
|
-
# rubocop:enable Metrics/AbcSize
|
|
300
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
295
301
|
|
|
296
302
|
private
|
|
297
303
|
|
|
@@ -486,13 +492,13 @@ module ReactOnRails
|
|
|
486
492
|
end
|
|
487
493
|
|
|
488
494
|
def initialize_redux_stores
|
|
489
|
-
result =
|
|
495
|
+
result = +<<-JS
|
|
490
496
|
ReactOnRails.clearHydratedStores();
|
|
491
497
|
JS
|
|
492
498
|
|
|
493
499
|
return result unless @registered_stores.present? || @registered_stores_defer_render.present?
|
|
494
500
|
|
|
495
|
-
declarations = "var reduxProps, store, storeGenerator;\n"
|
|
501
|
+
declarations = +"var reduxProps, store, storeGenerator;\n"
|
|
496
502
|
all_stores = (@registered_stores || []) + (@registered_stores_defer_render || [])
|
|
497
503
|
|
|
498
504
|
result << all_stores.each_with_object(declarations) do |redux_store_data, memo|
|
|
@@ -32,12 +32,12 @@ module ReactOnRails
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def exist_files
|
|
35
|
-
@exist_files ||= files.select
|
|
35
|
+
@exist_files ||= files.select { |file| File.exist?(file) }
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def files_are_outdated
|
|
39
|
-
latest_yml = locale_files.map
|
|
40
|
-
earliest = exist_files.map
|
|
39
|
+
latest_yml = locale_files.map { |file| File.mtime(file) }.max
|
|
40
|
+
earliest = exist_files.map { |file| File.mtime(file) }.min
|
|
41
41
|
latest_yml > earliest
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -46,7 +46,7 @@ module ReactOnRails
|
|
|
46
46
|
private
|
|
47
47
|
|
|
48
48
|
def calc_message(component_name, console_messages, err, js_code, props)
|
|
49
|
-
message = "ERROR in SERVER PRERENDERING\n"
|
|
49
|
+
message = +"ERROR in SERVER PRERENDERING\n"
|
|
50
50
|
if err
|
|
51
51
|
message << <<~MSG
|
|
52
52
|
Encountered error: \"#{err}\"
|
|
@@ -47,6 +47,7 @@ module ReactOnRails
|
|
|
47
47
|
# Note, js_code does not have to be based on React.
|
|
48
48
|
# js_code MUST RETURN json stringify Object
|
|
49
49
|
# Calling code will probably call 'html_safe' on return value before rendering to the view.
|
|
50
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
50
51
|
def exec_server_render_js(js_code, render_options, js_evaluator = nil)
|
|
51
52
|
js_evaluator ||= self
|
|
52
53
|
if render_options.trace
|
|
@@ -67,16 +68,15 @@ module ReactOnRails
|
|
|
67
68
|
console_script = result["consoleReplayScript"]
|
|
68
69
|
console_script_lines = console_script.split("\n")
|
|
69
70
|
console_script_lines = console_script_lines[2..-2]
|
|
70
|
-
re = /console\.(log|error)\.apply\(console, \["\[SERVER\] (?<msg>.*)"\]\);/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
Rails.logger.info { "[react_on_rails] #{match[:msg]}" } if match
|
|
75
|
-
end
|
|
71
|
+
re = /console\.(?:log|error)\.apply\(console, \["\[SERVER\] (?<msg>.*)"\]\);/
|
|
72
|
+
console_script_lines&.each do |line|
|
|
73
|
+
match = re.match(line)
|
|
74
|
+
Rails.logger.info { "[react_on_rails] #{match[:msg]}" } if match
|
|
76
75
|
end
|
|
77
76
|
end
|
|
78
77
|
result
|
|
79
78
|
end
|
|
79
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
80
80
|
|
|
81
81
|
def trace_js_code_used(msg, js_code, file_name = "tmp/server-generated.js", force: false)
|
|
82
82
|
return unless ReactOnRails.configuration.trace || force
|
|
@@ -8,7 +8,7 @@ module ReactOnRails
|
|
|
8
8
|
def compile_assets
|
|
9
9
|
if ReactOnRails.configuration.build_test_command.blank?
|
|
10
10
|
msg = <<~MSG
|
|
11
|
-
You are using the React on Rails test helper.
|
|
11
|
+
You are using the React on Rails test helper.
|
|
12
12
|
Either you used:
|
|
13
13
|
ReactOnRails::TestHelper.configure_rspec_to_compile_assets or
|
|
14
14
|
ReactOnRails::TestHelper.ensure_assets_compiled
|
|
@@ -52,6 +52,7 @@ module ReactOnRails
|
|
|
52
52
|
# don't provide one.
|
|
53
53
|
# webpack_generated_files List of files to check for up-to-date-status, defaulting to
|
|
54
54
|
# webpack_generated_files in your configuration
|
|
55
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
55
56
|
def self.ensure_assets_compiled(webpack_assets_status_checker: nil,
|
|
56
57
|
webpack_assets_compiler: nil,
|
|
57
58
|
source_path: nil,
|
|
@@ -96,4 +97,5 @@ module ReactOnRails
|
|
|
96
97
|
).call
|
|
97
98
|
end
|
|
98
99
|
end
|
|
100
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
99
101
|
end
|