react_on_rails 12.2.0 → 12.5.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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +12 -10
  3. data/.rubocop.yml +2 -1
  4. data/CHANGELOG.md +44 -17
  5. data/Gemfile.development_dependencies +3 -2
  6. data/NEWS.md +9 -3
  7. data/REACT-ON-RAILS-PRO-LICENSE +1 -1
  8. data/README.md +31 -317
  9. data/Rakefile +1 -1
  10. data/SUMMARY.md +21 -12
  11. data/docs/additional-details/generator-details.md +1 -1
  12. data/docs/additional-details/manual-installation-overview.md +2 -2
  13. data/docs/api/view-helpers-api.md +4 -4
  14. data/docs/contributor-info/linters.md +1 -1
  15. data/docs/contributor-info/pull-requests.md +1 -1
  16. data/docs/deployment/heroku-deployment.md +16 -5
  17. data/docs/{basics → guides}/client-vs-server-rendering.md +1 -1
  18. data/docs/{basics → guides}/configuration.md +11 -9
  19. data/docs/{basics → guides}/deployment.md +1 -1
  20. data/docs/guides/getting-started.md +183 -0
  21. data/docs/{basics → guides}/hmr-and-hot-reloading-with-the-webpack-dev-server.md +0 -0
  22. data/docs/{basics → guides}/how-react-on-rails-works.md +3 -2
  23. data/docs/guides/how-to-conditionally-server-render-based-on-device-type.md +39 -0
  24. data/docs/guides/how-to-use-different-files-for-client-and-server-rendering.md +98 -0
  25. data/docs/{basics → guides}/i18n.md +0 -0
  26. data/docs/{basics → guides}/installation-into-an-existing-rails-app.md +3 -3
  27. data/docs/{basics → guides}/minitest-configuration.md +0 -0
  28. data/docs/{rails-webpacker-react-integration-options.md → guides/rails-webpacker-react-integration-options.md} +1 -1
  29. data/docs/guides/react-on-rails-overview.md +30 -0
  30. data/docs/{basics → guides}/react-server-rendering.md +2 -2
  31. data/docs/{basics → guides}/render-functions-and-railscontext.md +0 -0
  32. data/docs/{basics → guides}/rspec-configuration.md +2 -2
  33. data/docs/{basics → guides}/tutorial.md +20 -18
  34. data/docs/{basics → guides}/upgrading-react-on-rails.md +1 -1
  35. data/docs/{basics → guides}/webpack-configuration.md +1 -1
  36. data/docs/home.md +19 -378
  37. data/docs/javascript/code-splitting.md +2 -2
  38. data/docs/misc/articles.md +1 -1
  39. data/docs/misc/doctrine.md +3 -3
  40. data/docs/outdated/rails-assets-relative-paths.md +2 -2
  41. data/docs/outdated/rails-assets.md +1 -1
  42. data/docs/rails/convert-rails-5-api-only-app.md +1 -1
  43. data/docs/rails/rails-engine-integration.md +3 -12
  44. data/docs/rails/turbolinks.md +13 -1
  45. data/docs/react-on-rails-pro/react-on-rails-pro.md +43 -0
  46. data/docs/testimonials/testimonials.md +4 -4
  47. data/lib/generators/react_on_rails/base_generator.rb +47 -4
  48. data/lib/generators/react_on_rails/generator_helper.rb +4 -0
  49. data/lib/generators/react_on_rails/templates/.eslintrc +3 -1
  50. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +4 -8
  51. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static +9 -0
  52. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
  53. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +4 -0
  54. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js +5 -0
  55. data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js +8 -0
  56. data/lib/generators/react_on_rails/templates/base/base/app/views/layouts/hello_world.html.erb +1 -0
  57. data/lib/generators/react_on_rails/templates/base/base/babel.config.js.tt +15 -0
  58. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +1 -1
  59. data/lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt +17 -0
  60. data/lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt +15 -0
  61. data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +27 -0
  62. data/lib/generators/react_on_rails/templates/base/base/config/webpack/production.js.tt +11 -0
  63. data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +117 -0
  64. data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpackConfig.js.tt +36 -0
  65. data/lib/generators/react_on_rails/templates/base/base/config/webpacker.yml +62 -0
  66. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
  67. data/lib/react_on_rails/helper.rb +6 -0
  68. data/lib/react_on_rails/locales/base.rb +7 -9
  69. data/lib/react_on_rails/server_rendering_js_code.rb +13 -0
  70. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +9 -0
  71. data/lib/react_on_rails/version.rb +1 -1
  72. data/lib/tasks/assets.rake +8 -7
  73. data/package.json +1 -1
  74. data/rakelib/example_type.rb +5 -1
  75. data/rakelib/examples.rake +7 -2
  76. data/rakelib/release.rake +1 -1
  77. data/rakelib/task_helpers.rb +7 -0
  78. data/react_on_rails.gemspec +1 -1
  79. metadata +35 -19
  80. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-hmr +0 -26
@@ -33,7 +33,40 @@ module ReactOnRails
33
33
  app/views/layouts/hello_world.html.erb
34
34
  config/initializers/react_on_rails.rb
35
35
  Procfile.dev
36
- Procfile.dev-hmr]
36
+ Procfile.dev-static]
37
+ base_files.each { |file| copy_file("#{base_path}#{file}", file) }
38
+ end
39
+
40
+ def copy_js_bundle_files
41
+ base_path = "base/base/"
42
+ base_files = %w[app/javascript/packs/server-bundle.js
43
+ app/javascript/bundles/HelloWorld/components/HelloWorldServer.js
44
+ app/javascript/bundles/HelloWorld/components/HelloWorld.module.css]
45
+ base_files.each { |file| copy_file("#{base_path}#{file}", file) }
46
+ end
47
+
48
+ def copy_webpack_config
49
+ puts "Adding Webpack config"
50
+ base_path = "base/base"
51
+ base_files = %w[babel.config.js
52
+ config/webpack/clientWebpackConfig.js
53
+ config/webpack/commonWebpackConfig.js
54
+ config/webpack/development.js
55
+ config/webpack/production.js
56
+ config/webpack/serverWebpackConfig.js
57
+ config/webpack/webpackConfig.js]
58
+ config = {
59
+ message: "// The source code including full typescript support is available at:"
60
+ }
61
+ base_files.each do |file|
62
+ template("#{base_path}/#{file}.tt", file, config)
63
+ end
64
+ end
65
+
66
+ def copy_webpacker_config
67
+ puts "Adding Webpacker v6 config"
68
+ base_path = "base/base/"
69
+ base_files = %w[config/webpacker.yml]
37
70
  base_files.each { |file| copy_file("#{base_path}#{file}", file) }
38
71
  end
39
72
 
@@ -51,6 +84,16 @@ module ReactOnRails
51
84
  puts "Adding the lastest react-on-rails NPM module. Double check this is correct in package.json"
52
85
  run "yarn add react-on-rails --exact"
53
86
  end
87
+
88
+ puts "Adding React dependencies"
89
+ run "yarn add react react-dom @babel/preset-react prop-types babel-plugin-transform-react-remove-prop-types \
90
+ babel-plugin-macros"
91
+
92
+ puts "Adding CSS handlers"
93
+ run "yarn add css-loader css-minimizer-webpack-plugin mini-css-extract-plugin style-loader"
94
+
95
+ puts "Adding dev dependencies"
96
+ run "yarn add -D @pmmmwh/react-refresh-webpack-plugin react-refresh"
54
97
  end
55
98
 
56
99
  def append_to_spec_rails_helper
@@ -111,10 +154,10 @@ module ReactOnRails
111
154
  - Alternately, you may turn off compile in config/webpacker.yml and run the foreman
112
155
  command to start the rails server and run webpack in watch mode.
113
156
 
114
- foreman start -f Procfile.dev
157
+ foreman start -f Procfile.dev-static
115
158
 
116
159
  - To turn on HMR, edit config/webpacker.yml and set HMR to true. Restart the rails server
117
- and bin/webpack-dev-server. Or use Procfile.dev-hmr.
160
+ and bin/webpack-dev-server. Or use Procfile.dev.
118
161
 
119
162
  - To server render, change this line app/views/hello_world/index.html.erb to
120
163
  `prerender: true` to see server rendering (right click on page and select "view source").
@@ -132,7 +175,7 @@ module ReactOnRails
132
175
  # From https://github.com/rails/rails/blob/4c940b2dbfb457f67c6250b720f63501d74a45fd/railties/lib/rails/generators/rails/app/app_generator.rb
133
176
  def app_name
134
177
  @app_name ||= (defined_app_const_base? ? defined_app_name : File.basename(destination_root))
135
- .tr('\\', "").tr(". ", "_")
178
+ .tr("\\", "").tr(". ", "_")
136
179
  end
137
180
 
138
181
  def defined_app_name
@@ -52,4 +52,8 @@ module GeneratorHelper
52
52
  empty_directory(parent_directories) unless dest_dir_exists?(parent_directories)
53
53
  copy_file source_file, destination_file
54
54
  end
55
+
56
+ def add_documentation_reference(message, source)
57
+ "#{message} \n#{source}"
58
+ end
55
59
  end
@@ -1,5 +1,7 @@
1
1
  ---
2
- extends: eslint-config-shakacode
2
+ extends:
3
+ - eslint-config-shakacode
4
+ - prettier
3
5
 
4
6
  plugins:
5
7
  - react
@@ -1,9 +1,5 @@
1
+ # Procfile for development using HMR
1
2
  # You can run these commands in separate shells
2
- web: rails s -p 3000
3
-
4
- # Next line runs a watch process with webpack to compile the changed files.
5
- # When making frequent changes to client side assets, you will prefer building webpack assets
6
- # upon saving rather than when you refresh your browser page.
7
- # Note, if using React on Rails localization you will need to run
8
- # `bundle exec rake react_on_rails:locale` before you run bin/webpack
9
- client: sh -c 'rm -rf public/packs/* || true && bin/webpack -w'
3
+ rails: bundle exec rails s -p 3000
4
+ wp-client: HMR=true bin/webpack-dev-server
5
+ wp-server: HMR=true SERVER_BUNDLE_ONLY=yes bin/webpack --watch
@@ -0,0 +1,9 @@
1
+ # You can run these commands in separate shells
2
+ web: rails s -p 3000
3
+
4
+ # Next line runs a watch process with webpack to compile the changed files.
5
+ # When making frequent changes to client side assets, you will prefer building webpack assets
6
+ # upon saving rather than when you refresh your browser page.
7
+ # Note, if using React on Rails localization you will need to run
8
+ # `bundle exec rake react_on_rails:locale` before you run bin/webpack
9
+ webpack: sh -c 'rm -rf public/packs/* || true && bin/webpack -w'
@@ -1,5 +1,6 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React, { useState } from 'react';
3
+ import style from './HelloWorld.module.css';
3
4
 
4
5
  const HelloWorld = (props) => {
5
6
  const [name, setName] = useState(props.name);
@@ -9,7 +10,7 @@ const HelloWorld = (props) => {
9
10
  <h3>Hello, {name}!</h3>
10
11
  <hr />
11
12
  <form>
12
- <label htmlFor="name">
13
+ <label className={style.bright} htmlFor="name">
13
14
  Say hello to:
14
15
  <input id="name" type="text" value={name} onChange={(e) => setName(e.target.value)} />
15
16
  </label>
@@ -0,0 +1,5 @@
1
+ import HelloWorld from './HelloWorld';
2
+ // This could be specialized for server rendering
3
+ // For example, if using React-Router, we'd have the SSR setup here.
4
+
5
+ export default HelloWorld;
@@ -0,0 +1,8 @@
1
+ import ReactOnRails from 'react-on-rails';
2
+
3
+ import HelloWorld from '../bundles/HelloWorld/components/HelloWorldServer';
4
+
5
+ // This is how react_on_rails can see the HelloWorld in the browser.
6
+ ReactOnRails.register({
7
+ HelloWorld,
8
+ });
@@ -4,6 +4,7 @@
4
4
  <title>ReactOnRailsWithWebpacker</title>
5
5
  <%= csrf_meta_tags %>
6
6
  <%= javascript_pack_tag 'hello-world-bundle' %>
7
+ <%= stylesheet_pack_tag 'hello-world-bundle' %>
7
8
  </head>
8
9
 
9
10
  <body>
@@ -0,0 +1,15 @@
1
+ <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/babel.config.js") %>
2
+
3
+ const defaultConfigFunc = require('@rails/webpacker/package/babel/preset.js');
4
+
5
+ module.exports = function (api) {
6
+ const resultConfig = defaultConfigFunc(api);
7
+
8
+ const changesOnDefault = {
9
+ plugins: [process.env.WEBPACK_SERVE && 'react-refresh/babel'].filter(Boolean),
10
+ };
11
+
12
+ resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins];
13
+
14
+ return resultConfig;
15
+ };
@@ -41,5 +41,5 @@ ReactOnRails.configure do |config|
41
41
  # different. You should have ONE server bundle which can create all of your server rendered
42
42
  # React components.
43
43
  #
44
- config.server_bundle_js_file = "hello-world-bundle.js"
44
+ config.server_bundle_js_file = "server-bundle.js"
45
45
  end
@@ -0,0 +1,17 @@
1
+ <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/config/webpack/clientWebpackConfig.js") %>
2
+
3
+ const commonWebpackConfig = require('./commonWebpackConfig');
4
+
5
+ const configureClient = () => {
6
+ const clientConfig = commonWebpackConfig();
7
+
8
+ // server-bundle is special and should ONLY be built by the serverConfig
9
+ // In case this entry is not deleted, a very strange "window" not found
10
+ // error shows referring to window["webpackJsonp"]. That is because the
11
+ // client config is going to try to load chunks.
12
+ delete clientConfig.entry['server-bundle'];
13
+
14
+ return clientConfig;
15
+ };
16
+
17
+ module.exports = configureClient;
@@ -0,0 +1,15 @@
1
+ <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/config/webpack/commonWebpackConfig.js") %>
2
+
3
+ // Common configuration applying to client and server configuration
4
+ const { webpackConfig: baseClientWebpackConfig, merge } = require('@rails/webpacker');
5
+
6
+ const commonOptions = {
7
+ resolve: {
8
+ extensions: ['.css', '.ts', '.tsx'],
9
+ },
10
+ };
11
+
12
+ // Copy the object using merge b/c the baseClientWebpackConfig and commonOptions are mutable globals
13
+ const commonWebpackConfig = () => merge({}, baseClientWebpackConfig, commonOptions);
14
+
15
+ module.exports = commonWebpackConfig;
@@ -0,0 +1,27 @@
1
+ <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/config/webpack/development.js") %>
2
+
3
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
4
+
5
+ const { devServer, inliningCss } = require('@rails/webpacker');
6
+
7
+ const webpackConfig = require('./webpackConfig');
8
+
9
+ const developmentEnvOnly = (clientWebpackConfig, _serverWebpackConfig) => {
10
+ // plugins
11
+ if (inliningCss) {
12
+ // Note, when this is run, we're building the server and client bundles in separate processes.
13
+ // Thus, this plugin is not applied to the server bundle.
14
+
15
+ // eslint-disable-next-line global-require
16
+ const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
17
+ clientWebpackConfig.plugins.push(
18
+ new ReactRefreshWebpackPlugin({
19
+ overlay: {
20
+ sockPort: devServer.port,
21
+ },
22
+ }),
23
+ );
24
+ }
25
+ };
26
+
27
+ module.exports = webpackConfig(developmentEnvOnly);
@@ -0,0 +1,11 @@
1
+ <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/config/webpack/production.js") %>
2
+
3
+ process.env.NODE_ENV = process.env.NODE_ENV || 'production';
4
+
5
+ const webpackConfig = require('./webpackConfig');
6
+
7
+ const productionEnvOnly = (_clientWebpackConfig, _serverWebpackConfig) => {
8
+ // place any code here that is for production only
9
+ };
10
+
11
+ module.exports = webpackConfig(productionEnvOnly);
@@ -0,0 +1,117 @@
1
+ <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/config/webpack/serverWebpackConfig.js") %>
2
+
3
+ const { merge, config } = require('@rails/webpacker');
4
+ const commonWebpackConfig = require('./commonWebpackConfig');
5
+
6
+ const webpack = require('webpack');
7
+
8
+ const configureServer = () => {
9
+ // We need to use "merge" because the clientConfigObject, EVEN after running
10
+ // toWebpackConfig() is a mutable GLOBAL. Thus any changes, like modifying the
11
+ // entry value will result in changing the client config!
12
+ // Using webpack-merge into an empty object avoids this issue.
13
+ const serverWebpackConfig = commonWebpackConfig();
14
+
15
+ // We just want the single server bundle entry
16
+ const serverEntry = {
17
+ 'server-bundle': serverWebpackConfig.entry['server-bundle'],
18
+ };
19
+
20
+ if (!serverEntry['server-bundle']) {
21
+ throw new Error(
22
+ "Create a pack with the file name 'server-bundle.js' containing all the server rendering files",
23
+ );
24
+ }
25
+
26
+ serverWebpackConfig.entry = serverEntry;
27
+
28
+ // Remove the mini-css-extract-plugin from the style loaders because
29
+ // the client build will handle exporting CSS.
30
+ // replace file-loader with null-loader
31
+ serverWebpackConfig.module.rules.forEach((loader) => {
32
+ if (loader.use && loader.use.filter) {
33
+ loader.use = loader.use.filter(
34
+ (item) => !(typeof item === 'string' && item.match(/mini-css-extract-plugin/)),
35
+ );
36
+ }
37
+ });
38
+
39
+ // No splitting of chunks for a server bundle
40
+ serverWebpackConfig.optimization = {
41
+ minimize: false,
42
+ };
43
+ serverWebpackConfig.plugins.unshift(new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }));
44
+
45
+ // Custom output for the server-bundle that matches the config in
46
+ // config/initializers/react_on_rails.rb
47
+ serverWebpackConfig.output = {
48
+ filename: 'server-bundle.js',
49
+ globalObject: 'this',
50
+ // If using the React on Rails Pro node server renderer, uncomment the next line
51
+ // libraryTarget: 'commonjs2',
52
+ path: config.outputPath,
53
+ publicPath: config.publicPath,
54
+ // https://webpack.js.org/configuration/output/#outputglobalobject
55
+ };
56
+
57
+ // Don't hash the server bundle b/c would conflict with the client manifest
58
+ // And no need for the MiniCssExtractPlugin
59
+ serverWebpackConfig.plugins = serverWebpackConfig.plugins.filter(
60
+ (plugin) =>
61
+ plugin.constructor.name !== 'WebpackAssetsManifest' &&
62
+ plugin.constructor.name !== 'MiniCssExtractPlugin' &&
63
+ plugin.constructor.name !== 'ForkTsCheckerWebpackPlugin',
64
+ );
65
+
66
+ // Configure loader rules for SSR
67
+ // Remove the mini-css-extract-plugin from the style loaders because
68
+ // the client build will handle exporting CSS.
69
+ // replace file-loader with null-loader
70
+ const rules = serverWebpackConfig.module.rules;
71
+ rules.forEach((rule) => {
72
+ if (Array.isArray(rule.use)) {
73
+ // remove the mini-css-extract-plugin and style-loader
74
+ rule.use = rule.use.filter((item) => {
75
+ let testValue;
76
+ if (typeof item === 'string') {
77
+ testValue = item;
78
+ } else if (typeof item.loader === 'string') {
79
+ testValue = item.loader;
80
+ }
81
+ return !(testValue.match(/mini-css-extract-plugin/) || testValue === 'style-loader');
82
+ });
83
+ const cssLoader = rule.use.find((item) => {
84
+ let testValue;
85
+
86
+ if (typeof item === 'string') {
87
+ testValue = item;
88
+ } else if (typeof item.loader === 'string') {
89
+ testValue = item.loader;
90
+ }
91
+
92
+ return testValue.includes('css-loader');
93
+ });
94
+ if (cssLoader && cssLoader.options) {
95
+ cssLoader.options.modules = { exportOnlyLocals: true };
96
+ }
97
+
98
+ // Skip writing image files during SSR by setting emitFile to false
99
+ } else if (rule.use && (rule.use.loader === 'url-loader' || rule.use.loader === 'file-loader')) {
100
+ rule.use.options.emitFile = false;
101
+ }
102
+ });
103
+
104
+ // eval works well for the SSR bundle because it's the fastest and shows
105
+ // lines in the server bundle which is good for debugging SSR
106
+ // The default of cheap-module-source-map is slow and provides poor info.
107
+ serverWebpackConfig.devtool = 'eval';
108
+
109
+ // If using the default 'web', then libraries like Emotion and loadable-components
110
+ // break with SSR. The fix is to use a node renderer and change the target.
111
+ // If using the React on Rails Pro node server renderer, uncomment the next line
112
+ // serverWebpackConfig.target = 'node'
113
+
114
+ return serverWebpackConfig;
115
+ };
116
+
117
+ module.exports = configureServer;
@@ -0,0 +1,36 @@
1
+ <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/config/webpack/webpackConfig.js") %>
2
+
3
+ const clientWebpackConfig = require('./clientWebpackConfig');
4
+ const serverWebpackConfig = require('./serverWebpackConfig');
5
+
6
+ const webpackConfig = (envSpecific) => {
7
+ const clientConfig = clientWebpackConfig();
8
+ const serverConfig = serverWebpackConfig();
9
+
10
+ if (envSpecific) {
11
+ envSpecific(clientConfig, serverConfig);
12
+ }
13
+
14
+ let result;
15
+ // For HMR, need to separate the the client and server webpack configurations
16
+ if (process.env.WEBPACK_SERVE || process.env.CLIENT_BUNDLE_ONLY) {
17
+ // eslint-disable-next-line no-console
18
+ console.log('[React on Rails] Creating only the client bundles.');
19
+ result = clientConfig;
20
+ } else if (process.env.SERVER_BUNDLE_ONLY) {
21
+ // eslint-disable-next-line no-console
22
+ console.log('[React on Rails] Creating only the server bundle.');
23
+ result = serverConfig;
24
+ } else {
25
+ // default is the standard client and server build
26
+ // eslint-disable-next-line no-console
27
+ console.log('[React on Rails] Creating both client and server bundles.');
28
+ result = [clientConfig, serverConfig];
29
+ }
30
+
31
+ // To debug, uncomment next line and inspect "result"
32
+ // debugger
33
+ return result;
34
+ };
35
+
36
+ module.exports = webpackConfig;
@@ -0,0 +1,62 @@
1
+ # Note: You must restart bin/webpack-dev-server for changes to take effect
2
+
3
+ default: &default
4
+ source_path: app/javascript
5
+ source_entry_path: packs
6
+ public_root_path: public
7
+ public_output_path: packs
8
+ cache_path: tmp/webpacker
9
+ webpack_compile_output: true
10
+
11
+ # Additional paths webpack should lookup modules
12
+ # ['app/assets', 'engine/foo/app/assets']
13
+ additional_paths: []
14
+
15
+ # Reload manifest.json on all requests so we reload latest compiled packs
16
+ cache_manifest: false
17
+
18
+ development:
19
+ <<: *default
20
+ # This is false since we're running `bin/webpack -w` in Procfile.dev-setic
21
+ compile: false
22
+
23
+ # Reference: https://webpack.js.org/configuration/dev-server/
24
+ dev_server:
25
+ https: false
26
+ host: localhost
27
+ port: 3035
28
+ # Hot Module Replacement updates modules while the application is running without a full reload
29
+ hmr: true
30
+ client:
31
+ # Should we show a full-screen overlay in the browser when there are compiler errors or warnings?
32
+ overlay: true
33
+ # May also be a string
34
+ # webSocketURL:
35
+ # hostname: "0.0.0.0"
36
+ # pathname: "/ws"
37
+ # port: 8080
38
+ compress: true
39
+ # Note that apps that do not check the host are vulnerable to DNS rebinding attacks
40
+ allowed_hosts: [ 'localhost' ]
41
+ pretty: true
42
+ headers:
43
+ 'Access-Control-Allow-Origin': '*'
44
+ static:
45
+ watch:
46
+ ignored: '**/node_modules/**'
47
+
48
+ test:
49
+ <<: *default
50
+ compile: true
51
+
52
+ # Compile test packs to a separate directory
53
+ public_output_path: packs-test
54
+
55
+ production:
56
+ <<: *default
57
+
58
+ # Production depends on precompilation of packs prior to booting for performance.
59
+ compile: false
60
+
61
+ # Cache manifest.json for performance
62
+ cache_manifest: true
@@ -1,5 +1,6 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
+ import style from './HelloWorld.module.css';
3
4
 
4
5
  const HelloWorld = ({ name, updateName }) => (
5
6
  <div>
@@ -9,7 +10,7 @@ const HelloWorld = ({ name, updateName }) => (
9
10
  </h3>
10
11
  <hr />
11
12
  <form>
12
- <label htmlFor="name">
13
+ <label className={style.bright} htmlFor="name">
13
14
  Say hello to:
14
15
  <input id="name" type="text" value={name} onChange={(e) => updateName(e.target.value)} />
15
16
  </label>
@@ -536,6 +536,12 @@ module ReactOnRails
536
536
 
537
537
  controller.is_a?(ActionMailer::Base)
538
538
  end
539
+
540
+ if defined?(ScoutApm)
541
+ include ScoutApm::Tracer
542
+ instrument_method :react_component, type: "ReactOnRails", name: "react_component"
543
+ instrument_method :react_component_hash, type: "ReactOnRails", name: "react_component_hash"
544
+ end
539
545
  end
540
546
  end
541
547
  # rubocop:enable Metrics/ModuleLength
@@ -54,15 +54,13 @@ module ReactOnRails
54
54
  end
55
55
 
56
56
  def locale_files
57
- @locale_files ||= begin
58
- if i18n_yml_dir.present?
59
- Dir["#{i18n_yml_dir}/**/*.yml"]
60
- else
61
- ReactOnRails::Utils.truthy_presence(
62
- Rails.application && Rails.application.config.i18n.load_path
63
- ).presence
64
- end
65
- end
57
+ @locale_files ||= if i18n_yml_dir.present?
58
+ Dir["#{i18n_yml_dir}/**/*.yml"]
59
+ else
60
+ ReactOnRails::Utils.truthy_presence(
61
+ Rails.application && Rails.application.config.i18n.load_path
62
+ ).presence
63
+ end
66
64
  end
67
65
 
68
66
  def i18n_dir
@@ -18,6 +18,19 @@ module ReactOnRails
18
18
  react_component_name: nil,
19
19
  render_options: nil
20
20
  )
21
+
22
+ config_server_bundle_js = ReactOnRails.configuration.server_bundle_js_file
23
+
24
+ if render_options.prerender == true && config_server_bundle_js.blank?
25
+ msg = <<~MSG
26
+ The `prerender` option to allow Server Side Rendering is marked as true but the ReactOnRails configuration
27
+ for `server_bundle_js_file` is nil or not present in `config/initializers/react_on_rails.rb`.
28
+ Set `config.server_bundle_js_file` to your javascript bundle to allow server side rendering.
29
+ Read more at https://www.shakacode.com/react-on-rails/docs/guides/react-server-rendering/
30
+ MSG
31
+ raise ReactOnRails::Error, msg
32
+ end
33
+
21
34
  js_code_renderer.render(props_string, rails_context, redux_stores, react_component_name, render_options)
22
35
  end
23
36
 
@@ -150,6 +150,10 @@ module ReactOnRails
150
150
  end
151
151
 
152
152
  def execjs_timer_polyfills
153
+ if ReactOnRails::Utils.react_on_rails_pro? && ReactOnRailsPro.configuration.include_execjs_polyfills == false
154
+ return ""
155
+ end
156
+
153
157
  <<~JS
154
158
  function getStackTrace () {
155
159
  var stack;
@@ -204,6 +208,11 @@ module ReactOnRails
204
208
  JS
205
209
  end
206
210
 
211
+ if defined?(ScoutApm)
212
+ include ScoutApm::Tracer
213
+ instrument_method :exec_server_render_js, type: "ReactOnRails", name: "ExecJs React Server Rendering"
214
+ end
215
+
207
216
  private
208
217
 
209
218
  def file_url_to_string(url)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactOnRails
4
- VERSION = "12.2.0"
4
+ VERSION = "12.5.0"
5
5
  end
@@ -7,7 +7,9 @@ require "active_support"
7
7
 
8
8
  ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
9
9
 
10
- unless ReactOnRails::WebpackerUtils.webpacker_webpack_production_config_exists?
10
+ skip_react_on_rails_precompile = %w[no false n f].include?(ENV["REACT_ON_RAILS_PRECOMPILE"])
11
+
12
+ if !skip_react_on_rails_precompile && ReactOnRails.configuration.build_production_command.present?
11
13
  # Ensure that rails/webpacker does not call bin/webpack if we're providing
12
14
  # the build command.
13
15
  ENV["WEBPACKER_PRECOMPILE"] = "false"
@@ -38,12 +40,10 @@ end
38
40
  # rubocop:disable Metrics/BlockLength
39
41
  namespace :react_on_rails do
40
42
  namespace :assets do
41
- desc <<-DESC.strip_heredoc
42
- Compile assets with webpack
43
- Uses command defined with ReactOnRails.configuration.build_production_command
44
- sh "#{ReactOnRails::Utils.prepend_cd_node_modules_directory('<ReactOnRails.configuration.build_production_command>')}"
45
- Note: This command is not automatically added to assets:precompile if the rails/webpacker
46
- configuration file config/webpack/production.js exists.
43
+ desc <<~DESC.strip_heredoc
44
+ If config.build_production_command is defined, this command is automatically
45
+ added to task assets:precompile and the regular webpacker compile will not run.
46
+ The defined command is either a script or a module with a method `call`.
47
47
  DESC
48
48
  task webpack: :locale do
49
49
  build_production_command = ReactOnRails.configuration.build_production_command
@@ -61,6 +61,7 @@ namespace :react_on_rails do
61
61
  exit!(1)
62
62
  end
63
63
  else
64
+ # Left in this warning message in case this rake task is run directly
64
65
  msg = <<~MSG
65
66
  React on Rails is aborting webpack compilation from task react_on_rails:assets:webpack
66
67
  because you do not have the `config.build_production_command` defined.
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-on-rails",
3
- "version": "12.2.0",
3
+ "version": "12.5.0",
4
4
  "description": "react-on-rails JavaScript for react_on_rails Ruby gem",
5
5
  "main": "node_package/lib/ReactOnRails.js",
6
6
  "directories": {