react_on_rails 11.0.5 → 13.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +338 -0
  3. data/.eslintignore +2 -1
  4. data/.eslintrc +32 -3
  5. data/.github/FUNDING.yml +1 -0
  6. data/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
  7. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  8. data/.github/PULL_REQUEST_TEMPLATE.md +19 -0
  9. data/.github/workflows/lint-js-and-ruby.yml +54 -0
  10. data/.github/workflows/main.yml +183 -0
  11. data/.github/workflows/package-js-tests.yml +35 -0
  12. data/.github/workflows/rspec-package-specs.yml +46 -0
  13. data/.gitignore +3 -4
  14. data/.prettierignore +14 -0
  15. data/.prettierrc +20 -0
  16. data/.rubocop.yml +76 -34
  17. data/.travis.yml +15 -22
  18. data/CHANGELOG.md +443 -55
  19. data/CONTRIBUTING.md +62 -80
  20. data/Gemfile +1 -35
  21. data/Gemfile.development_dependencies +50 -0
  22. data/KUDOS.md +4 -1
  23. data/{docs/LICENSE.md → LICENSE.md} +1 -1
  24. data/NEWS.md +14 -4
  25. data/REACT-ON-RAILS-PRO-LICENSE +95 -0
  26. data/README.md +107 -802
  27. data/Rakefile +1 -8
  28. data/SUMMARY.md +51 -29
  29. data/book.json +5 -5
  30. data/docs/{basics/generator.md → additional-details/generator-details.md} +5 -13
  31. data/docs/{basics/installation-overview.md → additional-details/manual-installation-overview.md} +9 -14
  32. data/docs/{basics → additional-details}/migrating-from-react-rails.md +1 -1
  33. data/docs/additional-details/recommended-project-structure.md +69 -0
  34. data/docs/additional-details/tips-for-usage-with-sp6.md +15 -0
  35. data/docs/additional-details/upgrade-webpacker-v3-to-v4.md +10 -0
  36. data/docs/api/javascript-api.md +35 -6
  37. data/docs/api/redux-store-api.md +102 -0
  38. data/docs/api/view-helpers-api.md +133 -0
  39. data/docs/contributor-info/errors-with-hooks.md +45 -0
  40. data/docs/contributor-info/linters.md +5 -6
  41. data/docs/contributor-info/pull-requests.md +42 -0
  42. data/docs/contributor-info/releasing.md +1 -1
  43. data/docs/deployment/heroku-deployment.md +39 -0
  44. data/docs/getting-started.md +196 -0
  45. data/docs/guides/client-vs-server-rendering.md +27 -0
  46. data/docs/guides/configuration.md +289 -0
  47. data/docs/guides/deployment.md +5 -0
  48. data/docs/guides/file-system-based-automated-bundle-generation.md +197 -0
  49. data/docs/guides/hmr-and-hot-reloading-with-the-webpack-dev-server.md +104 -0
  50. data/docs/guides/how-react-on-rails-works.md +44 -0
  51. data/docs/guides/how-to-conditionally-server-render-based-on-device-type.md +40 -0
  52. data/docs/guides/how-to-use-different-files-for-client-and-server-rendering.md +98 -0
  53. data/docs/guides/i18n.md +87 -0
  54. data/docs/guides/installation-into-an-existing-rails-app.md +66 -0
  55. data/docs/guides/minitest-configuration.md +31 -0
  56. data/docs/guides/rails-webpacker-react-integration-options.md +213 -0
  57. data/docs/guides/react-on-rails-overview.md +29 -0
  58. data/docs/guides/react-server-rendering.md +32 -0
  59. data/docs/guides/render-functions-and-railscontext.md +205 -0
  60. data/docs/guides/rspec-configuration.md +73 -0
  61. data/docs/guides/tutorial.md +371 -0
  62. data/docs/{basics → guides}/upgrading-react-on-rails.md +126 -3
  63. data/docs/guides/webpack-configuration.md +42 -0
  64. data/docs/home.md +23 -0
  65. data/docs/javascript/asset-pipeline.md +12 -0
  66. data/docs/{additional-reading → javascript}/code-splitting.md +21 -11
  67. data/docs/javascript/converting-from-custom-webpack-config-to-rails-webpacker-config.md +10 -0
  68. data/docs/javascript/credits.md +10 -0
  69. data/docs/{additional-reading → javascript}/images.md +5 -6
  70. data/docs/javascript/react-helmet.md +100 -0
  71. data/docs/javascript/react-router.md +90 -0
  72. data/docs/{additional-reading → javascript}/server-rendering-tips.md +15 -12
  73. data/docs/javascript/troubleshooting-when-using-shakapacker.md +77 -0
  74. data/docs/{additional-reading → javascript}/webpack.md +2 -2
  75. data/docs/misc/articles.md +20 -0
  76. data/docs/misc/doctrine.md +5 -6
  77. data/docs/outdated/deferred-rendering.md +39 -0
  78. data/docs/{additional-reading → outdated}/rails-assets-relative-paths.md +4 -4
  79. data/docs/{additional-reading → outdated}/rails-assets.md +12 -20
  80. data/docs/{misc → outdated}/rails3.md +2 -2
  81. data/docs/rails/convert-rails-5-api-only-app.md +19 -0
  82. data/docs/rails/rails-engine-integration.md +32 -0
  83. data/docs/{additional-reading → rails}/rails_view_rendering_from_inline_javascript.md +2 -1
  84. data/docs/{additional-reading → rails}/turbolinks.md +13 -1
  85. data/docs/react-on-rails-pro/react-on-rails-pro.md +43 -0
  86. data/docs/testimonials/hvmn.md +25 -0
  87. data/docs/testimonials/resortpass.md +13 -0
  88. data/docs/testimonials/testimonials.md +28 -0
  89. data/jest.config.js +4 -0
  90. data/lib/generators/USAGE +1 -1
  91. data/lib/generators/react_on_rails/adapt_for_older_shakapacker_generator.rb +41 -0
  92. data/lib/generators/react_on_rails/base_generator.rb +55 -43
  93. data/lib/generators/react_on_rails/bin/dev +30 -0
  94. data/lib/generators/react_on_rails/bin/dev-static +30 -0
  95. data/lib/generators/react_on_rails/dev_tests_generator.rb +4 -3
  96. data/lib/generators/react_on_rails/generator_helper.rb +8 -6
  97. data/lib/generators/react_on_rails/generator_messages.rb +40 -0
  98. data/lib/generators/react_on_rails/install_generator.rb +37 -0
  99. data/lib/generators/react_on_rails/templates/.eslintrc +3 -1
  100. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +4 -6
  101. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static +9 -0
  102. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +21 -40
  103. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +4 -0
  104. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js +5 -0
  105. data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js +8 -0
  106. data/lib/generators/react_on_rails/templates/base/base/app/views/layouts/hello_world.html.erb +2 -1
  107. data/lib/generators/react_on_rails/templates/base/base/babel.config.js.tt +32 -0
  108. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +20 -4
  109. data/lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml +62 -0
  110. data/lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt +17 -0
  111. data/lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt +17 -0
  112. data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +25 -0
  113. data/lib/generators/react_on_rails/templates/base/base/config/webpack/production.js.tt +9 -0
  114. data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +117 -0
  115. data/lib/generators/react_on_rails/templates/base/base/config/webpack/test.js.tt +9 -0
  116. data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpack.config.js.tt +15 -0
  117. data/lib/generators/react_on_rails/templates/base/base/config/webpack/webpackConfig.js.tt +36 -0
  118. data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +8 -2
  119. data/lib/generators/react_on_rails/templates/dev_tests/spec/simplecov_helper.rb +1 -1
  120. data/lib/generators/react_on_rails/templates/dev_tests/spec/{features → system}/hello_world_spec.rb +2 -2
  121. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +6 -9
  122. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/store/helloWorldStore.js +1 -3
  123. data/lib/react_on_rails/configuration.rb +198 -145
  124. data/lib/react_on_rails/error.rb +2 -0
  125. data/lib/react_on_rails/git_utils.rb +5 -3
  126. data/lib/react_on_rails/{react_on_rails_helper.rb → helper.rb} +201 -190
  127. data/lib/react_on_rails/json_output.rb +1 -1
  128. data/lib/react_on_rails/json_parse_error.rb +28 -0
  129. data/lib/react_on_rails/locales/base.rb +169 -0
  130. data/lib/react_on_rails/locales/to_js.rb +33 -0
  131. data/lib/react_on_rails/locales/to_json.rb +23 -0
  132. data/lib/react_on_rails/packs_generator.rb +234 -0
  133. data/lib/react_on_rails/prerender_error.rb +35 -27
  134. data/lib/react_on_rails/react_component/render_options.rb +64 -9
  135. data/lib/react_on_rails/server_rendering_js_code.rb +55 -0
  136. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +126 -76
  137. data/lib/react_on_rails/server_rendering_pool.rb +0 -1
  138. data/lib/react_on_rails/test_helper/ensure_assets_compiled.rb +9 -8
  139. data/lib/react_on_rails/test_helper/webpack_assets_compiler.rb +17 -0
  140. data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +13 -12
  141. data/lib/react_on_rails/test_helper.rb +24 -3
  142. data/lib/react_on_rails/utils.rb +94 -25
  143. data/lib/react_on_rails/version.rb +1 -1
  144. data/lib/react_on_rails/version_checker.rb +5 -1
  145. data/lib/react_on_rails/version_syntax_converter.rb +14 -12
  146. data/lib/react_on_rails/webpacker_utils.rb +105 -5
  147. data/lib/react_on_rails.rb +8 -2
  148. data/lib/tasks/assets.rake +28 -60
  149. data/lib/tasks/generate_packs.rake +11 -0
  150. data/lib/tasks/locale.rake +5 -4
  151. data/package-scripts.yml +49 -0
  152. data/package.json +52 -47
  153. data/rakelib/docker.rake +0 -5
  154. data/rakelib/dummy_apps.rake +5 -8
  155. data/rakelib/example_type.rb +12 -3
  156. data/rakelib/examples.rake +5 -4
  157. data/rakelib/lint.rake +5 -16
  158. data/rakelib/node_package.rake +2 -2
  159. data/rakelib/release.rake +37 -23
  160. data/rakelib/run_rspec.rake +16 -44
  161. data/rakelib/task_helpers.rb +16 -4
  162. data/react_on_rails.gemspec +6 -22
  163. data/tsconfig.json +14 -0
  164. data/webpackConfigLoader.js +5 -4
  165. data/yarn.lock +5935 -3106
  166. metadata +122 -272
  167. data/Gemfile.rails32 +0 -74
  168. data/docs/additional-reading/asset-pipeline.md +0 -20
  169. data/docs/additional-reading/babel.md +0 -5
  170. data/docs/additional-reading/caching-and-performance.md +0 -4
  171. data/docs/additional-reading/heroku-deployment.md +0 -92
  172. data/docs/additional-reading/hot-reloading-rails-development.md +0 -57
  173. data/docs/additional-reading/node-server-rendering.md +0 -5
  174. data/docs/additional-reading/rails-engine-integration.md +0 -34
  175. data/docs/additional-reading/react-helmet.md +0 -80
  176. data/docs/additional-reading/react-router.md +0 -113
  177. data/docs/additional-reading/recommended-project-structure.md +0 -49
  178. data/docs/additional-reading/rspec-configuration.md +0 -56
  179. data/docs/additional-reading/webpack-dev-server.md +0 -15
  180. data/docs/api/ruby-api-hot-reload-view-helpers.md +0 -44
  181. data/docs/api/ruby-api.md +0 -8
  182. data/docs/basics/configuration.md +0 -163
  183. data/docs/basics/i18n.md +0 -77
  184. data/docs/tutorial.md +0 -220
  185. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-server +0 -12
  186. data/lib/react_on_rails/assets_precompile.rb +0 -150
  187. data/lib/react_on_rails/locales_to_js.rb +0 -134
  188. data/ruby-lint.yml +0 -25
  189. /data/docs/{additional-reading → additional-details}/updating-dependencies.md +0 -0
  190. /data/docs/{additional-reading → deployment}/elastic-beanstalk.md +0 -0
  191. /data/docs/{additional-reading → javascript}/angular-js-integration-migration.md +0 -0
  192. /data/docs/{additional-reading → javascript}/capistrano-deployment.md +0 -0
  193. /data/docs/{additional-reading → javascript}/foreman-issues.md +0 -0
  194. /data/docs/{additional-reading → javascript}/node-dependencies-and-npm.md +0 -0
  195. /data/docs/{additional-reading → javascript}/react-and-redux.md +0 -0
  196. /data/docs/{additional-reading → javascript}/troubleshooting-when-using-webpacker.md +0 -0
  197. /data/docs/{additional-reading → javascript}/webpack-v1-notes.md +0 -0
  198. /data/docs/{coding-style → misc}/style.md +0 -0
  199. /data/docs/{additional-reading → misc}/tips.md +0 -0
@@ -33,17 +33,68 @@ 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-server]
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/test.js
55
+ config/webpack/development.js
56
+ config/webpack/production.js
57
+ config/webpack/serverWebpackConfig.js
58
+ config/webpack/webpack.config.js
59
+ config/webpack/webpackConfig.js]
60
+ config = {
61
+ message: "// The source code including full typescript support is available at:"
62
+ }
63
+ base_files.each do |file|
64
+ template("#{base_path}/#{file}.tt", file, config)
65
+ end
66
+ end
67
+
68
+ def copy_shakapacker_config
69
+ puts "Adding Shakapacker v7 config file"
70
+ base_path = "base/base/"
71
+ base_files = %w[config/shakapacker.yml]
37
72
  base_files.each { |file| copy_file("#{base_path}#{file}", file) }
38
73
  end
39
74
 
40
75
  def add_base_gems_to_gemfile
41
- gem "mini_racer", platforms: :ruby
42
76
  run "bundle"
43
77
  end
44
78
 
45
79
  def add_yarn_dependencies
46
- run "yarn add react-on-rails --exact"
80
+ major_minor_patch_only = /\A\d+\.\d+\.\d+\z/.freeze
81
+ if ReactOnRails::VERSION.match?(major_minor_patch_only)
82
+ run "yarn add react-on-rails@#{ReactOnRails::VERSION} --exact"
83
+ else
84
+ # otherwise add latest
85
+ puts "Adding the lastest react-on-rails NPM module. Double check this is correct in package.json"
86
+ run "yarn add react-on-rails --exact"
87
+ end
88
+
89
+ puts "Adding React dependencies"
90
+ run "yarn add react react-dom @babel/preset-react prop-types babel-plugin-transform-react-remove-prop-types \
91
+ babel-plugin-macros"
92
+
93
+ puts "Adding CSS handlers"
94
+ run "yarn add css-loader css-minimizer-webpack-plugin mini-css-extract-plugin style-loader"
95
+
96
+ puts "Adding dev dependencies"
97
+ run "yarn add -D @pmmmwh/react-refresh-webpack-plugin react-refresh"
47
98
  end
48
99
 
49
100
  def append_to_spec_rails_helper
@@ -81,51 +132,12 @@ module ReactOnRails
81
132
  ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
82
133
  STR
83
134
 
84
- def self.helpful_message
85
- <<-MSG.strip_heredoc
86
-
87
- What to do next:
88
-
89
- - See the documentation on https://github.com/rails/webpacker/blob/master/docs/webpack.md
90
- for how to customize the default webpack configuration.
91
-
92
- - Include your webpack assets to your application layout.
93
-
94
- <%= javascript_pack_tag 'hello-world-bundle' %>
95
-
96
- - Run `rails s` to start the Rails server and use Webpacker's default lazy compilation.
97
-
98
- - Visit http://localhost:3000/hello_world and see your React On Rails app running!
99
-
100
- - Run bin/webpack-dev-server to start the Webpack dev server for compilation of Webpack
101
- assets as soon as you save. This default setup with the dev server does not work
102
- for server rendering
103
-
104
- - Alternately, you may turn off compile in config/webpacker.yml and run the foreman
105
- command to start the rails server and run webpack in watch mode.
106
-
107
- foreman start -f Procfile.dev
108
-
109
- - To turn on HMR, edit config/webpacker.yml and set HMR to true. Restart the rails server
110
- and bin/webpack-dev-server. Or use Procfile.dev-server.
111
-
112
- - To server render, change this line app/views/hello_world/index.html.erb to
113
- `prerender: true` to see server rendering (right click on page and select "view source").
114
-
115
- <%= react_component("HelloWorldApp", props: @hello_world_props, prerender: true) %>
116
- MSG
117
- end
118
-
119
- def print_helpful_message
120
- GeneratorMessages.add_info(self.class.helpful_message)
121
- end
122
-
123
135
  private
124
136
 
125
137
  # From https://github.com/rails/rails/blob/4c940b2dbfb457f67c6250b720f63501d74a45fd/railties/lib/rails/generators/rails/app/app_generator.rb
126
138
  def app_name
127
139
  @app_name ||= (defined_app_const_base? ? defined_app_name : File.basename(destination_root))
128
- .tr('\\', "").tr(". ", "_")
140
+ .tr("\\", "").tr(". ", "_")
129
141
  end
130
142
 
131
143
  def defined_app_name
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ def installed?(process)
5
+ IO.popen "#{process} -v"
6
+ rescue Errno::ENOENT
7
+ false
8
+ end
9
+
10
+ def run(process)
11
+ system "#{process} start -f Procfile.dev"
12
+ rescue Errno::ENOENT
13
+ warn <<~MSG
14
+ ERROR:
15
+ Please ensure `Procfile.dev` exists in your project!
16
+ MSG
17
+ exit!
18
+ end
19
+
20
+ if installed? "overmind"
21
+ run "overmind"
22
+ elsif installed? "foreman"
23
+ run "foreman"
24
+ else
25
+ warn <<~MSG
26
+ NOTICE:
27
+ For this script to run, you need either 'overmind' or 'foreman' installed on your machine. Please try this script after installing one of them.
28
+ MSG
29
+ exit!
30
+ end
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ def installed?(process)
5
+ IO.popen "#{process} -v"
6
+ rescue Errno::ENOENT
7
+ false
8
+ end
9
+
10
+ def run(process)
11
+ system "#{process} start -f Procfile.dev-static"
12
+ rescue Errno::ENOENT
13
+ warn <<~MSG
14
+ ERROR:
15
+ Please ensure `Procfile.dev-static` exists in your project!
16
+ MSG
17
+ exit!
18
+ end
19
+
20
+ if installed? "overmind"
21
+ run "overmind"
22
+ elsif installed? "foreman"
23
+ run "foreman"
24
+ else
25
+ warn <<~MSG
26
+ NOTICE:
27
+ For this script to run, you need either 'overmind' or 'foreman' installed on your machine. Please try this script after installing one of them.
28
+ MSG
29
+ exit!
30
+ end
@@ -25,7 +25,7 @@ module ReactOnRails
25
25
  end
26
26
 
27
27
  def copy_tests
28
- %w[spec/features/hello_world_spec.rb].each { |file| copy_file(file) }
28
+ %w[spec/system/hello_world_spec.rb].each { |file| copy_file(file) }
29
29
  end
30
30
 
31
31
  def add_test_related_gems_to_gemfile
@@ -36,6 +36,7 @@ module ReactOnRails
36
36
 
37
37
  def replace_prerender_if_server_rendering
38
38
  return unless options.example_server_rendering
39
+
39
40
  hello_world_index = File.join(destination_root, "app", "views", "hello_world", "index.html.erb")
40
41
  hello_world_contents = File.read(hello_world_index)
41
42
  new_hello_world_contents = hello_world_contents.gsub(/prerender: false/,
@@ -49,8 +50,8 @@ module ReactOnRails
49
50
  contents = File.read(package_json)
50
51
  replacement_value = <<-STRING
51
52
  "scripts": {
52
- "postinstall": "yarn link react-on-rails",
53
- STRING
53
+ "postinstall": "yalc link react-on-rails",
54
+ STRING
54
55
  new_client_package_json_contents = contents.gsub(/ {2}"scripts": {/,
55
56
  replacement_value)
56
57
  File.open(package_json, "w+") { |f| f.puts new_client_package_json_contents }
@@ -15,13 +15,11 @@ module GeneratorHelper
15
15
  end
16
16
 
17
17
  def setup_file_error(file, data)
18
- # rubocop:disable Layout/IndentHeredoc
19
- <<-MSG
20
- #{file} was not found.
21
- Please add the following content to your #{file} file:
22
- #{data}
18
+ <<~MSG
19
+ #{file} was not found.
20
+ Please add the following content to your #{file} file:
21
+ #{data}
23
22
  MSG
24
- # rubocop:enable Layout/IndentHeredoc
25
23
  end
26
24
 
27
25
  def empty_directory_with_keep_file(destination, config = {})
@@ -54,4 +52,8 @@ Please add the following content to your #{file} file:
54
52
  empty_directory(parent_directories) unless dest_dir_exists?(parent_directories)
55
53
  copy_file source_file, destination_file
56
54
  end
55
+
56
+ def add_documentation_reference(message, source)
57
+ "#{message} \n#{source}"
58
+ end
57
59
  end
@@ -37,5 +37,45 @@ module GeneratorMessages
37
37
  def clear
38
38
  @output = []
39
39
  end
40
+
41
+ def helpful_message_after_installation
42
+ <<~MSG
43
+
44
+ What to do next:
45
+
46
+ - See the documentation on https://github.com/shakacode/shakapacker#webpack-configuration
47
+ for how to customize the default webpack configuration.
48
+
49
+ - Include your webpack assets to your application layout.
50
+
51
+ <%= javascript_pack_tag 'hello-world-bundle' %>
52
+
53
+ - To start Rails server run:
54
+
55
+ ./bin/dev # Running with HMR
56
+
57
+ or
58
+
59
+ ./bin/dev-static # Running with statically created bundles, without HMR
60
+
61
+ - To server render, change this line app/views/hello_world/index.html.erb to
62
+ `prerender: true` to see server rendering (right click on page and select "view source").
63
+
64
+ <%= react_component("HelloWorldApp", props: @hello_world_props, prerender: true) %>
65
+
66
+ Alternative steps to run the app:
67
+
68
+ - Run `rails s` to start the Rails server.
69
+
70
+ - Run bin/shakapacker-dev-server to start the Webpack dev server for compilation of Webpack
71
+ assets as soon as you save. This default setup with the dev server does not work
72
+ for server rendering
73
+
74
+ - Visit http://localhost:3000/hello_world and see your React On Rails app running!
75
+
76
+ - To turn on HMR, edit config/shakapacker.yml and set HMR to true. Restart the rails server
77
+ and bin/shakapacker-dev-server. Or use Procfile.dev.
78
+ MSG
79
+ end
40
80
  end
41
81
  end
@@ -28,6 +28,8 @@ module ReactOnRails
28
28
  def run_generators
29
29
  if installation_prerequisites_met? || options.ignore_warnings?
30
30
  invoke_generators
31
+ add_bin_scripts
32
+ add_post_install_message
31
33
  else
32
34
  error = "react_on_rails generator prerequisites not met!"
33
35
  GeneratorMessages.add_error(error)
@@ -51,6 +53,8 @@ module ReactOnRails
51
53
  else
52
54
  invoke "react_on_rails:react_no_redux"
53
55
  end
56
+
57
+ invoke "react_on_rails:adapt_for_older_shakapacker" unless using_shakapacker_7?
54
58
  end
55
59
 
56
60
  # NOTE: other requirements for existing files such as .gitignore or application.
@@ -62,6 +66,7 @@ module ReactOnRails
62
66
 
63
67
  def missing_yarn?
64
68
  return false unless ReactOnRails::Utils.running_on_windows? ? `where yarn`.blank? : `which yarn`.blank?
69
+
65
70
  error = "yarn is required. Please install it before continuing. https://yarnpkg.com/en/docs/install"
66
71
  GeneratorMessages.add_error(error)
67
72
  true
@@ -69,10 +74,42 @@ module ReactOnRails
69
74
 
70
75
  def missing_node?
71
76
  return false unless ReactOnRails::Utils.running_on_windows? ? `where node`.blank? : `which node`.blank?
77
+
72
78
  error = "** nodejs is required. Please install it before continuing. https://nodejs.org/en/"
73
79
  GeneratorMessages.add_error(error)
74
80
  true
75
81
  end
82
+
83
+ def add_bin_scripts
84
+ directory "#{__dir__}/bin", "bin"
85
+
86
+ # Make these and only these files executable
87
+ files_to_copy = []
88
+ Dir.chdir("#{__dir__}/bin") do
89
+ files_to_copy.concat(Dir.glob("*"))
90
+ end
91
+ files_to_become_excutable = files_to_copy.map { |filename| "bin/#{filename}" }
92
+
93
+ File.chmod(0o755, *files_to_become_excutable)
94
+ end
95
+
96
+ def add_post_install_message
97
+ message = GeneratorMessages.helpful_message_after_installation
98
+ unless using_shakapacker_7?
99
+ message = message.gsub("config/shakapacker", "config/webpacker")
100
+ message = message.gsub("bin/shakapacker", "bin/webpacker")
101
+ end
102
+
103
+ GeneratorMessages.add_info(message)
104
+ end
105
+
106
+ def using_shakapacker_7?
107
+ shakapacker_gem = Gem::Specification.find_by_name("shakapacker")
108
+ shakapacker_gem.version.segments.first == 7
109
+ rescue Gem::MissingSpecError
110
+ # In case using Webpacker
111
+ false
112
+ end
76
113
  end
77
114
  end
78
115
  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,7 +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
- client: sh -c 'rm -rf public/packs/* || true && bundle exec rake react_on_rails:locale && bin/webpack -w'
3
+ rails: bundle exec rails s -p 3000
4
+ wp-client: bin/shakapacker-dev-server
5
+ wp-server: SERVER_BUNDLE_ONLY=yes bin/shakapacker --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/shakapacker
9
+ webpack: sh -c 'rm -rf public/packs/* || true && bin/shakapacker -w'
@@ -1,45 +1,26 @@
1
1
  import PropTypes from 'prop-types';
2
- import React from 'react';
2
+ import React, { useState } from 'react';
3
+ import style from './HelloWorld.module.css';
3
4
 
4
- export default class HelloWorld extends React.Component {
5
- static propTypes = {
6
- name: PropTypes.string.isRequired, // this is passed from the Rails view
7
- };
5
+ const HelloWorld = (props) => {
6
+ const [name, setName] = useState(props.name);
8
7
 
9
- /**
10
- * @param props - Comes from your rails view.
11
- */
12
- constructor(props) {
13
- super(props);
8
+ return (
9
+ <div>
10
+ <h3>Hello, {name}!</h3>
11
+ <hr />
12
+ <form>
13
+ <label className={style.bright} htmlFor="name">
14
+ Say hello to:
15
+ <input id="name" type="text" value={name} onChange={(e) => setName(e.target.value)} />
16
+ </label>
17
+ </form>
18
+ </div>
19
+ );
20
+ };
14
21
 
15
- // How to set initial state in ES6 class syntax
16
- // https://reactjs.org/docs/state-and-lifecycle.html#adding-local-state-to-a-class
17
- this.state = { name: this.props.name };
18
- }
22
+ HelloWorld.propTypes = {
23
+ name: PropTypes.string.isRequired, // this is passed from the Rails view
24
+ };
19
25
 
20
- updateName = (name) => {
21
- this.setState({ name });
22
- };
23
-
24
- render() {
25
- return (
26
- <div>
27
- <h3>
28
- Hello, {this.state.name}!
29
- </h3>
30
- <hr />
31
- <form >
32
- <label htmlFor="name">
33
- Say hello to:
34
- </label>
35
- <input
36
- id="name"
37
- type="text"
38
- value={this.state.name}
39
- onChange={(e) => this.updateName(e.target.value)}
40
- />
41
- </form>
42
- </div>
43
- );
44
- }
45
- }
26
+ export default HelloWorld;
@@ -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
+ });
@@ -1,9 +1,10 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title>ReactOnRailsWithWebpacker</title>
4
+ <title>ReactOnRailsWithShakapacker</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_demo_ssr_hmr/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
+ }
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # See https://github.com/shakacode/react_on_rails/blob/master/docs/basics/configuration.md
3
+ # See https://github.com/shakacode/react_on_rails/blob/master/docs/guides/configuration.md
4
4
  # for many more options.
5
5
 
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
- config.build_production_command = "RAILS_ENV=production NODE_ENV=production bin/webpack"
9
+ # If nil, then the standard shakacode/shakapacker assets:precompile will run
10
+ # config.build_production_command = nil
10
11
 
11
12
  ################################################################################
12
13
  ################################################################################
@@ -22,7 +23,9 @@ ReactOnRails.configure do |config|
22
23
  # with rspec then this controls what yarn command is run
23
24
  # to automatically refresh your webpack assets on every test run.
24
25
  #
25
- config.build_test_command = "RAILS_ENV=test bin/webpack"
26
+ # Alternately, you can remove the `ReactOnRails::TestHelper.configure_rspec_to_compile_assets`
27
+ # and set the config/shakapacker.yml option for test to true.
28
+ config.build_test_command = "RAILS_ENV=test bin/shakapacker"
26
29
 
27
30
  ################################################################################
28
31
  ################################################################################
@@ -38,5 +41,18 @@ ReactOnRails.configure do |config|
38
41
  # different. You should have ONE server bundle which can create all of your server rendered
39
42
  # React components.
40
43
  #
41
- config.server_bundle_js_file = "hello-world-bundle.js"
44
+ config.server_bundle_js_file = "server-bundle.js"
45
+
46
+ ################################################################################
47
+ ################################################################################
48
+ # FILE SYSTEM BASED COMPONENT REGISTRY
49
+ ################################################################################
50
+ # `components_subdirectory` is the name of the matching directories that contain automatically registered components
51
+ # for use in the Rails views. The default is nil, you can enable the feature by updating it in the next line.
52
+ # config.components_subdirectory = "ror_components"
53
+ #
54
+ # For automated component registry, `render_component` view helper method tries to load bundle for component from
55
+ # generated directory. default is false, you can pass option at the time of individual usage or update the default
56
+ # in the following line
57
+ config.auto_load_bundle = false
42
58
  end
@@ -0,0 +1,62 @@
1
+ # Note: You must restart bin/shakapacker-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/shakapacker
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/shakapacker -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
@@ -0,0 +1,17 @@
1
+ <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_demo_ssr_hmr/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;