react_on_rails 13.3.5 → 14.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +100 -62
- data/Gemfile.development_dependencies +10 -9
- data/README.md +7 -2
- data/lib/generators/react_on_rails/adapt_for_older_shakapacker_generator.rb +41 -0
- data/lib/generators/react_on_rails/base_generator.rb +13 -49
- data/lib/generators/react_on_rails/dev_tests_generator.rb +1 -1
- data/lib/generators/react_on_rails/generator_messages.rb +40 -0
- data/lib/generators/react_on_rails/install_generator.rb +21 -0
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +2 -2
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static +2 -2
- data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +2 -2
- data/lib/generators/react_on_rails/templates/base/base/config/{webpacker.yml → shakapacker.yml} +3 -3
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt +3 -1
- data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +2 -2
- data/lib/generators/react_on_rails/templates/dev_tests/spec/system/hello_world_spec.rb +1 -1
- data/lib/react_on_rails/configuration.rb +39 -25
- data/lib/react_on_rails/git_utils.rb +3 -3
- data/lib/react_on_rails/helper.rb +25 -13
- data/lib/react_on_rails/json_output.rb +0 -17
- data/lib/react_on_rails/locales/base.rb +4 -4
- data/lib/react_on_rails/locales/to_js.rb +1 -1
- data/lib/react_on_rails/packs_generator.rb +4 -4
- data/lib/react_on_rails/react_component/render_options.rb +1 -1
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +10 -12
- data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +3 -3
- data/lib/react_on_rails/test_helper.rb +2 -2
- data/lib/react_on_rails/utils.rb +2 -8
- data/lib/react_on_rails/version.rb +1 -1
- data/lib/react_on_rails/version_checker.rb +2 -2
- data/lib/react_on_rails/webpacker_utils.rb +6 -0
- data/lib/tasks/assets.rake +1 -1
- data/react_on_rails.gemspec +4 -4
- metadata +6 -131
- data/.bookignore +0 -15
- data/.circleci/config.yml +0 -338
- data/.coveralls.yml +0 -1
- data/.dockerignore +0 -2
- data/.eslintignore +0 -17
- data/.eslintrc +0 -53
- data/.github/FUNDING.yml +0 -1
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -23
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -19
- data/.github/workflows/lint-js-and-ruby.yml +0 -54
- data/.github/workflows/main.yml +0 -183
- data/.github/workflows/package-js-tests.yml +0 -35
- data/.github/workflows/rspec-package-specs.yml +0 -46
- data/.gitignore +0 -33
- data/.npmignore +0 -22
- data/.prettierignore +0 -14
- data/.prettierrc +0 -20
- data/.rspec +0 -2
- data/.rubocop.yml +0 -134
- data/.scss-lint.yml +0 -205
- data/.travis.yml +0 -61
- data/book.json +0 -18
- data/docs/additional-details/generator-details.md +0 -56
- data/docs/additional-details/manual-installation-overview.md +0 -30
- data/docs/additional-details/migrating-from-react-rails.md +0 -17
- data/docs/additional-details/recommended-project-structure.md +0 -69
- data/docs/additional-details/updating-dependencies.md +0 -31
- data/docs/additional-details/upgrade-webpacker-v3-to-v4.md +0 -10
- data/docs/api/javascript-api.md +0 -99
- data/docs/api/redux-store-api.md +0 -102
- data/docs/api/view-helpers-api.md +0 -133
- data/docs/contributor-info/errors-with-hooks.md +0 -45
- data/docs/contributor-info/generator-testing.md +0 -11
- data/docs/contributor-info/linters.md +0 -68
- data/docs/contributor-info/pull-requests.md +0 -42
- data/docs/contributor-info/releasing.md +0 -76
- data/docs/deployment/elastic-beanstalk.md +0 -63
- data/docs/deployment/heroku-deployment.md +0 -35
- data/docs/getting-started.md +0 -195
- data/docs/guides/client-vs-server-rendering.md +0 -27
- data/docs/guides/configuration.md +0 -289
- data/docs/guides/deployment.md +0 -5
- data/docs/guides/file-system-based-automated-bundle-generation.md +0 -205
- data/docs/guides/hmr-and-hot-reloading-with-the-webpack-dev-server.md +0 -104
- data/docs/guides/how-react-on-rails-works.md +0 -44
- data/docs/guides/how-to-conditionally-server-render-based-on-device-type.md +0 -40
- data/docs/guides/how-to-use-different-files-for-client-and-server-rendering.md +0 -98
- data/docs/guides/i18n.md +0 -87
- data/docs/guides/installation-into-an-existing-rails-app.md +0 -66
- data/docs/guides/minitest-configuration.md +0 -31
- data/docs/guides/rails-webpacker-react-integration-options.md +0 -213
- data/docs/guides/react-on-rails-overview.md +0 -30
- data/docs/guides/react-server-rendering.md +0 -32
- data/docs/guides/render-functions-and-railscontext.md +0 -205
- data/docs/guides/rspec-configuration.md +0 -73
- data/docs/guides/tutorial.md +0 -374
- data/docs/guides/upgrading-react-on-rails.md +0 -304
- data/docs/guides/webpack-configuration.md +0 -42
- data/docs/home.md +0 -23
- data/docs/javascript/angular-js-integration-migration.md +0 -28
- data/docs/javascript/asset-pipeline.md +0 -12
- data/docs/javascript/capistrano-deployment.md +0 -18
- data/docs/javascript/code-splitting.md +0 -165
- data/docs/javascript/converting-from-custom-webpack-config-to-rails-webpacker-config.md +0 -10
- data/docs/javascript/credits.md +0 -10
- data/docs/javascript/foreman-issues.md +0 -15
- data/docs/javascript/images.md +0 -57
- data/docs/javascript/node-dependencies-and-npm.md +0 -19
- data/docs/javascript/react-and-redux.md +0 -36
- data/docs/javascript/react-helmet.md +0 -100
- data/docs/javascript/react-router.md +0 -90
- data/docs/javascript/server-rendering-tips.md +0 -55
- data/docs/javascript/troubleshooting-when-using-webpacker.md +0 -90
- data/docs/javascript/webpack-v1-notes.md +0 -23
- data/docs/javascript/webpack.md +0 -22
- data/docs/misc/articles.md +0 -20
- data/docs/misc/code_of_conduct.md +0 -13
- data/docs/misc/doctrine.md +0 -77
- data/docs/misc/style.md +0 -33
- data/docs/misc/tips.md +0 -10
- data/docs/outdated/deferred-rendering.md +0 -39
- data/docs/outdated/rails-assets-relative-paths.md +0 -195
- data/docs/outdated/rails-assets.md +0 -77
- data/docs/outdated/rails3.md +0 -9
- data/docs/rails/convert-rails-5-api-only-app.md +0 -19
- data/docs/rails/rails-engine-integration.md +0 -32
- data/docs/rails/rails_view_rendering_from_inline_javascript.md +0 -36
- data/docs/rails/turbolinks.md +0 -124
- data/docs/react-on-rails-pro/react-on-rails-pro.md +0 -43
- data/docs/testimonials/hvmn.md +0 -25
- data/docs/testimonials/resortpass.md +0 -13
- data/docs/testimonials/testimonials.md +0 -28
- data/jest.config.js +0 -4
- data/package-scripts.yml +0 -49
- data/package.json +0 -96
- data/rakelib/docker.rake +0 -26
- data/rakelib/dummy_apps.rake +0 -30
- data/rakelib/example_type.rb +0 -96
- data/rakelib/examples.rake +0 -64
- data/rakelib/examples_config.yml +0 -14
- data/rakelib/lint.rake +0 -30
- data/rakelib/node_package.rake +0 -15
- data/rakelib/release.rake +0 -92
- data/rakelib/run_rspec.rake +0 -103
- data/rakelib/task_helpers.rb +0 -62
- data/script/bootstrap +0 -33
- data/script/release +0 -3
- data/script/setup +0 -23
- data/script/test +0 -38
- data/webpackConfigLoader.js +0 -71
- data/yarn.lock +0 -7010
@@ -1,42 +0,0 @@
|
|
1
|
-
# Webpack Configuration: custom setup for Webpack or rails/webpacker?
|
2
|
-
|
3
|
-
## Webpack vs. rails/webpacker
|
4
|
-
|
5
|
-
[Webpack](https://webpack.js.org) is the JavaScript npm package that prepares all your client-side assets. The Rails asset pipeline used to be the preferable way to prepare client-side assets.
|
6
|
-
|
7
|
-
[rails/webpacker](https://github.com/rails/webpacker) is the Ruby gem that mainly gives us 2 things:
|
8
|
-
|
9
|
-
1. View helpers for placing the webpack bundles on your Rails views. React on Rails depends on these view helpers.
|
10
|
-
2. A layer of abstraction on top of Webpack customization. The base setup works great for the client side webpack configuration.
|
11
|
-
|
12
|
-
To get a deeper understanding of `rails/webpacker`, watch [RailsConf 2020 CE - Webpacker, It-Just-Works, But How? by Justin Gordon](https://youtu.be/sJLoOpc5LD8)
|
13
|
-
|
14
|
-
Per the example repo [shakacode/react_on_rails_demo_ssr_hmr](https://github.com/shakacode/react_on_rails_demo_ssr_hmr),
|
15
|
-
you should consider keeping your codebase mostly consistent with the defaults for [rails/webpacker](https://github.com/rails/webpacker).
|
16
|
-
|
17
|
-
# React on Rails
|
18
|
-
|
19
|
-
Version 9 of React on Rails added support for the rails/webpacker view helpers so that Webpack produced assets would no longer pass through the Rails asset pipeline. As part of this change, React on Rails added a configuration option to support customization of the node_modules directory. This allowed React on Rails to support the rails/webpacker configuration of the Webpack configuration.
|
20
|
-
|
21
|
-
A key decision in your use React on Rails is whether you go with the rails/webpacker default setup or the traditional React on Rails setup of putting all your client side files under the `/client` directory. While there are technically 2 independent choices involved, the directory structure and the mechanism of Webpack configuration, for simplicity sake we'll assume that these choices go together.
|
22
|
-
|
23
|
-
## Option 1: Default Generator Setup: rails/webpacker app/javascript
|
24
|
-
|
25
|
-
Typical rails/webpacker apps have a standard directory structure as documented [here](https://github.com/rails/webpacker/blob/5-x-stable/docs/recommended-project-structure.md). If you follow the steps in the the [basic tutorial](https://www.shakacode.com/react-on-rails/docs/guides/tutorial/), you will see this pattern in action. In order to customize the Webpack configuration, you need to consult with the [rails/webpacker Webpack configuration](https://www.shakacode.com/react-on-rails/docs/javascript/webpack/).
|
26
|
-
|
27
|
-
The *advantage* of using rails/webpacker to configure Webpack is that there is very little code needed to get started and you don't need to understand really anything about Webpack customization.
|
28
|
-
|
29
|
-
## Option 2: Traditional React on Rails using the /client directory
|
30
|
-
|
31
|
-
Until version 9, all React on Rails apps used the `/client` directory for configuring React on Rails in terms of the configuration of Webpack and location of your JavaScript and Webpack files, including the node_modules directory. Version 9 changed the default to `/` for the `node_modules` location using this value in `config/initializers/react_on_rails.rb`: `config.node_modules_location`.
|
32
|
-
|
33
|
-
You can access values in the `config/webpacker.yml`
|
34
|
-
|
35
|
-
```js
|
36
|
-
const { config, devServer } = require('shakapacker');
|
37
|
-
```
|
38
|
-
|
39
|
-
You will want consider using some of the same values set in these files:
|
40
|
-
|
41
|
-
* https://github.com/rails/webpacker/blob/master/package/environments/base.js
|
42
|
-
* https://github.com/rails/webpacker/blob/master/package/environments/development.js
|
data/docs/home.md
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# React on Rails
|
2
|
-
|
3
|
-
## Details
|
4
|
-
1. [Overview](https://www.shakacode.com/react-on-rails/docs/guides/react-on-rails-overview/)
|
5
|
-
1. [Getting Started](https://www.shakacode.com/react-on-rails/docs/getting-started/)
|
6
|
-
1. [How React on Rails Works](https://www.shakacode.com/react-on-rails/docs/guides/how-react-on-rails-works/)
|
7
|
-
1. [Webpack Configuration](https://www.shakacode.com/react-on-rails/docs/guides/webpack-configuration/)
|
8
|
-
1. [View Helpers API](https://www.shakacode.com/react-on-rails/docs/api/view-helpers-api/)
|
9
|
-
1. [Caching and Performance: React on Rails Pro](https://www.shakacode.com/react-on-rails-pro/).
|
10
|
-
1. [Deployment](https://www.shakacode.com/react-on-rails/docs/guides/deployment/).
|
11
|
-
|
12
|
-
## Changes and Upgrades
|
13
|
-
1. [CHANGELOG.md](https://github.com/shakacode/react_on_rails/tree/master/CHANGELOG.md)
|
14
|
-
2. [Upgrading React on Rails](https://www.shakacode.com/react-on-rails/docs/guides/upgrading-react-on-rails/#upgrading-to-v12).
|
15
|
-
|
16
|
-
## Example Apps
|
17
|
-
1. [spec/dummy](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy) example repo for a simple configuration of webpack via the rails/webpacker gem
|
18
|
-
that supports SSR.
|
19
|
-
2. Example repo of [React on Rails Tutorial With SSR, HMR fast refresh, and TypeScript](https://github.com/shakacode/react_on_rails_demo_ssr_hmr) for a new way to setup the creation of your SSR bundle with `rails/webpacker`.
|
20
|
-
3. Live, [open source](https://github.com/shakacode/react-webpack-rails-tutorial), example of this gem, see [reactrails.com](http://reactrails.com).
|
21
|
-
|
22
|
-
# Other Resources
|
23
|
-
1. RailsConf 2020 talk: [Webpacker, It-Just-Works, But How?](http://railsconf.com/2020/video/justin-gordon-webpacker-it-just-works-but-how)
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# AngularJS Integration and Migration to React on Rails
|
2
|
-
|
3
|
-
[React on Rails](https://github.com/shakacode/react_on_rails) offers a smooth transition to migrating your existing [AngularJS](https://angularjs.org/) + Rails application to use React with Webpack on top of Rails. Here are a few highlights and tips.
|
4
|
-
|
5
|
-
## Assets Handling
|
6
|
-
Ideally, you should have your JavaScript libraries packaged by `webpack` and gathered by `yarn`. If you have not already done this, then you can setup the `ReactOnRails` default JS code directory of `/client` to load the JS libraries related to AngularJS, etc. You can configure Webpack to globally export these libraries, so inclusion this way will be no different than using the Rails asset pipeline. However, so long as you *understand* how your JavaScript will eventually make its way onto your main layout, you will be OK.
|
7
|
-
|
8
|
-
## Styling and CSS Modules
|
9
|
-
Once you move to Webpack, you can start using CSS modules. However, you'll need to carefully consider if your styling needs to apply to legacy AngularJS components in your app.
|
10
|
-
|
11
|
-
## ngReact Package
|
12
|
-
|
13
|
-
Check out the [ngReact](https://github.com/ngReact/ngReact) package. This package allows your AngularJS components to contain React components, including support for passing props from AngularJS to React. The [ShakaCode team](http://www.shakacode.com/about/) is using this library on a commercial project. However, we're doing this with some limitations:
|
14
|
-
|
15
|
-
1. We're only having the data flow in one direction, from AngularJS to React and never back up to the Angular components.
|
16
|
-
2. When we get to a case where the React components will affect the Angular layout, we try to convert the components up the tree to React.
|
17
|
-
3. Thus, the React components within AngularJS components will tend to be React "dumb" components, or totally self-contained chunks of React that have no side effects on the Angular code.
|
18
|
-
|
19
|
-
## StoryBook
|
20
|
-
|
21
|
-
We love using [StoryBook](https://getstorybook.io/) to create a simple testing and inspection area of new React components as we migrate them over from AngularJS Components.
|
22
|
-
|
23
|
-
## Overall Approach?
|
24
|
-
|
25
|
-
The big question when doing the migration from AngularJS to React is whether you should replace leaf level components first, to minimize the changes before you can deploy your hybrid AngularJS and React app. The alternative is to try to replace larger chunks at once. Both approaches have pros and cons.
|
26
|
-
|
27
|
-
1. Frequent deploys with incremental parts of AngularJS replaced by React allows smaller incremental deploys and easier regression analysis should something break. On the negative side, any ping-pong of data between AngularJS and React can result in a complicated and convoluted architecture.
|
28
|
-
2. Larger deploys of a full screen can yield efficiencies such as converting the whole screen to use one Redux store. However, this can be a large chunk of code to test and deploy.
|
@@ -1,12 +0,0 @@
|
|
1
|
-
# Asset Pipeline with React on Rails
|
2
|
-
|
3
|
-
In general, you should not be mixing the asset pipeline with rails/webpacker and React on Rails.
|
4
|
-
|
5
|
-
If you're using React, then all of your CSS and images should be under either `/client` or
|
6
|
-
`/app/javascript` or wherever you want your client side application.
|
7
|
-
|
8
|
-
If you are incrementally migrating a large application, your main concern will be how to minimize
|
9
|
-
duplication of styles and images between your old application and the new one.
|
10
|
-
|
11
|
-
Please email [justin@shakacode.com](mailto:justin@shakacode.com) if you would be interested in help
|
12
|
-
to migrate a larger application.
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# Capistrano Deployment
|
2
|
-
Make sure ReactOnRails is working in development environment.
|
3
|
-
|
4
|
-
Add the following to development your Gemfile and bundle install.
|
5
|
-
``` ruby
|
6
|
-
group :development do
|
7
|
-
gem 'capistrano-yarn'
|
8
|
-
end
|
9
|
-
```
|
10
|
-
Then run Bundler to ensure Capistrano is downloaded and installed.
|
11
|
-
``` sh
|
12
|
-
$ bundle install
|
13
|
-
```
|
14
|
-
Add the following in your Capfile.
|
15
|
-
``` ruby
|
16
|
-
require 'capistrano/yarn'
|
17
|
-
```
|
18
|
-
If the deployment is taking too long or getting stuck at assets:precompile stage, it probably is because of memory. Webpack consumes a lot of memory so if possible, try increasing the RAM of your server.
|
@@ -1,165 +0,0 @@
|
|
1
|
-
# Code Splitting (Outdated)
|
2
|
-
|
3
|
-
_Note: This document is outdated._ Please email [justin@shakacode.com](mailto:justin@shakacode.com)
|
4
|
-
if you would be interested in help with code splitting using
|
5
|
-
[loadable-components.com](https://loadable-components.com/docs) with React on Rails.
|
6
|
-
|
7
|
-
-----
|
8
|
-
|
9
|
-
What is code splitting? From the webpack documentation:
|
10
|
-
|
11
|
-
> For big web apps it’s not efficient to put all code into a single file, especially if some blocks of code are only required under some circumstances. Webpack has a feature to split your codebase into “chunks” which are loaded on demand. Some other bundlers call them “layers”, “rollups”, or “fragments”. This feature is called “code splitting”.
|
12
|
-
|
13
|
-
## Server Rendering and Code Splitting
|
14
|
-
|
15
|
-
Let's say you're requesting a page that needs to fetch a code chunk from the server before it's able to render. If you do all your rendering on the client side, you don't have to do anything special. However, if the page is rendered on the server, you'll find that React will spit out the following error:
|
16
|
-
|
17
|
-
> Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
|
18
|
-
|
19
|
-
> (client) <!-- react-empty: 1 -
|
20
|
-
|
21
|
-
> (server) <div data-reactroot="
|
22
|
-
<!--This comment is here because the comment beginning on line 13 messes up Sublime's markdown parsing-->
|
23
|
-
|
24
|
-
Different markup is generated on the client than on the server. Why does this happen? When you register a component or Render-Function with `ReactOnRails.register`, react on rails will render the component as soon as the page loads. However, react-router renders a comment while waiting for the code chunk to be fetched from the server. This means that react will tear all of the server rendered code out of the DOM, and then rerender it a moment later once the code chunk arrives from the server, defeating most of the purpose of server rendering.
|
25
|
-
|
26
|
-
### The solution
|
27
|
-
|
28
|
-
To prevent this, you have to wait until the code chunk is fetched before doing the initial render on the client side. To accomplish this, react on rails allows you to register a renderer. This works just like registering a Render-Function, except that the function you pass takes three arguments: `renderer(props, railsContext, domNodeId)`, and is responsible for calling `ReactDOM.render` or `ReactDOM.hydrate` to render the component to the DOM. React on rails will automatically detect when a Render-Function takes three arguments, and will **not** call `ReactDOM.render` or `ReactDOM.hydrate`, instead allowing you to control the initial render yourself. Note, you have to be careful to call `ReactDOM.hydrate` rather than `ReactDOM.render` if you are are server rendering.
|
29
|
-
|
30
|
-
Here's an example of how you might use this in practice:
|
31
|
-
|
32
|
-
#### page.html.erb
|
33
|
-
```erb
|
34
|
-
<%= react_component("NavigationApp", prerender: true) %>
|
35
|
-
<%= react_component("RouterApp", prerender: true) %>
|
36
|
-
<%= redux_store_hydration_data %>
|
37
|
-
```
|
38
|
-
|
39
|
-
#### clientRegistration.js
|
40
|
-
```js
|
41
|
-
import ReactOnRails from 'node_package/lib/ReactOnRails';
|
42
|
-
import NavigationApp from './NavigationApp';
|
43
|
-
|
44
|
-
// Note that we're importing a different RouterApp than in serverRegistration.js
|
45
|
-
// Renderer functions should not be used on the server, because there is no DOM.
|
46
|
-
import RouterApp from './RouterAppRenderer';
|
47
|
-
import applicationStore from '../store/applicationStore';
|
48
|
-
|
49
|
-
ReactOnRails.registerStore({applicationStore});
|
50
|
-
ReactOnRails.register({
|
51
|
-
NavigationApp,
|
52
|
-
RouterApp,
|
53
|
-
});
|
54
|
-
```
|
55
|
-
|
56
|
-
#### serverRegistration.js
|
57
|
-
```js
|
58
|
-
import ReactOnRails from 'react-on-rails';
|
59
|
-
import NavigationApp from './NavigationApp';
|
60
|
-
|
61
|
-
// Note that we're importing a different RouterApp than in clientRegistration.js
|
62
|
-
import RouterApp from './RouterAppServer';
|
63
|
-
import applicationStore from '../store/applicationStore';
|
64
|
-
|
65
|
-
ReactOnRails.registerStore({applicationStore});
|
66
|
-
ReactOnRails.register({
|
67
|
-
NavigationApp,
|
68
|
-
RouterApp,
|
69
|
-
});
|
70
|
-
```
|
71
|
-
Note that you should not register a renderer on the server, since there won't be a domNodeId when we're server rendering. Note that the `RouterApp` imported by `serverRegistration.js` is from a different file. For an example of how to set up an app for server rendering, see the [react router docs](https://www.shakacode.com/react-on-rails/docs/javascript/react-router/).
|
72
|
-
|
73
|
-
#### RouterAppRenderer.jsx
|
74
|
-
```jsx
|
75
|
-
import ReactOnRails from 'react-on-rails';
|
76
|
-
import React from 'react';
|
77
|
-
import ReactDOM from 'react-dom';
|
78
|
-
import Router from 'react-router/lib/Router';
|
79
|
-
import match from 'react-router/lib/match';
|
80
|
-
import browserHistory from 'react-router/lib/browserHistory';
|
81
|
-
import { Provider } from 'react-redux';
|
82
|
-
|
83
|
-
import routes from '../routes/routes';
|
84
|
-
|
85
|
-
// NOTE how this function takes 3 params, and is thus responsible for calling ReactDOM.render
|
86
|
-
const RouterAppRenderer = (props, railsContext, domNodeId) => {
|
87
|
-
const store = ReactOnRails.getStore('applicationStore');
|
88
|
-
const history = browserHistory;
|
89
|
-
|
90
|
-
match({ history, routes }, (error, redirectionLocation, renderProps) => {
|
91
|
-
if (error) {
|
92
|
-
throw error;
|
93
|
-
}
|
94
|
-
|
95
|
-
const reactElement = (
|
96
|
-
<Provider store={store}>
|
97
|
-
<Router {...renderProps} />
|
98
|
-
</Provider>
|
99
|
-
);
|
100
|
-
|
101
|
-
ReactDOM.render(reactElement, document.getElementById(domNodeId));
|
102
|
-
});
|
103
|
-
};
|
104
|
-
|
105
|
-
export default RouterAppRenderer;
|
106
|
-
```
|
107
|
-
|
108
|
-
What's going on in this example is that we're putting the rendering code in the callback passed to `match`. The effect is that the client render doesn't happen until the code chunk gets fetched from the server, preventing the client/server checksum mismatch.
|
109
|
-
|
110
|
-
The idea is that match from react-router is async; it fetches the component using the getComponent method that you provide with the route definition, and then passes the props to the callback that are needed to do the complete render. Then we do the first render inside of the callback, so that the first render is the same as the server render.
|
111
|
-
|
112
|
-
The server render matches the deferred render because the server bundle is a single file, and so it doesn't need to wait for anything to be fetched.
|
113
|
-
|
114
|
-
### Working Example
|
115
|
-
|
116
|
-
There's an implemented example of code splitting in the `spec/dummy` folder of this repository.
|
117
|
-
|
118
|
-
See:
|
119
|
-
|
120
|
-
- [spec/dummy/client/app/startup/client-bundle.js](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/startup/client-bundle.js)
|
121
|
-
- [spec/dummy/client/app/packs/server-bundle.js](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/packs/server-bundle.js)
|
122
|
-
- [spec/dummy/client/app/startup/DeferredRenderAppClient](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/startup/DeferredRenderAppClient.jsx)<-- Code splitting implemented here
|
123
|
-
- [spec/dummy/client/app/startup/DeferredRenderAppServer.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/startup/DeferredRenderAppServer.jsx)
|
124
|
-
- [spec/dummy/client/app/components/DeferredRender.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/components/DeferredRender.jsx)
|
125
|
-
- [spec/dummy/client/app/components/DeferredRenderAsyncPage.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/components/DeferredRenderAsyncPage.jsx)
|
126
|
-
|
127
|
-
### Comparison of Server vs. Client Code
|
128
|
-
|
129
|
-
![image](https://user-images.githubusercontent.com/1118459/42479546-2296f794-8375-11e8-85ff-52629fcaf657.png)
|
130
|
-
|
131
|
-
### Caveats
|
132
|
-
|
133
|
-
If you're going to try to do code splitting with server rendered routes, you'll probably need to use seperate route definitions for client and server to prevent code splitting from happening for the server bundle. The server bundle should be one file containing all the JavaScript code. This will require you to have seperate webpack configurations for client and server.
|
134
|
-
|
135
|
-
The reason is we do server rendering with ExecJS, which is not capable of doing anything asynchronous. It would be impossible to asyncronously fetch a code chunk while server rendering. See [this issue](https://github.com/shakacode/react_on_rails/issues/477) for a discussion.
|
136
|
-
|
137
|
-
Also, do not attempt to register a renderer function on the server. Instead, register either a Render-Function or a component. If you register a renderer in the server bundle, you'll get an error when react on rails tries to server render the component.
|
138
|
-
|
139
|
-
## How does Webpack know where to find my code chunks?
|
140
|
-
|
141
|
-
Add the following to the output key of your webpack config:
|
142
|
-
|
143
|
-
```js
|
144
|
-
config = {
|
145
|
-
output: {
|
146
|
-
publicPath: '/assets/',
|
147
|
-
}
|
148
|
-
};
|
149
|
-
```
|
150
|
-
|
151
|
-
This causes Webpack to prepend the code chunk filename with `/assets/` in the request url. The react on rails sets up the webpack config to put webpack bundles in `app/assets/javascripts/webpack`, and modifies `config/initializers/assets.rb` so that rails detects the bundles. This means that when we prepend the request url with `/assets/`, rails will know what webpack is asking for.
|
152
|
-
|
153
|
-
See [our rails assets documentation](https://www.shakacode.com/react-on-rails/docs/outdated/rails-assets/) to learn more about static assets.
|
154
|
-
|
155
|
-
If you forget to set the public path, webpack will request the code chunk at `/{filename}`. This will cause the request to be handled by the Rails router, which will send back a 404 response, assuming that you don't have a catch-all route. In your javascript console, you'll get the following error:
|
156
|
-
|
157
|
-
> GET http://localhost:3000/1.1-bundle.js
|
158
|
-
|
159
|
-
You'll also see the following in your Rails development log:
|
160
|
-
|
161
|
-
> Started GET "/1.1-bundle.js" for 127.0.0.1 at 2016-11-29 15:21:55 -0800
|
162
|
-
>
|
163
|
-
> ActionController::RoutingError (No route matches [GET] "/1.1-bundle.js")
|
164
|
-
|
165
|
-
It's worth mentioning that in Webpack v2, it's possible to register an error handler by calling `catch` on the promise returned by `System.import`, so if you want to do error handling, you should use v2. The [example](#working-example) in `spec/dummy` is currently using Webpack v1.
|
@@ -1,10 +0,0 @@
|
|
1
|
-
# Converting from Custom Webpack Config to Rails Webpacker Config
|
2
|
-
|
3
|
-
1. Compare your package.json and the dependencies in https://github.com/rails/webpacker/blob/master/package.json
|
4
|
-
and avoid any duplicates. We don't want different versions of the same packages.
|
5
|
-
We want the versions from rails/webpacker unless we specifically want to override them.
|
6
|
-
2. Search the rails/webpacker repo for anything you're not sure about in terms of package names.
|
7
|
-
3. run `bin/webpacker` and make sure there are zero errors
|
8
|
-
4. update webpack plugins and loaders to current or close to current
|
9
|
-
5. Make sure that your bin/webpacker and bin/webpacker match the latest on
|
10
|
-
https://github.com/rails/webpacker/tree/master/lib/install/bin
|
data/docs/javascript/credits.md
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
## Authors
|
2
|
-
|
3
|
-
[The Shaka Code team!](http://www.shakacode.com/about/)
|
4
|
-
|
5
|
-
The origins of the project began with the need to do a rich JavaScript interface for a ShakaCode's client. The choice to use Webpack and Rails is 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/).
|
6
|
-
|
7
|
-
The gem project started with [Justin Gordon](https://github.com/justin808/) pairing with [Samnang Chhun](https://github.com/samnang) to figure out how to do server rendering with Webpack plus Rails. [Alex Fedoseev](https://github.com/alexfedoseev) then joined in. [Rob Wise](https://github.com/robwise), [Aaron Van Bokhoven](https://github.com/aaronvb), and [Andy Wang](https://github.com/yorzi) did the bulk of the generators. Many others have [contributed](https://github.com/shakacode/react_on_rails/graphs/contributors).
|
8
|
-
|
9
|
-
The gem was initially inspired by the [react-rails gem](https://github.com/reactjs/react-rails).
|
10
|
-
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# Foreman Issues
|
2
|
-
|
3
|
-
## It is not recomended to include foreman into Gemfile
|
4
|
-
|
5
|
-
See: https://github.com/ddollar/foreman
|
6
|
-
|
7
|
-
> Ruby users should take care not to install foreman in their project's Gemfile.
|
8
|
-
|
9
|
-
## Known issues
|
10
|
-
|
11
|
-
* With `foreman 0.82.0` npm `react-s3-uploader` was failing to finish upload file to S3 when server was started by `foreman -f Procfile.dev`,
|
12
|
-
at the same time the same code works fine when ruby server started by `bundle exec rails s`.
|
13
|
-
|
14
|
-
* The same Procfile with different versions of `foreman` in combination with different versions of `bundler` may produce different output of `ps aux`.
|
15
|
-
This may brake bash tools which rely on `ps` output.
|
data/docs/javascript/images.md
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
# Images
|
2
|
-
|
3
|
-
1. leading slash necessary on the
|
4
|
-
a. Option name for the file-loader and url-loader (todo reference)
|
5
|
-
b. Option publicPath for the output (todo reference)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
```
|
12
|
-
const assetLoaderRules = [
|
13
|
-
{
|
14
|
-
test: /\.(jpe?g|png|gif|ico|woff)$/,
|
15
|
-
use: {
|
16
|
-
loader: 'url-loader',
|
17
|
-
options: {
|
18
|
-
limit: urlFileSizeCutover,
|
19
|
-
// Leading slash is 100% needed
|
20
|
-
name: 'images/[hash].[ext]',
|
21
|
-
},
|
22
|
-
},
|
23
|
-
},
|
24
|
-
{
|
25
|
-
test: /\.(ttf|eot|svg)$/,
|
26
|
-
use: {
|
27
|
-
loader: 'file-loader',
|
28
|
-
options: {
|
29
|
-
// Leading slash is 100% needed
|
30
|
-
name: '/images/[hash].[ext]',
|
31
|
-
}
|
32
|
-
},
|
33
|
-
},
|
34
|
-
];
|
35
|
-
|
36
|
-
```
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
A full example can be found at [spec/dummy/client/app/components/ImageExample/ImageExample.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/components/ImageExample/ImageExample.jsx)
|
43
|
-
|
44
|
-
You are free to use images either in image tags or as background images in SCSS files. You can
|
45
|
-
use a "global" location of /client/app/assets/images or a relative path to your JS or SCSS file, as
|
46
|
-
is done with CSS modules.
|
47
|
-
|
48
|
-
**images** is a defined alias, so "images/foobar.jpg" would point to the file at
|
49
|
-
`/client/app/assets/images/foobar.jpg.`
|
50
|
-
|
51
|
-
```
|
52
|
-
resolve: {
|
53
|
-
alias: {
|
54
|
-
images: join(process.cwd(), 'app', 'assets', 'images'),
|
55
|
-
},
|
56
|
-
},
|
57
|
-
```
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# Node Dependencies, NPM, and Yarn
|
2
|
-
|
3
|
-
## Updating
|
4
|
-
|
5
|
-
You can check for outdated versions of packages with `yarn outdated` in your `client` directory.
|
6
|
-
|
7
|
-
To upgrade package version, use `yarn upgrade [package]`. To update all dependencies, use `yarn upgrade`.
|
8
|
-
|
9
|
-
Confirm that the hot replacement dev server and the Rails server both work.
|
10
|
-
|
11
|
-
## Adding New Dependencies
|
12
|
-
Typically, you can add your Node dependencies as you normally would.
|
13
|
-
|
14
|
-
```bash
|
15
|
-
cd client
|
16
|
-
yarn add module_name@version
|
17
|
-
# or
|
18
|
-
# yarn add --dev module_name@version
|
19
|
-
```
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# Communication between React Components and Redux Reducers
|
2
|
-
|
3
|
-
## Communication Between Components
|
4
|
-
See https://facebook.github.io/react/tips/communicate-between-components.html
|
5
|
-
|
6
|
-
# Redux Reducers
|
7
|
-
Documentation of generated Redux code for reducers.
|
8
|
-
|
9
|
-
## Example
|
10
|
-
The `helloWorld/reducers/index.jsx` example that results from running the generator with the Redux option may be slightly confusing because of its simplicity. For clarity, what follows is a more fleshed-out example of what a reducer might look like:
|
11
|
-
|
12
|
-
```javascript
|
13
|
-
import usersReducer from './usersReducer';
|
14
|
-
import blogPostsReducer from './blogPostsReducer';
|
15
|
-
import commentsReducer from './commentsReducer';
|
16
|
-
// ...
|
17
|
-
|
18
|
-
import { $$initialState as $$usersState } from './usersReducer';
|
19
|
-
import { $$initialState as $$blogPostsState } from './blogPostsReducer';
|
20
|
-
import { $$initialState as $$commentsState } from './commentsReducer';
|
21
|
-
// ...
|
22
|
-
|
23
|
-
export default {
|
24
|
-
$$usersStore: usersReducer,
|
25
|
-
$$blogPostsStore: blogPostsReducer,
|
26
|
-
$$commentsStore: commentsReducer,
|
27
|
-
// ...
|
28
|
-
};
|
29
|
-
|
30
|
-
export const initialStates = {
|
31
|
-
$$usersState,
|
32
|
-
$$blogPostsState,
|
33
|
-
$$commentsState,
|
34
|
-
// ...
|
35
|
-
};
|
36
|
-
```
|
@@ -1,100 +0,0 @@
|
|
1
|
-
# Using React Helmet to build `<head>` content
|
2
|
-
|
3
|
-
## Installation and general usage
|
4
|
-
See [nfl/react-helmet](https://github.com/nfl/react-helmet) for details on how to use this package.
|
5
|
-
Run `yarn add react-helmet` to add this package to your application.
|
6
|
-
|
7
|
-
## Example
|
8
|
-
Here is what you need to do in order to configure your Rails application to work with **ReactHelmet**.
|
9
|
-
|
10
|
-
Create a render-function for server rendering like this:
|
11
|
-
|
12
|
-
```javascript
|
13
|
-
export default (props, _railsContext) => {
|
14
|
-
const componentHtml = renderToString(<App {...props} />);
|
15
|
-
const helmet = Helmet.renderStatic();
|
16
|
-
|
17
|
-
const renderedHtml = {
|
18
|
-
componentHtml,
|
19
|
-
title: helmet.title.toString(),
|
20
|
-
};
|
21
|
-
return { renderedHtml };
|
22
|
-
};
|
23
|
-
```
|
24
|
-
You can add more **helmet** properties to the result, e.g. **meta**, **base** and so on. See https://github.com/nfl/react-helmet#server-usage.
|
25
|
-
|
26
|
-
Use a regular React functional or class component or a render-function for your client-side bundle:
|
27
|
-
|
28
|
-
```javascript
|
29
|
-
// React functional component
|
30
|
-
export default (props) => (
|
31
|
-
<App {...props} />
|
32
|
-
);
|
33
|
-
```
|
34
|
-
|
35
|
-
Or a render-function. Note you can't return just the JSX (React element), but you need to return
|
36
|
-
either a React functional or class component.
|
37
|
-
```javascript
|
38
|
-
// React functional component
|
39
|
-
export default (props, railsContext) => (
|
40
|
-
() => <App {{railsContext, ...props}} />
|
41
|
-
);
|
42
|
-
```
|
43
|
-
|
44
|
-
Note, this doesn't work, because this function just returns a React element rather than a React component
|
45
|
-
```javascript
|
46
|
-
// React functional component
|
47
|
-
export default (props, railsContext) => (
|
48
|
-
<App {{railsContext, ...props}} />
|
49
|
-
);
|
50
|
-
```
|
51
|
-
|
52
|
-
Put the **ReactHelmet** component somewhere in your `<App>`:
|
53
|
-
```javascript
|
54
|
-
import { Helmet } from 'react-helmet';
|
55
|
-
|
56
|
-
const App = (props) => (
|
57
|
-
<div>
|
58
|
-
<Helmet>
|
59
|
-
<title>Custom page title</title>
|
60
|
-
</Helmet>
|
61
|
-
...
|
62
|
-
</div>
|
63
|
-
);
|
64
|
-
|
65
|
-
export default App;
|
66
|
-
```
|
67
|
-
Register your generators for client and server sides:
|
68
|
-
|
69
|
-
```javascript
|
70
|
-
import ReactHelmetApp from '../ReactHelmetClientApp';
|
71
|
-
|
72
|
-
ReactOnRails.register({
|
73
|
-
ReactHelmetApp
|
74
|
-
});
|
75
|
-
```
|
76
|
-
```javascript
|
77
|
-
// Note the import from the server file.
|
78
|
-
import ReactHelmetApp from '../ReactHelmetServerApp';
|
79
|
-
|
80
|
-
ReactOnRails.register({
|
81
|
-
ReactHelmetApp
|
82
|
-
});
|
83
|
-
```
|
84
|
-
Now when the `react_component_hash` helper is called with **"ReactHelmetApp"** as a first argument it
|
85
|
-
will return a hash instead of HTML string. Note, there is no need to specify "prerender" as it would not
|
86
|
-
make sense to use react_component_hash without server rendering:
|
87
|
-
```ruby
|
88
|
-
<% react_helmet_app = react_component_hash("ReactHelmetApp", props: { hello: "world" }, trace: true) %>
|
89
|
-
|
90
|
-
<% content_for :title do %>
|
91
|
-
<%= react_helmet_app['title'] %>
|
92
|
-
<% end %>
|
93
|
-
|
94
|
-
<%= react_helmet_app["componentHtml"] %>
|
95
|
-
```
|
96
|
-
|
97
|
-
So now we're able to insert received title tag to our application layout:
|
98
|
-
```ruby
|
99
|
-
<%= yield(:title) if content_for?(:title) %>
|
100
|
-
```
|
@@ -1,90 +0,0 @@
|
|
1
|
-
_This article needs updating for the latest version of React Router_
|
2
|
-
|
3
|
-
# Using React Router
|
4
|
-
|
5
|
-
|
6
|
-
React on Rails supports the use of React Router. Client-side code doesn't need any special configuration for the React on Rails gem. Implement React Router how you normally would. Note, you might want to avoid using Turbolinks as both Turbolinks and React-Router will be trying to handle the back and forward buttons. If you get this figured out, please do share with the community! Otherwise, you might have to tweak the basic settings for Turbolinks, and this may or may not be worth the effort.
|
7
|
-
|
8
|
-
If you are working with the HelloWorldApp created by the react_on_rails generator, then the code below corresponds to the module in `client/app/bundles/HelloWorld/startup/HelloWorldApp.jsx`.
|
9
|
-
|
10
|
-
```js
|
11
|
-
|
12
|
-
import { BrowserRouter, Switch } from 'react-router-dom'
|
13
|
-
import routes from './routes.jsx'
|
14
|
-
|
15
|
-
const RouterApp = (props, railsContext) => {
|
16
|
-
// create your hydrated store
|
17
|
-
const store = createStore(props);
|
18
|
-
|
19
|
-
return (
|
20
|
-
<Provider store={store}>
|
21
|
-
<BrowserRouter>
|
22
|
-
<Switch>
|
23
|
-
{routes}
|
24
|
-
</Switch>
|
25
|
-
</BrowserRouter>
|
26
|
-
</Provider>
|
27
|
-
);
|
28
|
-
};
|
29
|
-
```
|
30
|
-
|
31
|
-
For a fleshed out integration of react_on_rails with react-router, check out [React Webpack Rails Tutorial Code](https://github.com/shakacode/react-webpack-rails-tutorial), specifically the files:
|
32
|
-
|
33
|
-
* [react-webpack-rails-tutorial/client/app/bundles/comments/routes/routes.jsx](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/app/bundles/comments/routes/routes.jsx)
|
34
|
-
|
35
|
-
* [react-webpack-rails-tutorial/client/app/bundles/comments/startup/ClientRouterApp.jsx](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/app/bundles/comments/startup/ClientRouterApp.jsx)
|
36
|
-
|
37
|
-
* [react-webpack-rails-tutorial/client/app/bundles/comments/startup/ServerRouterApp.jsx](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/app/bundles/comments/startup/ServerRouterApp.jsx)
|
38
|
-
|
39
|
-
|
40
|
-
# Server Rendering Using React Router V4
|
41
|
-
|
42
|
-
Your Render-Function may not return an object with the property `renderedHtml`. Thus, you call
|
43
|
-
renderToString() and return an object with this property.
|
44
|
-
|
45
|
-
This example **only applies to server rendering** and should be only used in the server side bundle.
|
46
|
-
|
47
|
-
From the [original example in the ReactRouter docs](https://github.com/ReactTraining/react-router/blob/v4.3.1/packages/react-router-dom/docs/guides/server-rendering.md)
|
48
|
-
|
49
|
-
```javascript
|
50
|
-
import React from 'react'
|
51
|
-
import { renderToString } from 'react-dom/server'
|
52
|
-
import { StaticRouter } from 'react-router'
|
53
|
-
import { Provider } from 'react-redux'
|
54
|
-
import ReactOnRails from 'react-on-rails'
|
55
|
-
|
56
|
-
// App.jsx from src/client/App.jsx
|
57
|
-
import App from '../App'
|
58
|
-
|
59
|
-
const ReactServerRenderer = (props, railsContext) => {
|
60
|
-
const context = {}
|
61
|
-
|
62
|
-
// commentStore from src/server/store/commentStore
|
63
|
-
const store = ReactOnRails.getStore('../store/commentStore')
|
64
|
-
|
65
|
-
// Route Store generated from react-on-rails
|
66
|
-
|
67
|
-
const { location } = railsContext
|
68
|
-
|
69
|
-
const html = ReactDOMServer.renderToString(
|
70
|
-
<Provider store={store}>
|
71
|
-
<StaticRouter
|
72
|
-
location={location}
|
73
|
-
context={context}
|
74
|
-
props={props}
|
75
|
-
>
|
76
|
-
<App />
|
77
|
-
</StaticRouter>
|
78
|
-
</ Provider>
|
79
|
-
)
|
80
|
-
|
81
|
-
if (context.url) {
|
82
|
-
// Somewhere a `<Redirect>` was rendered
|
83
|
-
redirect(301, context.url)
|
84
|
-
} else {
|
85
|
-
// we're good, send the response
|
86
|
-
return { renderedHtml: html };
|
87
|
-
}
|
88
|
-
}
|
89
|
-
}
|
90
|
-
```
|