react_on_rails 12.4.0 → 12.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +2 -1
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.github/workflows/main.yml +3 -3
  6. data/.gitignore +0 -3
  7. data/.prettierignore +2 -0
  8. data/CHANGELOG.md +32 -2
  9. data/Gemfile.development_dependencies +7 -6
  10. data/REACT-ON-RAILS-PRO-LICENSE +1 -1
  11. data/README.md +22 -12
  12. data/SUMMARY.md +9 -0
  13. data/docs/deployment/heroku-deployment.md +16 -5
  14. data/docs/guides/configuration.md +26 -12
  15. data/docs/guides/how-react-on-rails-works.md +0 -1
  16. data/docs/guides/tutorial.md +18 -14
  17. data/lib/generators/react_on_rails/base_generator.rb +46 -3
  18. data/lib/generators/react_on_rails/generator_helper.rb +4 -0
  19. data/lib/generators/react_on_rails/templates/.eslintrc +3 -1
  20. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +4 -8
  21. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static +9 -0
  22. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
  23. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +4 -0
  24. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js +5 -0
  25. data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js +8 -0
  26. data/lib/generators/react_on_rails/templates/base/base/app/views/layouts/hello_world.html.erb +1 -0
  27. data/lib/generators/react_on_rails/templates/base/base/babel.config.js.tt +15 -0
  28. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +1 -1
  29. data/lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt +17 -0
  30. data/lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt +15 -0
  31. data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +27 -0
  32. data/lib/generators/react_on_rails/templates/base/base/config/webpack/production.js.tt +11 -0
  33. data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +117 -0
  34. data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpackConfig.js.tt +36 -0
  35. data/lib/generators/react_on_rails/templates/base/base/config/webpacker.yml +62 -0
  36. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
  37. data/lib/react_on_rails/configuration.rb +70 -35
  38. data/lib/react_on_rails/helper.rb +1 -1
  39. data/lib/react_on_rails/react_component/render_options.rb +14 -0
  40. data/lib/react_on_rails/server_rendering_js_code.rb +13 -0
  41. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +3 -1
  42. data/lib/react_on_rails/version.rb +1 -1
  43. data/lib/tasks/assets.rake +5 -47
  44. data/lib/tasks/locale.rake +1 -2
  45. data/package.json +1 -1
  46. data/rakelib/example_type.rb +5 -1
  47. data/rakelib/examples.rake +8 -3
  48. data/rakelib/release.rake +7 -1
  49. data/rakelib/task_helpers.rb +7 -0
  50. data/react_on_rails.gemspec +3 -3
  51. data/yarn.lock +117 -71
  52. metadata +22 -9
  53. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-hmr +0 -26
@@ -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>
@@ -32,6 +32,7 @@ module ReactOnRails
32
32
  # skip_display_none is deprecated
33
33
  webpack_generated_files: %w[manifest.json],
34
34
  rendering_extension: nil,
35
+ rendering_props_extension: nil,
35
36
  server_render_method: nil,
36
37
  build_test_command: "",
37
38
  build_production_command: "",
@@ -51,7 +52,7 @@ module ReactOnRails
51
52
  :build_production_command,
52
53
  :i18n_dir, :i18n_yml_dir, :i18n_output_format,
53
54
  :server_render_method, :random_dom_id,
54
- :same_bundle_for_client_and_server
55
+ :same_bundle_for_client_and_server, :rendering_props_extension
55
56
 
56
57
  # rubocop:disable Metrics/AbcSize
57
58
  def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
@@ -65,7 +66,7 @@ module ReactOnRails
65
66
  build_production_command: nil,
66
67
  same_bundle_for_client_and_server: nil,
67
68
  i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil,
68
- random_dom_id: nil, server_render_method: nil)
69
+ random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil)
69
70
  self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
70
71
  self.generated_assets_dirs = generated_assets_dirs
71
72
  self.generated_assets_dir = generated_assets_dir
@@ -87,6 +88,7 @@ module ReactOnRails
87
88
  self.trace = trace.nil? ? Rails.env.development? : trace
88
89
  self.raise_on_prerender_error = raise_on_prerender_error
89
90
  self.skip_display_none = skip_display_none
91
+ self.rendering_props_extension = rendering_props_extension
90
92
 
91
93
  # Server rendering:
92
94
  self.server_bundle_js_file = server_bundle_js_file
@@ -111,46 +113,79 @@ module ReactOnRails
111
113
  check_i18n_yml_directory_exists
112
114
  check_server_render_method_is_only_execjs
113
115
  error_if_using_webpacker_and_generated_assets_dir_not_match_public_output_path
114
- check_deprecated_settings
116
+ # check_deprecated_settings
117
+ adjust_precompile_task
115
118
  end
116
119
 
117
120
  private
118
121
 
119
- def check_deprecated_settings
120
- if build_production_command.present? &&
121
- ReactOnRails::WebpackerUtils.webpacker_webpack_production_config_exists?
122
- msg = <<~MSG
123
- Setting ReactOnRails configuration for `build_production_command` is
124
- not necessary if you have config/webpack/production.js. When that file
125
- exists, React on Rails DOES NOT modify the standard assets:precompile.
126
- If you want React on Rails to modify to the standard assets:precompile
127
- to use your config/initializers/react_on_rails.rb config.build_production_command
128
- then delete the config/webpack/production.js.
129
- MSG
130
- Rails.logger.warn(msg)
122
+ def adjust_precompile_task
123
+ skip_react_on_rails_precompile = %w[no false n f].include?(ENV["REACT_ON_RAILS_PRECOMPILE"])
124
+
125
+ return if skip_react_on_rails_precompile || build_production_command.blank?
126
+
127
+ # Ensure that rails/webpacker does not call bin/webpack if we're providing
128
+ # the build command.
129
+ ENV["WEBPACKER_PRECOMPILE"] = "false"
130
+
131
+ precompile_tasks = lambda {
132
+ Rake::Task["react_on_rails:assets:webpack"].invoke
133
+ puts "Invoking task webpacker:clean from React on Rails"
134
+
135
+ # VERSIONS is per the rails/webpacker clean method definition.
136
+ # We set it very big so that it is not used, and then clean just
137
+ # removes files older than 1 hour.
138
+ versions = 100_000
139
+ Rake::Task["webpacker:clean"].invoke(versions)
140
+ }
141
+
142
+ if Rake::Task.task_defined?("assets:precompile")
143
+ Rake::Task["assets:precompile"].enhance do
144
+ precompile_tasks.call
145
+ end
146
+ else
147
+ Rake::Task.define_task("assets:precompile") do
148
+ precompile_tasks.call
149
+ end
131
150
  end
132
- #
133
- # msg = <<~MSG
134
- # ReactOnRails configuration for `build_production_command` is removed.
135
- # Move this command into `bin/webpack` converting the script to a shell script.
136
- # MSG
137
- # raise ReactOnRails::Error, msg
138
- # Commenting out until v13 when
139
- # https://github.com/rails/webpacker/issues/2640 gets resolved
140
- # if node_modules_location.present?
141
- # Rails.logger.warn("ReactOnRails configuration for `node_modules_location` is deprecated. "\
142
- # "Instead, prepend a `cd client` (or whichever location) before your test command.")
143
- # end
144
- #
145
- # return unless build_production_command.present?
146
- #
147
- # msg = <<~MSG
148
- # ReactOnRails configuration for `build_production_command` is removed.
149
- # Move this command into `bin/webpack` converting the script to a shell script.
150
- # MSG
151
- # raise ReactOnRails::Error, msg
152
151
  end
153
152
 
153
+ # Pending updates to rails/webpacker v6, we may have some message that prints after configuration runs.
154
+ # def check_deprecated_settings
155
+ # if build_production_command.present? &&
156
+ # ReactOnRails::WebpackerUtils.webpacker_webpack_production_config_exists?
157
+ # msg = <<~MSG
158
+ # Setting ReactOnRails configuration for `build_production_command` is
159
+ # not necessary if you have config/webpack/production.js. When that file
160
+ # exists, React on Rails DOES NOT modify the standard assets:precompile.
161
+ # If you want React on Rails to modify to the standard assets:precompile
162
+ # to use your config/initializers/react_on_rails.rb config.build_production_command
163
+ # then delete the config/webpack/production.js.
164
+ # MSG
165
+ # Rails.logger.warn(msg)
166
+ # end
167
+ #
168
+ # msg = <<~MSG
169
+ # ReactOnRails configuration for `build_production_command` is removed.
170
+ # Move this command into `bin/webpack` converting the script to a shell script.
171
+ # MSG
172
+ # raise ReactOnRails::Error, msg
173
+ # Commenting out until v13 when
174
+ # https://github.com/rails/webpacker/issues/2640 gets resolved
175
+ # if node_modules_location.present?
176
+ # Rails.logger.warn("ReactOnRails configuration for `node_modules_location` is deprecated. "\
177
+ # "Instead, prepend a `cd client` (or whichever location) before your test command.")
178
+ # end
179
+ #
180
+ # return unless build_production_command.present?
181
+ #
182
+ # msg = <<~MSG
183
+ # ReactOnRails configuration for `build_production_command` is removed.
184
+ # Move this command into `bin/webpack` converting the script to a shell script.
185
+ # MSG
186
+ # raise ReactOnRails::Error, msg
187
+ # end
188
+
154
189
  def error_if_using_webpacker_and_generated_assets_dir_not_match_public_output_path
155
190
  return unless ReactOnRails::WebpackerUtils.using_webpacker?
156
191
 
@@ -413,7 +413,7 @@ module ReactOnRails
413
413
  # Setup the page_loaded_js, which is the same regardless of prerendering or not!
414
414
  # The reason is that React is smart about not doing extra work if the server rendering did its job.
415
415
  component_specification_tag = content_tag(:script,
416
- json_safe_and_pretty(render_options.props).html_safe,
416
+ json_safe_and_pretty(render_options.client_props).html_safe,
417
417
  type: "application/json",
418
418
  class: "js-react-on-rails-component",
419
419
  "data-component-name" => render_options.react_component_name,
@@ -27,6 +27,20 @@ module ReactOnRails
27
27
  options.fetch(:props) { NO_PROPS }
28
28
  end
29
29
 
30
+ def client_props
31
+ props_extension = ReactOnRails.configuration.rendering_props_extension
32
+ if props_extension.present?
33
+ if props_extension.respond_to?(:adjust_props_for_client_side_hydration)
34
+ return props_extension.adjust_props_for_client_side_hydration(react_component_name,
35
+ props.clone)
36
+ end
37
+
38
+ raise ReactOnRails::Error, "ReactOnRails: your rendering_props_extension module is missing the "\
39
+ "required adjust_props_for_client_side_hydration method & can not be used"
40
+ end
41
+ props
42
+ end
43
+
30
44
  def random_dom_id
31
45
  retrieve_configuration_value_for(:random_dom_id)
32
46
  end
@@ -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,7 +150,9 @@ 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
153
+ if ReactOnRails::Utils.react_on_rails_pro? &&
154
+ ReactOnRailsPro.configuration.respond_to?(:include_execjs_polyfills) &&
155
+ ReactOnRailsPro.configuration.include_execjs_polyfills == false
154
156
  return ""
155
157
  end
156
158
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactOnRails
4
- VERSION = "12.4.0"
4
+ VERSION = "12.6.0"
5
5
  end