react_on_rails 11.0.9 → 11.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +8 -2
  4. data/{docs/LICENSE.md → LICENSE.md} +1 -1
  5. data/README.md +177 -693
  6. data/SUMMARY.md +39 -26
  7. data/docs/additional-reading/convert-rails-5-api-only-app.md +19 -0
  8. data/docs/additional-reading/credits.md +10 -0
  9. data/docs/additional-reading/rails-assets-relative-paths.md +2 -2
  10. data/docs/additional-reading/server-rendering-tips.md +2 -4
  11. data/docs/additional-reading/webpack.md +2 -2
  12. data/docs/api/javascript-api.md +21 -1
  13. data/docs/api/redux-store-api.md +100 -0
  14. data/docs/api/view-helpers-api.md +115 -0
  15. data/docs/articles.md +20 -0
  16. data/docs/basics/client-vs-server-rendering.md +17 -0
  17. data/docs/basics/deployment.md +6 -0
  18. data/docs/basics/{generator.md → generator-details.md} +4 -7
  19. data/docs/basics/generator-functions-and-railscontext.md +157 -0
  20. data/docs/basics/how-react-on-rails-works.md +40 -0
  21. data/docs/basics/installation-into-an-existing-rails-app.md +64 -0
  22. data/docs/basics/react-server-rendering.md +27 -0
  23. data/docs/{additional-reading → basics}/recommended-project-structure.md +26 -4
  24. data/docs/{additional-reading → basics}/rspec-configuration.md +0 -0
  25. data/docs/basics/webpack-configuration.md +29 -0
  26. data/docs/misc/doctrine.md +1 -1
  27. data/docs/{additional-reading → misc-pending}/code-splitting.md +8 -2
  28. data/docs/{basics/installation-overview.md → misc-pending/manual-installation-overview.md} +3 -8
  29. data/docs/{additional-reading → misc-pending}/rails-assets.md +3 -1
  30. data/docs/testimonials.md +11 -0
  31. data/docs/tutorial.md +4 -4
  32. data/lib/generators/USAGE +1 -1
  33. data/lib/react_on_rails/{react_on_rails_helper.rb → helper.rb} +4 -4
  34. data/lib/react_on_rails/prerender_error.rb +7 -3
  35. data/lib/react_on_rails/server_rendering_pool.rb +0 -1
  36. data/lib/react_on_rails/utils.rb +17 -0
  37. data/lib/react_on_rails/version.rb +1 -1
  38. data/lib/react_on_rails.rb +1 -1
  39. data/package.json +1 -1
  40. data/react_on_rails.gemspec +1 -1
  41. metadata +27 -17
  42. data/docs/additional-reading/caching-and-performance.md +0 -4
  43. data/docs/additional-reading/node-server-rendering.md +0 -5
  44. data/docs/api/ruby-api.md +0 -8
@@ -0,0 +1,157 @@
1
+ # Generator Functions and Rails Context
2
+
3
+ ## Generator Functions
4
+
5
+ When you use a "generator function" to create react components (or renderedHtml on the server), or you used shared redux stores, you get two params passed to your function that creates a React component:
6
+
7
+ 1. `props`: Props that you pass in the view helper of either `react_component` or `redux_store`
8
+ 2. `railsContext`: Rails contextual information, such as the current pathname. You can customize this in your config file. **Note**: The `railsContext` is not related to the concept of a ["context" for React components](https://facebook.github.io/react/docs/context.html#how-to-use-context).
9
+
10
+ This parameters (`props` and `railsContext`) will be the same regardless of either client or server side rendering, except for the key `serverSide` based on whether or not you are server rendering.
11
+
12
+ While you could manually configure your Rails code to pass the "`railsContext` information" with the rest of your "props", the `railsContext` is a convenience because it's passed consistently to all invocations of generator functions.
13
+
14
+ For example, suppose you create a "generator function" called MyAppComponent.
15
+
16
+ ```js
17
+ import React from 'react';
18
+ const MyAppComponent = (props, railsContext) => (
19
+ <div>
20
+ <p>props are: {JSON.stringify(props)}</p>
21
+ <p>railsContext is: {JSON.stringify(railsContext)}
22
+ </p>
23
+ </div>
24
+ );
25
+ export default MyAppComponent;
26
+ ```
27
+
28
+ *Note: you will get a React browser console warning if you try to serverRender this since the value of `serverSide` will be different for server rendering.*
29
+
30
+ So if you register your generator function `MyAppComponent`, it will get called like:
31
+
32
+ ```js
33
+ reactComponent = MyAppComponent(props, railsContext);
34
+ ```
35
+
36
+ and, similarly, any redux store always initialized with 2 parameters:
37
+
38
+ ```js
39
+ reduxStore = MyReduxStore(props, railsContext);
40
+ ```
41
+
42
+ Note: you never make these calls. React on Rails makes these calls when it does either client or server rendering. You will define functions that take these 2 params and return a React component or a Redux Store. Naturally, you do not have to use second parameter of the railsContext if you do not need it.
43
+
44
+ (Note: see below [section](#multiple-react-components-on-a-page-with-one-store) on how to setup redux stores that allow multiple components to talk to the same store.)
45
+
46
+ The `railsContext` has: (see implementation in file [react_on_rails_helper.rb](https://github.com/shakacode/react_on_rails/tree/master/app/helpers/react_on_rails_helper.rb), method `rails_context` for the definitive list).
47
+
48
+ ```ruby
49
+ {
50
+ railsEnv: Rails.env
51
+ # URL settings
52
+ href: request.original_url,
53
+ location: "#{uri.path}#{uri.query.present? ? "?#{uri.query}": ""}",
54
+ scheme: uri.scheme, # http
55
+ host: uri.host, # foo.com
56
+ port: uri.port,
57
+ pathname: uri.path, # /posts
58
+ search: uri.query, # id=30&limit=5
59
+
60
+ # Other
61
+ serverSide: boolean # Are we being called on the server or client? Note: if you conditionally
62
+ # render something different on the server than the client, then React will only show the
63
+ # server version!
64
+ }
65
+ ```
66
+
67
+ ## Rails Context
68
+
69
+ The `railsContext` is a second param passed to your generator functions for React components. This is in addition to the props that are passed from the `react_component` Rails helper. For example:
70
+
71
+ ERB view file:
72
+
73
+ ```ruby
74
+ # Rails View
75
+ <%= react_component("HelloWorld", props: { name: "Stranger" }) %>
76
+ ```
77
+
78
+ This is what your HelloWorld.js file might contain. The railsContext is always available for any parameters that you _always_ want available for your React components. It has _nothing_ to do with the concept of the [React Context](https://reactjs.org/docs/context.html).
79
+
80
+ ```js
81
+ import React from 'react';
82
+
83
+ export default (props, railsContext) => {
84
+ return (
85
+ <div>
86
+ Your locale is {railsContext.i18nLocale}.<br/>
87
+ Hello, {props.name}!
88
+ </div>
89
+ );
90
+ };
91
+ ```
92
+
93
+ ## Why is the railsContext is only passed to generator functions?
94
+
95
+ There's no reason that the railsContext would ever get passed to your React component unless the value is explicitly put into the props used for rendering. If you create a react component, rather than a generator function, for use by React on Rails, then you get whatever props are passed in from the view helper, which **does not include the Rails Context**. It's trivial to wrap your component in a "generator function" to return a new component that takes both:
96
+
97
+ ```js
98
+ import React from 'react';
99
+ import AppComponent from './AppComponent';
100
+ const AppComponentWithRailsContext = (props, railsContext) => (
101
+ <AppComponent {...{...props, railsContext}}/>
102
+ )
103
+ export default AppComponentWithRailsContext;
104
+ ```
105
+
106
+ Consider this line in depth:
107
+
108
+ ```js
109
+ <AppComponent {...{ ...props, railsContext }}/>
110
+ ```
111
+
112
+ The outer `{...` is for the [JSX spread operator for attributes](https://facebook.github.io/react/docs/jsx-in-depth.html#spread-attributes) and the innner `{...` is for the [Spread in object literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Spread_in_object_literals).
113
+
114
+ ## Use Cases
115
+
116
+ ### Heroku Preboot Considerations
117
+
118
+ [Heroku Preboot](https://devcenter.heroku.com/articles/preboot) is a feature on Heroku that allows for faster deploy times. When you promote your staging app to production, Preboot simply switches the production server to point at the staging app's container. This means it can deploy much faster since it doesn't have to rebuild anything. However, this means that if you use the [Define Plugin](https://github.com/webpack/docs/wiki/list-of-plugins#defineplugin) to provide the rails environment to your client code as a variable, that variable will erroneously still have a value of `Staging` instead of `Production`. The `Rails.env` provided at runtime in the railsContext is, however, accurate.
119
+
120
+ ### Needing the current URL path for server rendering
121
+
122
+ Suppose you want to display a nav bar with the current navigation link highlighted by the URL. When you server-render the code, your code will need to know the current URL/path. The new `railsContext` has this information. Your application will apply something like an "active" class on the server rendering.
123
+
124
+ ### Configuring different code for server side rendering
125
+
126
+ Suppose you want to turn off animation when doing server side rendering. The `serverSide` value is just what you need.
127
+
128
+ ## Customization of the rails_context
129
+
130
+ You can customize the values passed in the `railsContext` in your `config/initializers/react_on_rails.rb`. Here's how.
131
+
132
+ Set the config value for the `rendering_extension`:
133
+
134
+ ```ruby
135
+ config.rendering_extension = RenderingExtension
136
+ ```
137
+
138
+ Implement it like this above in the same file. Create a class method on the module called `custom_context` that takes the `view_context` for a param.
139
+
140
+ See [spec/dummy/config/initializers/react_on_rails.rb](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/config/initializers/react_on_rails.rb) for a detailed example.
141
+
142
+ ```ruby
143
+ module RenderingExtension
144
+
145
+ # Return a Hash that contains custom values from the view context that will get merged with
146
+ # the standard rails_context values and passed to all calls to generator functions used by the
147
+ # react_component and redux_store view helpers
148
+ def self.custom_context(view_context)
149
+ {
150
+ somethingUseful: view_context.session[:something_useful]
151
+ }
152
+ end
153
+ end
154
+ ```
155
+
156
+ In this case, a prop and value for `somethingUseful` will go into the railsContext passed to all react_component and redux_store calls. You may set any values available in the view rendering context.
157
+
@@ -0,0 +1,40 @@
1
+ # How React on Rails Works (with rails/webpacker)
2
+
3
+ *Note, older versions of React on Rails pushed the Webpack bundles through the Asset Pipeline. This older method has *many* disadvantages, such as broken sourcemaps, performance issues, etc. If you need help migrating to the current way of bypassing the Asset Pipeline, [email Justin](mailto:justin@shakacode.com).*
4
+
5
+ Webpack is used to generate JavaScript and CSS "bundles" directly to your `/public` directory. [rails/webpacker](https://github.com/rails/webpacker) provides view helpers to access the Webpack generated (and fingerprinted) JS and CSS. These files totally skip the Rails asset pipeline. You are responsible for properly configuring your Webpack output. You will either use the standard Webpack configuration (*recommended*) or the `rails/webpacker` setup for Webpack.
6
+
7
+ Ensure these generated bundle files are in your `.gitignore`, as you never want to add the large compiled bundles to git.
8
+
9
+ Inside your Rails views, you can now use the `react_component` helper method provided by React on Rails. You can pass props directly to the react component helper.
10
+
11
+ Optionally, you can also initialize a Redux store with the view or controller helper `redux_store` so that the redux store can be shared amongst multiple React components.
12
+
13
+ ## Client-Side Rendering vs. Server-Side Rendering
14
+
15
+ In most cases, you should use the `prerender: false` (default behavior) with the provided `react_component` helper method to render the React component from your Rails views. In some cases, such as when SEO is vital, or many users will not have JavaScript enabled, you can enable server-rendering by passing `prerender: true` to your helper, or you can simply change the default in `config/initializers/react_on_rails`.
16
+
17
+ Now the server will interpret your JavaScript. The default is to use [ExecJS](https://github.com/rails/execjs) and pass the resulting HTML to the client. If you want to maximize the perfomance of your server rendering, then you want to use React on Rails Pro which uses NodeJS to do the server rendering. See the [docs for React on Rails Pro](https://github.com/shakacode/react_on_rails/wiki).
18
+
19
+ ## HTML Source Code
20
+
21
+ If you open the HTML source of any web page using React on Rails, you'll see the 3 parts of React on Rails rendering:
22
+
23
+ 1. The wrapper div `<div id="HelloWorld-react-component-0">` specifies the div where to place the React rendering. It encloses the server-rendered HTML for the React component. If server rendering is not used (prerender: false), then the major difference is that the HTML rendered for the React component only contains the outer div: `<div id="HelloWorld-react-component-0"/>`. The first specification of the React component is just the same.
24
+ 1. A script tag containing the properties of the React component, such as the registered name and any props. A JavaScript function runs after the page loads, using this data to build and initialize your React components.
25
+ 1. Additional JavaScript is placed to console-log any messages, such as server rendering errors. Note: these server side logs can be configured only to be sent to the server logs.
26
+
27
+ You can see all this on the source for [reactrails.com](https://www.reactrails.com/)
28
+
29
+ ## Building the Bundles
30
+
31
+ Each time you change your client code, you will need to re-generate the bundles (the webpack-created JavaScript files included in application.js). The included example Foreman `Procfile.dev` files will take care of this for you by starting a webpack process with the watch flag. This will watch your JavaScript code files for changes.
32
+
33
+ Simply run `foreman start -f Procfile.dev`. [Example](spec/dummy/Procfile.static).
34
+
35
+ On production deployments that use asset precompilation, such as Heroku deployments, React on Rails, by default, will automatically run webpack to build your JavaScript bundles. You configure the command used as `config.build_production_command` in your [config/initializers/react_on_rails.rb](./configuration.md).
36
+
37
+ You can see the source code for what gets added to your precompilation [here](https://github.com/shakacode/react_on_rails/tree/master/lib/tasks/assets.rake). For more information on this topic, see [the doc on Heroku deployment](docs/additional-reading/heroku-deployment.md#more-details-on-precompilation-using-webpack-to-create-javascript-assets).
38
+
39
+ If you have used the provided generator, these bundles will automatically be added to your `.gitignore` to prevent extraneous noise from re-generated code in your pull requests. You will want to do this manually if you do not use the provided generator.
40
+
@@ -0,0 +1,64 @@
1
+ # Getting Started with an existing Rails app
2
+
3
+ **Also consult the instructions for installing on a fresh Rails app**, see the [React on Rails Basic Tutorial](../../docs/tutorial.md).
4
+
5
+ **If you have rails-5 API only project**, first [convert the rails-5 API only app to rails app](#convert-rails-5-api-only-app-to-rails-app) before [getting started](#getting-started-with-an-existing-rails-app).
6
+
7
+ 1. Add the following to your Gemfile and `bundle install`. We recommend fixing the version of React on Rails, as you will need to keep the exact version in sync with the version in your `client/package.json` file.
8
+
9
+ ```ruby
10
+ gem "react_on_rails", "11.0.0" # Update to the current version
11
+ gem "webpacker", "~> 3" # Newer versions might be supported
12
+ ```
13
+
14
+ 2. Run the following 2 commands to install Webpacker with React. Note, f you are using an older version of Rails than 5.1, you'll need to install webpacker with React per the instructions [here](https://github.com/rails/webpacker).
15
+
16
+
17
+ ```bash
18
+ $ bundle exec rails webpacker:install
19
+ $ bundle exec rails webpacker:install:react
20
+ ```
21
+
22
+ 3. Commit this to git (or else you cannot run the generator unless you pass the option `--ignore-warnings`).
23
+
24
+ 4. See help for the generator:
25
+
26
+ ```bash
27
+ $ rails generate react_on_rails:install --help
28
+ ```
29
+
30
+ 5. Run the generator with a simple "Hello World" example (more options below):
31
+
32
+ ```bash
33
+ $ rails generate react_on_rails:install
34
+ ```
35
+
36
+ 6. Ensure that you have `foreman` installed: `gem install foreman`.
37
+
38
+ 7. Start your Rails server:
39
+
40
+ ```bash
41
+ $ foreman start -f Procfile.dev
42
+ ```
43
+
44
+ 8. Visit [localhost:3000/hello_world](http://localhost:3000/hello_world). Note: `foreman` defaults to PORT 5000 unless you set the value of PORT in your environment. For example, you can `export PORT=3000` to use the Rails default port of 3000. For the hello_world example this is already set.
45
+
46
+ ## Installation
47
+
48
+ See the [Installation Overview](../misc-pending/manual-installation-overview.md) for a concise set summary of what's in a React on Rails installation.
49
+
50
+
51
+ ## NPM
52
+
53
+ All JavaScript in React On Rails is loaded from npm: [react-on-rails](https://www.npmjs.com/package/react-on-rails). To manually install this (you did not use the generator), assuming you have a standard configuration, run this command (assuming you are in the directory where you have your `node_modules`):
54
+
55
+ ```bash
56
+ $ yarn add react-on-rails --exact
57
+ ```
58
+
59
+ That will install the latest version and update your package.json. **NOTE:** the `--exact` flag will ensure that you do not have a "~" or "^" for your react-on-rails version in your package.json.
60
+
61
+ ## Webpacker Configuration
62
+
63
+ React on Rails users should set configuration value `compile` to false, as React on Rails handles compilation for test and production environments.
64
+
@@ -0,0 +1,27 @@
1
+ # React Server Rendering
2
+
3
+ ## What is Server Rendering?
4
+
5
+ Here's a [decent article to introduce you to server rendering](https://medium.freecodecamp.org/server-side-rendering-your-react-app-in-three-simple-steps-7a82b95db82e). Note, React on Rails takes care of calling the methods in [ReactDOMServer](https://reactjs.org/docs/react-dom-server.html).
6
+
7
+ During the Rails rendering of HTML per a browser request, the Rails server will execute some JavaScript to create a string of HTML used for React server rendering. This resulting HTML is placed with in your Rails view's output.
8
+
9
+ The default JavaScript interpretter is [ExecJS](https://github.com/rails/execjs). If you want to maximize the perfomance of your server rendering, then you want to use React on Rails Pro which uses NodeJS to do the server rendering. See the [docs for React on Rails Pro](https://github.com/shakacode/react_on_rails/wiki).
10
+
11
+ See [this note](basics/how-react-on-rails-works.md#client-side-rendering-vs-server-side-rendering)
12
+
13
+
14
+ ## How do you do Server Rendering with React on Rails?
15
+ 1. The `react_component` view helper method provides the `prerender:` option to switch on or off server rendering.
16
+ 1. Configure your Webpack setup to create a different server bundle per your needs. While you may reuse the same bundle as for client rendering, this is not common in larger apps for many reasons, such as as code splitting, handling CSS and images, different code paths for React Router on the server vs. client, etc.
17
+ 1. You need to configure `config.server_bundle_js_file = "my-server-bundle.js"` in your `config/initializers/react_on_rails.rb`
18
+
19
+ ## Do you need server rendering?
20
+
21
+ Server rendering is used for either SEO or performance reasons.
22
+
23
+ ## Considerations for what code can run on in server rendering
24
+
25
+ 1. Never access `window`. Animations, globals on window, etc. just don't make sense when you're trying to run some JavaScript code to output a string of HTML.
26
+ 2. JavaScript calls to `setTimeout`, `setInterval`, and `clearInterval` similarly don't make sense when server rendering.
27
+ 3. Promises don't work when server rendering. Anything to be done in a promise will never complete. This includes concepts such as asynchronous code loading and AJAX calls. If you want to do server rendering with asynchronous calls, [get in touch](mailto:justin@shakacode.com) as we're working on a Node renderer that handles asynchronous calls.
@@ -1,8 +1,32 @@
1
- # Project structure
1
+ # Recommended Project structure
2
2
 
3
3
  While React On Rails does not *enforce* a specific project structure, we do *recommend* a standard organization. The more we follow standards as a community, the easier it will be for all of us to move between various Rails projects that include React On Rails.
4
4
 
5
- The best way to understand these standards is to follow this example: [github.com/shakacode/react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial)
5
+ The React on Rails generator uses the standard `rails/webpacker` convention of this structure:
6
+
7
+ ```yml
8
+ app/javascript:
9
+ ├── bundles:
10
+ │ # Logical groups of files that can be used for code splitting
11
+ │ └── hello-world-bundle.js
12
+ ├── packs:
13
+ │ # only webpack entry files here
14
+ │ └── hello-world-bundle.js
15
+ ```
16
+
17
+ The problems with this structure and using rails/webpacker to configure Webpack for you:
18
+
19
+ 1. No support for different entry points for server rendering.
20
+ 2. Webpacker adds an ex``tra layer of abstraction over Webpack, which you probably don't want.
21
+
22
+ This default rails/webpacker configuration is used for the generator because:
23
+
24
+ 1. Minimizes the amount of generated code to get up and running with React on Rails.
25
+ 2. Good enough for very simple projects.
26
+ 3. Configuration of Webpack is not the goal of this library, React on Rails.
27
+
28
+
29
+ Thus, the generator structure and using rails/webpacker for Webpack configuration **is not recommended** for any commercial projects, especially those that will use server rendering. Instead, the recommended structure is shown in this example app: [github.com/shakacode/react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial) and described below.
6
30
 
7
31
  ## JavaScript Assets
8
32
  1. `/client`: All client side JavaScript goes under the `/client` directory. Place all the major domains of the client side app under client.
@@ -45,5 +69,3 @@ This technique involves customization of the webpack config files to generate CS
45
69
 
46
70
  #### Updates 2017-03-04 Regarding CSS handled by Webpack
47
71
  * See article [Best practices for CSS and CSS Modules using Webpack](https://forum.shakacode.com/t/best-practices-for-css-and-css-modules-using-webpack/799).
48
- * In the near future, all docs will be updated to Webpack v2 and probably recommended to move all CSS handling to Webpack v2 for advanced users. In the near term, global CSS handled by Rails will be best for simple projects. Another data point is that Rails is moving in direction of handling JavaScript, but not CSS, with [Webpacker](https://github.com/rails/webpacker).
49
-
@@ -0,0 +1,29 @@
1
+ # Webpack Configuration: custom setup for Webpack or rails/webpacker?
2
+
3
+ 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.
4
+
5
+ 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.
6
+
7
+ ## Option 1: Recommended: Traditional React on Rails using the /client directory
8
+
9
+ 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`. The
10
+
11
+ The [ShakaCode Team](http://www.shakacode.com) _recommends_ this approach for projects beyond the simplest cases as it provides the greatest transparency in your webpack and overall client-side setup. The *big advantage* to this is that almost everything within the `/client` directory will apply if you wish to convert your client-side code to a pure Single Page Application that runs without Rails. This allows you to google for how to do something with Webpack configuration and what applies to a non-Rails app will apply just as well to a React on Rails app.
12
+
13
+ The two best examples of this pattern are the [react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial) and the integration test example in [spec/dummy](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy).
14
+
15
+ In this case, you don't need to understand the nuances of customization of your Wepback config via the [Webpacker mechanism](./docs/additional-reading/webpack-tips.md).
16
+
17
+ ## Option 2: Default Generator Setup: rails/webpacker app/javascript
18
+
19
+ Typical rails/webpacker apps have a standard directory structure as documented [here](https://github.com/rails/webpacker/blob/master/docs/folder-structure.md). If you follow the steps in the the [basic tutorial](../../docs/tutorial.md), 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://github.com/rails/webpacker/blob/master/docs/webpack.md).
20
+
21
+ 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. The *big disadvantage* to this is that you will need to learn the ins and outs of the [rails/webpacker way to customize Webpack](https://github.com/rails/webpacker/blob/master/docs/webpack.md) which differs from the plain [Webpack way](https://webpack.js.org/).
22
+
23
+ Overall, consider carefully if you prefer the `rails/webpacker` directory structure and Webpack configuration, over the placement of all client side files within the `/client` directory along with conventional Webpack configuration. Once again, the `/client` directory setup is recommended.
24
+
25
+ You can find more details on this topic in [Recommended Project Structure](./recommended-project-structure.md).
26
+
27
+ See [Issue 982: Tutorial Generating Correct Project Structure?](https://github.com/shakacode/react_on_rails/issues/982) to discuss this issue.
28
+
29
+ For more details on project setup, see [Recommended Project Structure](./docs/basics/recommended-project-structure.md).
@@ -25,7 +25,7 @@ The React on Rails setup provides several key components related to front-end de
25
25
  * React on Rails has taken the hard work out of figuring out the JavaScript tooling that works best with Rails. Not only could you spend lots of time researching different tooling, but then you'd have to figure out how to splice it all together. This is where a lot of "JavaScript fatigue" comes from. The following keep the code clean and consistent:
26
26
  * [Style Guide](../coding-style/style.md)
27
27
  * [linters](../contributor-info/linters.md)
28
- * [Recommended Project Structure](../additional-reading/recommended-project-structure.md)
28
+ * [Recommended Project Structure](../basics/recommended-project-structure.md)
29
29
 
30
30
  We're big believers in this quote from the Rails Doctrine:
31
31
 
@@ -1,5 +1,7 @@
1
1
  # Code Splitting
2
2
 
3
+ *Note: This document needs updating for Webpack v4, React-Router v4, and using webpacker.*
4
+
3
5
  What is code splitting? From the webpack documentation:
4
6
 
5
7
  > 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”.
@@ -62,7 +64,7 @@ ReactOnRails.register({
62
64
  RouterApp,
63
65
  });
64
66
  ```
65
- 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](react-router.md).
67
+ 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](../additional-reading/react-router.md).
66
68
 
67
69
  #### RouterAppRenderer.jsx
68
70
  ```jsx
@@ -118,6 +120,10 @@ See:
118
120
  - [spec/dummy/client/app/components/DeferredRender.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/components/DeferredRender.jsx)
119
121
  - [spec/dummy/client/app/components/DeferredRenderAsyncPage.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/components/DeferredRenderAsyncPage.jsx)
120
122
 
123
+ ### Comparison of Server vs. Client Code
124
+
125
+ ![image](https://user-images.githubusercontent.com/1118459/42479546-2296f794-8375-11e8-85ff-52629fcaf657.png)
126
+
121
127
  ### Caveats
122
128
 
123
129
  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.
@@ -140,7 +146,7 @@ config = {
140
146
 
141
147
  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.
142
148
 
143
- See [rails-assets.md](./rails-assets.md) to learn more about static assets.
149
+ See [rails-assets.md](rails-assets.md) to learn more about static assets.
144
150
 
145
151
  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:
146
152
 
@@ -1,17 +1,12 @@
1
- # Installation Overview
1
+ # Manual Installation Overview
2
2
 
3
- Here's an overview of installation if you're not using the generator.
3
+ TODO: Review this file
4
4
 
5
- Note, the best way to understand how to use ReactOnRails is to study the examples:
6
5
 
7
- 1. Run the generator per the [Tutorial](../tutorial.md).
8
- 2. [spec/dummy](../../spec/dummy): Simple, no DB example.
9
- 3. [github.com/shakacode/react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial): Full featured example.
6
+ This file summarizes what the React on Rails generator does.
10
7
 
11
8
  ## Configure the `/client` Directory
12
9
 
13
- Note, version 9.0 of React on Rails removed the requirement to place all client side files in the `/client` directory.
14
-
15
10
  This directory has no references to Rails outside of the destination directory for the files created by the various Webpack config files.
16
11
 
17
12
  The only requirements within this directory for basic React on Rails integration are:
@@ -1,5 +1,7 @@
1
1
  # Rails assets and the Extract Text Plugin
2
2
 
3
+ *This doc needs updating for the use of rails/webpacker with React on Rails*
4
+
3
5
  The [Webpack file loader](https://github.com/webpack/file-loader) copies referenced files to
4
6
  the destination output directory, with an MD5 hash. The other term for this is a "digest".
5
7
 
@@ -28,7 +30,7 @@ will have the Webpack digested name (MD5 hash). Since the Webpack generated CSS
28
30
  just one level of "digesting", this "double-digesting" from Rails will cause such these assets
29
31
  fail to load.
30
32
 
31
- _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](./rails-assets-relative-paths.md)._
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](../additional-reading/rails-assets-relative-paths.md)._
32
34
 
33
35
  ## The Solution: Symlink Original File Names to New File Names
34
36
  React on Rails creates symlinks of non-digested versions (original webpack digested file names)
@@ -0,0 +1,11 @@
1
+ # Testimonials
2
+
3
+ From Joel Hooks, Co-Founder, Chief Nerd at [egghead.io](https://egghead.io/), January 30, 2017:
4
+
5
+ ![2017-01-30_11-33-59](https://cloud.githubusercontent.com/assets/1118459/22443635/b3549fb4-e6e3-11e6-8ea2-6f589dc93ed3.png)
6
+
7
+ From Kyle Maune of Cooper Aerial, May 4, 2018
8
+
9
+ ![image](https://user-images.githubusercontent.com/1118459/40891236-9b0b406e-671d-11e8-80ee-c026dbd1d5a2.png)
10
+
11
+ For more testimonials, see [Live Projects](PROJECTS.md) and [Kudos](KUDOS.md).
data/docs/tutorial.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # React on Rails Basic Tutorial
2
2
 
3
- This tutorial guides you through setting up a new or existing Rails app with **React on Rails**, demonstrating Rails + React + Redux + Server Rendering. It is updated to 10.0.2.
3
+ This tutorial guides you through setting up a new or existing Rails app with **React on Rails**, demonstrating Rails + React + Redux + Server Rendering. It is updated to 11.0.8.
4
4
 
5
5
  After finishing this tutorial you will get an application that can do the following (live on Heroku):
6
6
 
@@ -28,8 +28,8 @@ nvm list # check
28
28
 
29
29
  brew install yarn # you can use other installer if desired
30
30
 
31
- rvm install 2.4.1 # download and install latest stable Ruby (update to exact version)
32
- rvm use 2.4.1 --default # use it and make it default
31
+ rvm install 2.5.0 # download and install latest stable Ruby (update to exact version)
32
+ rvm use 2.5.0 --default # use it and make it default
33
33
  rvm list # check
34
34
 
35
35
  gem install rails # download and install latest stable Rails
@@ -59,7 +59,7 @@ bundle exec rails webpacker:install:react
59
59
  Add the **React On Rails** gem to your Gemfile:
60
60
 
61
61
  ```
62
- gem 'react_on_rails', '10.0.2' # prefer exact gem version to match npm version
62
+ gem 'react_on_rails', '11.0.8' # prefer exact gem version to match npm version
63
63
  ```
64
64
 
65
65
  Note: Latest released React On Rails version is considered stable. Please use the latest version to ensure you get all the security patches and the best support.
data/lib/generators/USAGE CHANGED
@@ -21,4 +21,4 @@ Then you may run
21
21
 
22
22
  More Details:
23
23
 
24
- `https://github.com/shakacode/react_on_rails/blob/master/docs/basics/generator.md`
24
+ `https://github.com/shakacode/react_on_rails/blob/master/docs/basics/generator-details.md`
@@ -472,14 +472,14 @@ module ReactOnRails
472
472
  end
473
473
 
474
474
  def initialize_redux_stores
475
- return "" unless @registered_stores.present? || @registered_stores_defer_render.present?
476
- declarations = "var reduxProps, store, storeGenerator;\n".dup
477
- all_stores = (@registered_stores || []) + (@registered_stores_defer_render || [])
478
-
479
475
  result = <<-JS.dup
480
476
  ReactOnRails.clearHydratedStores();
481
477
  JS
482
478
 
479
+ return result unless @registered_stores.present? || @registered_stores_defer_render.present?
480
+ declarations = "var reduxProps, store, storeGenerator;\n".dup
481
+ all_stores = (@registered_stores || []) + (@registered_stores_defer_render || [])
482
+
483
483
  result << all_stores.each_with_object(declarations) do |redux_store_data, memo|
484
484
  store_name = redux_store_data[:store_name]
485
485
  props = props_string(redux_store_data[:props])
@@ -3,6 +3,7 @@
3
3
  # rubocop:disable: Layout/IndentHeredoc
4
4
  module ReactOnRails
5
5
  class PrerenderError < ::ReactOnRails::Error
6
+ MAX_ERROR_SNIPPET_TO_LOG = 1000
6
7
  # TODO: Consider remove providing original `err` as already have access to `self.cause`
7
8
  # http://blog.honeybadger.io/nested-errors-in-ruby-with-exception-cause/
8
9
  attr_reader :component_name, :err, :props, :js_code, :console_messages
@@ -58,9 +59,12 @@ Encountered error: \"#{err}\"
58
59
  end
59
60
  # rubocop:disable Layout/IndentHeredoc
60
61
  message << <<-MSG
61
- when prerendering #{component_name} with props: #{props}
62
- js_code was:
63
- #{js_code}
62
+ when prerendering #{component_name} with props: #{Utils.smart_trim(props, MAX_ERROR_SNIPPET_TO_LOG)}
63
+
64
+ code:
65
+
66
+ #{Utils.smart_trim(js_code, MAX_ERROR_SNIPPET_TO_LOG)}
67
+
64
68
  MSG
65
69
  # rubocop:enable Layout/IndentHeredoc
66
70
 
@@ -5,7 +5,6 @@ require_relative "server_rendering_pool/ruby_embedded_java_script"
5
5
 
6
6
  # Based on the react-rails gem.
7
7
  # None of these methods should be called directly.
8
- # See app/helpers/react_on_rails_helper.rb
9
8
  module ReactOnRails
10
9
  module ServerRenderingPool
11
10
  class << self
@@ -8,6 +8,8 @@ require "active_support/core_ext/string"
8
8
 
9
9
  module ReactOnRails
10
10
  module Utils
11
+ TRUNCATION_FILLER = "\n... TRUNCATED ...\n"
12
+
11
13
  # https://forum.shakacode.com/t/yak-of-the-week-ruby-2-4-pathname-empty-changed-to-look-at-file-size/901
12
14
  # return object if truthy, else return nil
13
15
  def self.truthy_presence(obj)
@@ -152,5 +154,20 @@ exitstatus: #{status.exitstatus}#{stdout_msg}#{stderr_msg}
152
154
  def self.react_on_rails_pro?
153
155
  @react_on_rails_pro ||= gem_available?("react_on_rails_pro")
154
156
  end
157
+
158
+ def self.smart_trim(str, max_length = 1000)
159
+ # From https://stackoverflow.com/a/831583/1009332
160
+ str = str.to_s
161
+ return str unless str.present? && max_length >= 1
162
+ return str if str.length <= max_length
163
+
164
+ return str[0, 1] + TRUNCATION_FILLER if max_length == 1
165
+
166
+ midpoint = (str.length / 2.0).ceil;
167
+ to_remove = str.length - max_length;
168
+ lstrip = (to_remove / 2.0).ceil;
169
+ rstrip = to_remove - lstrip;
170
+ str[0..(midpoint - lstrip - 1)] + TRUNCATION_FILLER + str[(midpoint + rstrip)..-1]
171
+ end
155
172
  end
156
173
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactOnRails
4
- VERSION = "11.0.9".freeze
4
+ VERSION = "11.0.10".freeze
5
5
  end
@@ -5,7 +5,7 @@ require "rails"
5
5
  require "react_on_rails/error"
6
6
  require "react_on_rails/prerender_error"
7
7
  require "react_on_rails/json_parse_error"
8
- require "react_on_rails/react_on_rails_helper"
8
+ require "react_on_rails/helper"
9
9
  require "react_on_rails/controller"
10
10
  require "react_on_rails/version"
11
11
  require "react_on_rails/version_checker"
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-on-rails",
3
- "version": "11.0.9",
3
+ "version": "11.0.10",
4
4
  "description": "react-on-rails JavaScript for react_on_rails Ruby gem",
5
5
  "main": "node_package/lib/ReactOnRails.js",
6
6
  "directories": {
@@ -48,7 +48,7 @@ Gem::Specification.new do |s|
48
48
 
49
49
  s.add_development_dependency "rake", "~> 10.0"
50
50
  s.add_development_dependency "rspec"
51
- s.add_development_dependency "rubocop", "0.55.0"
51
+ s.add_development_dependency "rubocop", "~> 0.58.1"
52
52
 
53
53
  s.post_install_message = '
54
54
  --------------------------------------------------------------------------------