react_on_rails 12.0.1 → 13.0.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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +27 -13
  3. data/.eslintrc +2 -1
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.github/workflows/lint-js-and-ruby.yml +53 -0
  7. data/.github/workflows/main.yml +178 -0
  8. data/.github/workflows/package-js-tests.yml +35 -0
  9. data/.github/workflows/rspec-package-specs.yml +45 -0
  10. data/.gitignore +0 -3
  11. data/.prettierignore +2 -0
  12. data/.prettierrc +0 -3
  13. data/.rubocop.yml +48 -39
  14. data/.travis.yml +3 -1
  15. data/CHANGELOG.md +112 -25
  16. data/CONTRIBUTING.md +4 -3
  17. data/Gemfile +1 -33
  18. data/Gemfile.development_dependencies +52 -0
  19. data/NEWS.md +14 -4
  20. data/REACT-ON-RAILS-PRO-LICENSE +1 -1
  21. data/README.md +42 -324
  22. data/Rakefile +1 -1
  23. data/SUMMARY.md +22 -13
  24. data/docs/{basics → additional-details}/generator-details.md +1 -6
  25. data/docs/{outdated → additional-details}/manual-installation-overview.md +6 -6
  26. data/docs/additional-details/recommended-project-structure.md +69 -0
  27. data/docs/additional-details/upgrade-webpacker-v3-to-v4.md +10 -0
  28. data/docs/api/javascript-api.md +2 -2
  29. data/docs/api/redux-store-api.md +3 -3
  30. data/docs/api/view-helpers-api.md +7 -8
  31. data/docs/contributor-info/linters.md +5 -6
  32. data/docs/contributor-info/pull-requests.md +2 -4
  33. data/docs/contributor-info/releasing.md +1 -1
  34. data/docs/{basics → deployment}/heroku-deployment.md +16 -5
  35. data/docs/{basics → guides}/client-vs-server-rendering.md +4 -2
  36. data/docs/{basics → guides}/configuration.md +65 -31
  37. data/docs/guides/deployment.md +4 -0
  38. data/docs/guides/getting-started.md +183 -0
  39. data/docs/guides/hmr-and-hot-reloading-with-the-webpack-dev-server.md +104 -0
  40. data/docs/{outdated → guides}/how-react-on-rails-works.md +10 -10
  41. data/docs/guides/how-to-conditionally-server-render-based-on-device-type.md +39 -0
  42. data/docs/guides/how-to-use-different-files-for-client-and-server-rendering.md +98 -0
  43. data/docs/{basics → guides}/installation-into-an-existing-rails-app.md +14 -7
  44. data/docs/guides/rails-webpacker-react-integration-options.md +182 -0
  45. data/docs/guides/react-on-rails-overview.md +30 -0
  46. data/docs/{basics → guides}/react-server-rendering.md +8 -5
  47. data/docs/{basics → guides}/rspec-configuration.md +11 -11
  48. data/docs/{tutorial.md → guides/tutorial.md} +46 -50
  49. data/docs/{basics → guides}/upgrading-react-on-rails.md +56 -18
  50. data/docs/guides/webpack-configuration.md +42 -0
  51. data/docs/home.md +23 -0
  52. data/docs/{outdated → javascript}/code-splitting.md +5 -5
  53. data/docs/{additional-reading → javascript}/converting-from-custom-webpack-config-to-rails-webpacker-config.md +4 -4
  54. data/docs/{additional-reading → javascript}/images.md +5 -6
  55. data/docs/{articles.md → misc/articles.md} +1 -1
  56. data/docs/misc/doctrine.md +5 -6
  57. data/docs/outdated/deferred-rendering.md +39 -0
  58. data/docs/outdated/rails-assets-relative-paths.md +3 -3
  59. data/docs/outdated/rails-assets.md +8 -8
  60. data/docs/outdated/rails3.md +2 -2
  61. data/docs/{additional-reading → rails}/convert-rails-5-api-only-app.md +1 -1
  62. data/docs/{additional-reading → rails}/rails-engine-integration.md +3 -12
  63. data/docs/{additional-reading → rails}/turbolinks.md +13 -1
  64. data/docs/react-on-rails-pro/react-on-rails-pro.md +43 -0
  65. data/docs/testimonials/testimonials.md +6 -6
  66. data/lib/generators/react_on_rails/base_generator.rb +64 -12
  67. data/lib/generators/react_on_rails/dev_tests_generator.rb +1 -1
  68. data/lib/generators/react_on_rails/generator_helper.rb +4 -0
  69. data/lib/generators/react_on_rails/templates/.eslintrc +3 -1
  70. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +4 -8
  71. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static +9 -0
  72. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
  73. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +4 -0
  74. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js +5 -0
  75. data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js +8 -0
  76. data/lib/generators/react_on_rails/templates/base/base/app/views/layouts/hello_world.html.erb +1 -0
  77. data/lib/generators/react_on_rails/templates/base/base/babel.config.js.tt +32 -0
  78. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +3 -3
  79. data/lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt +17 -0
  80. data/lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt +15 -0
  81. data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +25 -0
  82. data/lib/generators/react_on_rails/templates/base/base/config/webpack/production.js.tt +9 -0
  83. data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +117 -0
  84. data/lib/generators/react_on_rails/templates/base/base/config/webpack/test.js.tt +6 -0
  85. data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpack.config.js.tt +15 -0
  86. data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpackConfig.js.tt +36 -0
  87. data/lib/generators/react_on_rails/templates/base/base/config/webpacker.yml +62 -0
  88. data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +8 -2
  89. data/lib/generators/react_on_rails/templates/dev_tests/spec/simplecov_helper.rb +1 -1
  90. data/lib/generators/react_on_rails/templates/dev_tests/spec/{features → system}/hello_world_spec.rb +2 -2
  91. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +2 -1
  92. data/lib/react_on_rails/configuration.rb +42 -41
  93. data/lib/react_on_rails/git_utils.rb +3 -3
  94. data/lib/react_on_rails/helper.rb +54 -28
  95. data/lib/react_on_rails/json_parse_error.rb +1 -1
  96. data/lib/react_on_rails/locales/base.rb +11 -15
  97. data/lib/react_on_rails/locales/to_js.rb +0 -4
  98. data/lib/react_on_rails/locales/to_json.rb +0 -4
  99. data/lib/react_on_rails/prerender_error.rb +6 -3
  100. data/lib/react_on_rails/react_component/render_options.rb +30 -7
  101. data/lib/react_on_rails/server_rendering_js_code.rb +13 -0
  102. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +41 -13
  103. data/lib/react_on_rails/test_helper/webpack_assets_compiler.rb +1 -1
  104. data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +3 -3
  105. data/lib/react_on_rails/test_helper.rb +4 -2
  106. data/lib/react_on_rails/utils.rb +24 -4
  107. data/lib/react_on_rails/version.rb +1 -1
  108. data/lib/react_on_rails/webpacker_utils.rb +9 -10
  109. data/lib/tasks/assets.rake +19 -50
  110. data/lib/tasks/locale.rake +1 -2
  111. data/package.json +24 -29
  112. data/rakelib/docker.rake +0 -5
  113. data/rakelib/example_type.rb +10 -3
  114. data/rakelib/examples.rake +3 -5
  115. data/rakelib/lint.rake +3 -9
  116. data/rakelib/release.rake +35 -15
  117. data/rakelib/run_rspec.rake +10 -11
  118. data/rakelib/task_helpers.rb +16 -4
  119. data/react_on_rails.gemspec +5 -20
  120. data/yarn.lock +2616 -5190
  121. metadata +86 -256
  122. data/.release-it.json +0 -3
  123. data/docs/additional-reading/upgrade-webpacker-v3-to-v4.md +0 -10
  124. data/docs/additional-reading/webpack-dev-server.md +0 -15
  125. data/docs/basics/deployment.md +0 -4
  126. data/docs/basics/hmr-and-hot-reloading-with-the-webpack-dev-server.md +0 -49
  127. data/docs/basics/recommended-project-structure.md +0 -77
  128. data/docs/basics/webpack-configuration.md +0 -50
  129. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-hmr +0 -26
  130. data/ruby-lint.yml +0 -25
  131. /data/docs/{basics → additional-details}/migrating-from-react-rails.md +0 -0
  132. /data/docs/{additional-reading → additional-details}/updating-dependencies.md +0 -0
  133. /data/docs/{additional-reading → deployment}/elastic-beanstalk.md +0 -0
  134. /data/docs/{basics → guides}/i18n.md +0 -0
  135. /data/docs/{basics → guides}/minitest-configuration.md +0 -0
  136. /data/docs/{basics → guides}/render-functions-and-railscontext.md +0 -0
  137. /data/docs/{additional-reading → javascript}/angular-js-integration-migration.md +0 -0
  138. /data/docs/{additional-reading → javascript}/asset-pipeline.md +0 -0
  139. /data/docs/{additional-reading → javascript}/capistrano-deployment.md +0 -0
  140. /data/docs/{additional-reading → javascript}/credits.md +0 -0
  141. /data/docs/{additional-reading → javascript}/foreman-issues.md +0 -0
  142. /data/docs/{additional-reading → javascript}/node-dependencies-and-npm.md +0 -0
  143. /data/docs/{additional-reading → javascript}/react-and-redux.md +0 -0
  144. /data/docs/{additional-reading → javascript}/react-helmet.md +0 -0
  145. /data/docs/{additional-reading → javascript}/react-router.md +0 -0
  146. /data/docs/{additional-reading → javascript}/server-rendering-tips.md +0 -0
  147. /data/docs/{additional-reading → javascript}/troubleshooting-when-using-webpacker.md +0 -0
  148. /data/docs/{additional-reading → javascript}/webpack-v1-notes.md +0 -0
  149. /data/docs/{additional-reading → javascript}/webpack.md +0 -0
  150. /data/docs/{coding-style → misc}/style.md +0 -0
  151. /data/docs/{additional-reading → misc}/tips.md +0 -0
  152. /data/docs/{additional-reading → rails}/rails_view_rendering_from_inline_javascript.md +0 -0
@@ -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/webpacker
9
+ webpack: sh -c 'rm -rf public/packs/* || true && bin/webpacker -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,32 @@
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
+ module.exports = function (api) {
4
+ const defaultConfigFunc = require('shakapacker/package/babel/preset.js')
5
+ const resultConfig = defaultConfigFunc(api)
6
+ const isProductionEnv = api.env('production')
7
+
8
+ const changesOnDefault = {
9
+ presets: [
10
+ [
11
+ '@babel/preset-react',
12
+ {
13
+ development: !isProductionEnv,
14
+ useBuiltIns: true
15
+ }
16
+ ]
17
+ ].filter(Boolean),
18
+ plugins: [
19
+ process.env.WEBPACK_SERVE && 'react-refresh/babel',
20
+ isProductionEnv && ['babel-plugin-transform-react-remove-prop-types',
21
+ {
22
+ removeImport: true
23
+ }
24
+ ]
25
+ ].filter(Boolean),
26
+ }
27
+
28
+ resultConfig.presets = [...resultConfig.presets, ...changesOnDefault.presets]
29
+ resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins ]
30
+
31
+ return resultConfig
32
+ }
@@ -6,7 +6,7 @@
6
6
  ReactOnRails.configure do |config|
7
7
  # This configures the script to run to build the production assets by webpack. Set this to nil
8
8
  # if you don't want react_on_rails building this file for you.
9
- # If nil, then the standard rails/webpacker assets:precompile will run
9
+ # If nil, then the standard shakacode/shakapacker assets:precompile will run
10
10
  # config.build_production_command = nil
11
11
 
12
12
  ################################################################################
@@ -25,7 +25,7 @@ ReactOnRails.configure do |config|
25
25
  #
26
26
  # Alternately, you can remove the `ReactOnRails::TestHelper.configure_rspec_to_compile_assets`
27
27
  # and set the config/webpacker.yml option for test to true.
28
- config.build_test_command = "RAILS_ENV=test bin/webpack"
28
+ config.build_test_command = "RAILS_ENV=test bin/webpacker"
29
29
 
30
30
  ################################################################################
31
31
  ################################################################################
@@ -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('shakapacker');
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,25 @@
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
+ const { devServer, inliningCss } = require('shakapacker');
4
+
5
+ const webpackConfig = require('./webpackConfig');
6
+
7
+ const developmentEnvOnly = (clientWebpackConfig, _serverWebpackConfig) => {
8
+ // plugins
9
+ if (inliningCss) {
10
+ // Note, when this is run, we're building the server and client bundles in separate processes.
11
+ // Thus, this plugin is not applied to the server bundle.
12
+
13
+ // eslint-disable-next-line global-require
14
+ const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
15
+ clientWebpackConfig.plugins.push(
16
+ new ReactRefreshWebpackPlugin({
17
+ overlay: {
18
+ sockPort: devServer.port,
19
+ },
20
+ }),
21
+ );
22
+ }
23
+ };
24
+
25
+ module.exports = webpackConfig(developmentEnvOnly);
@@ -0,0 +1,9 @@
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
+ const webpackConfig = require('./webpackConfig');
4
+
5
+ const productionEnvOnly = (_clientWebpackConfig, _serverWebpackConfig) => {
6
+ // place any code here that is for production only
7
+ };
8
+
9
+ 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('shakapacker');
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,6 @@
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
+ // Use dev
4
+ const config = require('./development');
5
+
6
+ module.exports = config;
@@ -0,0 +1,15 @@
1
+ const { env } = require('shakapacker')
2
+ const { existsSync } = require('fs')
3
+ const { resolve } = require('path')
4
+
5
+ const envSpecificConfig = () => {
6
+ const path = resolve(__dirname, `${env.nodeEnv}.js`)
7
+ if (existsSync(path)) {
8
+ console.log(`Loading ENV specific webpack configuration file ${path}`)
9
+ return require(path)
10
+ } else {
11
+ throw new Error(`Could not find file to load ${path}, based on NODE_ENV`)
12
+ }
13
+ }
14
+
15
+ module.exports = envSpecificConfig()
@@ -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/webpacker-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/webpacker -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
@@ -13,9 +13,11 @@ require_relative "spec_helper"
13
13
  require "rspec/rails"
14
14
  require "capybara/rspec"
15
15
  require "capybara/rails"
16
- Capybara.javascript_driver = :selenium_chrome
17
16
  Capybara.register_driver :selenium_chrome do |app|
18
- Capybara::Selenium::Driver.new(app, browser: :chrome)
17
+ options = Selenium::WebDriver::Chrome::Options.new
18
+ options.add_argument("--headless")
19
+ options.add_argument("--disable-gpu")
20
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
19
21
  end
20
22
 
21
23
  # Requires supporting ruby files with custom matchers and macros, etc, in
@@ -38,6 +40,10 @@ end
38
40
  # ActiveRecord::Migration.maintain_test_schema!
39
41
 
40
42
  RSpec.configure do |config|
43
+ config.before(:each, type: :system, js: true) do
44
+ driven_by :selenium_chrome
45
+ end
46
+
41
47
  # Ensure that if we are running js tests, we are using latest webpack assets
42
48
  # This will use the defaults of :js and :server_rendering meta tags
43
49
  ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
@@ -17,7 +17,7 @@ if ENV["COVERAGE"] == "true"
17
17
 
18
18
  # Don't report anything that has "spec" in the path
19
19
  add_filter do |src|
20
- src.filename =~ %r{\/spec\/}
20
+ src.filename.include?("/spec/")
21
21
  end
22
22
  end
23
23
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  require_relative "../rails_helper"
4
4
 
5
- feature "Hello World", js: true do
6
- scenario "the hello world example works" do
5
+ describe "Hello World", js: true do
6
+ it "the hello world example works" do
7
7
  visit "/hello_world"
8
8
  expect(heading).to have_text("Hello World")
9
9
  expect(message).to have_text("Stranger")
@@ -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,8 +52,9 @@ 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
 
57
+ # rubocop:disable Metrics/AbcSize
56
58
  def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
57
59
  replay_console: nil,
58
60
  trace: nil, development_mode: nil,
@@ -64,7 +66,7 @@ module ReactOnRails
64
66
  build_production_command: nil,
65
67
  same_bundle_for_client_and_server: nil,
66
68
  i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil,
67
- random_dom_id: nil, server_render_method: nil)
69
+ random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil)
68
70
  self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
69
71
  self.generated_assets_dirs = generated_assets_dirs
70
72
  self.generated_assets_dir = generated_assets_dir
@@ -86,6 +88,7 @@ module ReactOnRails
86
88
  self.trace = trace.nil? ? Rails.env.development? : trace
87
89
  self.raise_on_prerender_error = raise_on_prerender_error
88
90
  self.skip_display_none = skip_display_none
91
+ self.rendering_props_extension = rendering_props_extension
89
92
 
90
93
  # Server rendering:
91
94
  self.server_bundle_js_file = server_bundle_js_file
@@ -98,6 +101,7 @@ module ReactOnRails
98
101
 
99
102
  self.server_render_method = server_render_method
100
103
  end
104
+ # rubocop:enable Metrics/AbcSize
101
105
 
102
106
  # on ReactOnRails
103
107
  def setup_config_values
@@ -109,44 +113,41 @@ module ReactOnRails
109
113
  check_i18n_yml_directory_exists
110
114
  check_server_render_method_is_only_execjs
111
115
  error_if_using_webpacker_and_generated_assets_dir_not_match_public_output_path
112
- check_deprecated_settings
116
+ # check_deprecated_settings
117
+ adjust_precompile_task
113
118
  end
114
119
 
115
120
  private
116
121
 
117
- def check_deprecated_settings
118
- if build_production_command.present? &&
119
- ReactOnRails::WebpackerUtils.webpacker_webpack_production_config_exists?
120
- msg = <<~MSG
121
- Setting ReactOnRails configuration for `build_production_command` is
122
- not necessary if you have config/webpack/production.js. When that file
123
- exists, React on Rails DOES NOT modify the standard assets:precompile.
124
- If you want React on Rails to modify to the standard assets:precompile
125
- to use your config/initializers/react_on_rails.rb config.build_production_command
126
- then delete the config/webpack/production.js.
127
- MSG
128
- 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 shakacode/shakapacker does not call bin/webpacker 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 shakacode/shakapacker 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
129
150
  end
130
- #
131
- # msg = <<~MSG
132
- # ReactOnRails configuration for `build_production_command` is removed.
133
- # Move this command into `bin/webpack` converting the script to a shell script.
134
- # MSG
135
- # raise ReactOnRails::Error, msg
136
- # Commenting out until v13 when
137
- # https://github.com/rails/webpacker/issues/2640 gets resolved
138
- # if node_modules_location.present?
139
- # Rails.logger.warn("ReactOnRails configuration for `node_modules_location` is deprecated. "\
140
- # "Instead, prepend a `cd client` (or whichever location) before your test command.")
141
- # end
142
- #
143
- # return unless build_production_command.present?
144
- #
145
- # msg = <<~MSG
146
- # ReactOnRails configuration for `build_production_command` is removed.
147
- # Move this command into `bin/webpack` converting the script to a shell script.
148
- # MSG
149
- # raise ReactOnRails::Error, msg
150
151
  end
151
152
 
152
153
  def error_if_using_webpacker_and_generated_assets_dir_not_match_public_output_path
@@ -158,7 +159,7 @@ module ReactOnRails
158
159
 
159
160
  if File.expand_path(generated_assets_dir) == webpacker_public_output_path.to_s
160
161
  Rails.logger.warn("You specified generated_assets_dir in `config/initializers/react_on_rails.rb` "\
161
- "with Webpacker. Remove this line from your configuration file.")
162
+ "with Webpacker. Remove this line from your configuration file.")
162
163
  else
163
164
  msg = <<~MSG
164
165
  Error configuring /config/initializers/react_on_rails.rb: You are using webpacker
@@ -220,19 +221,19 @@ module ReactOnRails
220
221
  if ReactOnRails::WebpackerUtils.using_webpacker?
221
222
  webpacker_public_output_path = ReactOnRails::WebpackerUtils.webpacker_public_output_path
222
223
  Rails.logger.warn "Error configuring config/initializers/react_on_rails. Define neither the "\
223
- "generated_assets_dirs no the generated_assets_dir when using Webpacker. This is defined by "\
224
- "public_output_path specified in webpacker.yml = #{webpacker_public_output_path}."
224
+ "generated_assets_dirs no the generated_assets_dir when using Webpacker. This is defined by "\
225
+ "public_output_path specified in webpacker.yml = #{webpacker_public_output_path}."
225
226
  return
226
227
  end
227
228
 
228
229
  Rails.logger.warn "[DEPRECATION] ReactOnRails: Use config.generated_assets_dir rather than "\
229
- "generated_assets_dirs"
230
+ "generated_assets_dirs"
230
231
  if generated_assets_dir.blank?
231
232
  self.generated_assets_dir = generated_assets_dirs
232
233
  else
233
234
  Rails.logger.warn "[DEPRECATION] ReactOnRails. You have both generated_assets_dirs and "\
234
- "generated_assets_dir defined. Define ONLY generated_assets_dir if NOT using Webpacker"\
235
- " and define neither if using Webpacker"
235
+ "generated_assets_dir defined. Define ONLY generated_assets_dir if NOT using Webpacker"\
236
+ " and define neither if using Webpacker"
236
237
  end
237
238
  end
238
239