react_on_rails 13.1.0 → 13.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +5 -2
  3. data/.github/workflows/lint-js-and-ruby.yml +3 -3
  4. data/.github/workflows/main.yml +19 -13
  5. data/.github/workflows/package-js-tests.yml +2 -2
  6. data/.github/workflows/rspec-package-specs.yml +2 -2
  7. data/.rubocop.yml +4 -0
  8. data/CHANGELOG.md +21 -1
  9. data/Gemfile.development_dependencies +2 -2
  10. data/README.md +7 -5
  11. data/docs/api/javascript-api.md +9 -0
  12. data/docs/getting-started.md +15 -6
  13. data/docs/guides/configuration.md +25 -20
  14. data/docs/guides/file-system-based-automated-bundle-generation.md +16 -13
  15. data/docs/guides/installation-into-an-existing-rails-app.md +18 -20
  16. data/docs/guides/rails-webpacker-react-integration-options.md +8 -8
  17. data/docs/guides/react-server-rendering.md +1 -1
  18. data/docs/guides/tutorial.md +36 -32
  19. data/lib/generators/react_on_rails/base_generator.rb +15 -10
  20. data/lib/generators/react_on_rails/bin/dev +33 -0
  21. data/lib/generators/react_on_rails/bin/dev-static +33 -0
  22. data/lib/generators/react_on_rails/install_generator.rb +5 -0
  23. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +1 -1
  24. data/lib/react_on_rails/configuration.rb +40 -3
  25. data/lib/react_on_rails/helper.rb +21 -23
  26. data/lib/react_on_rails/packs_generator.rb +30 -101
  27. data/lib/react_on_rails/test_helper/ensure_assets_compiled.rb +1 -1
  28. data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +1 -20
  29. data/lib/react_on_rails/utils.rb +26 -0
  30. data/lib/react_on_rails/version.rb +1 -1
  31. data/lib/react_on_rails/webpacker_utils.rb +54 -3
  32. data/lib/tasks/generate_packs.rake +1 -1
  33. data/package.json +29 -28
  34. data/yarn.lock +2856 -3277
  35. metadata +4 -2
@@ -3,9 +3,9 @@
3
3
  You only _need_ props hydration if you need SSR. However, there's no good reason to
4
4
  have your app make a second round trip to the Rails server to get initialization props.
5
5
 
6
- **Server-Side Rendering (SSR)** results in Rails rendering HTML for your React components. The main reasons to use SSR are better SEO and pages display more quickly.
6
+ **Server-Side Rendering (SSR)** results in Rails rendering HTML for your React components. The main reasons to use SSR are better SEO and pages display more quickly.
7
7
 
8
- These gems provide advanced integration of React with [rails/webpacker](https://github.com/rails/webpacker):
8
+ These gems provide advanced integration of React with [rails/webpacker](https://github.com/rails/webpacker):
9
9
 
10
10
  | Gem | Props Hydration | Server-Side-Rendering (SSR) | SSR with HMR | SSR with React-Router | SSR with Code Splitting | Node SSR |
11
11
  | --- | --------------- | --- | --------------------- | ----------------------| ------------------------|----|
@@ -19,7 +19,7 @@ Note, Node SSR for React on Rails requires [React on Rails Pro](https://www.shak
19
19
 
20
20
  As mentioned, you don't _need_ to use a gem to integrate Rails with React.
21
21
 
22
- If you're not concerned with view helpers to pass props or server rendering, can do it yourself:
22
+ If you're not concerned with view helpers to pass props or server rendering, you can do it yourself:
23
23
 
24
24
  ```erb
25
25
  <%# views/layouts/application.html.erb %>
@@ -71,7 +71,7 @@ development:
71
71
  inline: true
72
72
  ```
73
73
 
74
- This basic configuration alone will have HMR working with the default webpacker setup. However, an code saves will trigger a full page refresh each time you save a file.
74
+ This basic configuration alone will have HMR working with the default webpacker setup. However, a code save will trigger a full page refresh each time you save a file.
75
75
 
76
76
  Webpack's HMR allows the replacement of modules for React in-place without reloading the browser. To do this, you have two options:
77
77
 
@@ -95,9 +95,9 @@ You can see an example commit of adding this [here](https://github.com/shakacode
95
95
  ```js
96
96
  const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
97
97
  const environment = require('./environment')
98
-
98
+
99
99
  const isWebpackDevServer = process.env.WEBPACK_DEV_SERVER;
100
-
100
+
101
101
  //plugins
102
102
  if (isWebpackDevServer) {
103
103
  environment.plugins.append(
@@ -164,11 +164,11 @@ const environment = require('./environment')
164
164
  + if (!module.hot) {
165
165
  + environment.loaders.get('sass').use.find(item => item.loader === 'sass-loader').options.sourceMapContents = false
166
166
  + }
167
- +
167
+ +
168
168
  module.exports = environment.toWebpackConfig()
169
169
  ```
170
170
 
171
- 5. Adjust your `config/webpack/environment.js` for a
171
+ 5. Adjust your `config/webpack/environment.js` for a
172
172
 
173
173
  ```diff
174
174
  // config/webpack/environment.js
@@ -17,7 +17,7 @@ See [this note](https://www.shakacode.com/react-on-rails/docs/guides/client-vs-s
17
17
 
18
18
  ## How do you do Server Rendering with React on Rails?
19
19
  1. The `react_component` view helper method provides the `prerender:` option to switch on or off server rendering.
20
- 1. Configure your Webpack setup to create a different server bundle per your needs. While you may reuse the same bundle as for client rendering, this is not common in larger apps for many reasons, such as as code splitting, handling CSS and images, different code paths for React Router on the server vs. client, etc.
20
+ 1. Configure your Webpack setup to create a different server bundle per your needs. While you may reuse the same bundle as for client rendering, this is not common in larger apps for many reasons, such as code splitting, handling CSS and images, different code paths for React Router on the server vs. client, etc.
21
21
  1. You need to configure `config.server_bundle_js_file = "server-bundle.js"` in your `config/initializers/react_on_rails.rb`
22
22
  1. You should ***not*** put a hash on the server-bundle so that you can easily use the webpack-dev-server for client bundles and have the server bundle generated by a watch process.
23
23
 
@@ -45,25 +45,23 @@ Then we need to create a fresh Rails application as following.
45
45
  First be sure to run `rails -v` and check you are using Rails 5.1.3 or above. If you are using an older version of Rails, you'll need to install webpacker with react per the instructions [here](https://github.com/rails/webpacker).
46
46
 
47
47
  ```bash
48
- cd <directory where you want to create your new Rails app>
48
+ # For Rails 6.x
49
+ rails new test-react-on-rails --skip-javascript
49
50
 
50
- # Any name you like for the rails app
51
- # Skip javascript so will add that next and get the current version
52
- # This is for Rails 7
53
- rails new --skip-turbolinks --skip-javascript test-react-on-rails
51
+ # For Rails 7.x
52
+ rails new test-react-on-rails --skip-turbolinks --skip-javascript
54
53
 
55
54
  cd test-react-on-rails
56
55
  ```
57
56
 
58
57
  ## Add the shakapacker and react_on_rails gems
59
- To avoid issues regarding inconsistent gem and npm versions, you should specify the exact versions
60
- of both the gem and npm package. In other words, don't use the `^` or `~` in the version specifications.
61
- _Use the latest version for `react_on_rails` and `shakapacker`._
62
-
63
- ```
64
- gem 'react_on_rails', '13.0.1' # prefer exact gem version to match npm version
65
- gem 'shakapacker', '6.4.0' # prefer exact gem version to match npm version
58
+ We recommend using the latest version of these gems. Otherwise, specify the
59
+ exact versions of both the gem and npm package. In other words, don't use
60
+ the `^` or `~` in the version specifications.
66
61
 
62
+ ```bash
63
+ bundle add react_on_rails --strict
64
+ bundle add shakapacker --strict
67
65
  ```
68
66
 
69
67
  Note: The latest released React On Rails version is considered stable. Please use the latest
@@ -71,32 +69,34 @@ version to ensure you get all the security patches and the best support.
71
69
 
72
70
  ## Run the shakapacker (webpacker) generator
73
71
 
74
- ```terminal
72
+ ```bash
75
73
  bundle exec rails webpacker:install
76
74
  ```
77
75
 
78
- **Let's commit everything before installing React on Rails.**
76
+ Commit all the changes so far to avoid getting errors in the next step.
79
77
 
78
+ ```bash
79
+ git commit -am "Initial commit"
80
80
  ```
81
- # Here are git commands to make a new git repo and commit everything.
82
- # Newer versions of Rails create the git repo by default.
83
- git add -A
84
- git commit -m "Initial commit"
85
- ```
81
+
82
+ Alternatively you can use `--ignore-warnings` in the next step.
86
83
 
87
84
  ## Run the React on Rails Generator
88
85
 
89
- Install React on Rails: `rails generate react_on_rails:install`. You need to first git commit your files before running the generator, or else it will generate an error.
86
+ ```bash
87
+ rails generate react_on_rails:install
88
+ ```
89
+
90
+ You will be prompted to approve changes in certain files. Press `enter` to proceed
91
+ one by one or enter `a` to replace all configuration files required by the project.
92
+ You can check the diffs before you commit to see what changed.
90
93
 
91
94
  Note, using `redux` is no longer recommended as the basic installer uses React Hooks.
92
- If you want the redux install: `rails generate react_on_rails:install --redux`
95
+ If you want the redux install, run:
93
96
 
97
+ ```bash
98
+ rails generate react_on_rails:install --redux
94
99
  ```
95
- bundle exec rails generate react_on_rails:install
96
- ```
97
-
98
- Enter `a` to replace all configuration files required by the project. You can check the diffs
99
- before you commit to see what changed.
100
100
 
101
101
  ## Setting up your environment variables
102
102
 
@@ -108,14 +108,18 @@ EXECJS_RUNTIME=Node
108
108
 
109
109
  Then run the server with one of the following options:
110
110
 
111
- ## Running with HMR
112
- ```
113
- foreman start -f Procfile.dev
114
- ```
111
+ ## Running the app
115
112
 
116
- ## Running without HMR, statically creating the bundles
113
+ ### For HMR:
114
+
115
+ ```bash
116
+ ./bin/dev
117
117
  ```
118
- foreman start -f Procfile.dev-static
118
+
119
+ ### Without HMR, statically creating the bundles
120
+
121
+ ```bash
122
+ ./bin/dev-static
119
123
  ```
120
124
 
121
125
  Visit [http://localhost:3000/hello_world](http://localhost:3000/hello_world) and see your **React On Rails** app running!
@@ -144,6 +144,21 @@ module ReactOnRails
144
144
 
145
145
  <%= javascript_pack_tag 'hello-world-bundle' %>
146
146
 
147
+ - To start Rails server run:
148
+
149
+ ./bin/dev # Running with HMR
150
+
151
+ or
152
+
153
+ ./bin/dev # Running with statically created bundles, without HMR
154
+
155
+ - To server render, change this line app/views/hello_world/index.html.erb to
156
+ `prerender: true` to see server rendering (right click on page and select "view source").
157
+
158
+ <%= react_component("HelloWorldApp", props: @hello_world_props, prerender: true) %>
159
+
160
+ Alternative steps to run the app:
161
+
147
162
  - Run `rails s` to start the Rails server.
148
163
 
149
164
  - Run bin/webpacker-dev-server to start the Webpack dev server for compilation of Webpack
@@ -152,18 +167,8 @@ module ReactOnRails
152
167
 
153
168
  - Visit http://localhost:3000/hello_world and see your React On Rails app running!
154
169
 
155
- - Alternately, run the foreman command to start the rails server and run webpack#{' '}
156
- in watch mode.
157
-
158
- foreman start -f Procfile.dev-static
159
-
160
170
  - To turn on HMR, edit config/webpacker.yml and set HMR to true. Restart the rails server
161
171
  and bin/webpacker-dev-server. Or use Procfile.dev.
162
-
163
- - To server render, change this line app/views/hello_world/index.html.erb to
164
- `prerender: true` to see server rendering (right click on page and select "view source").
165
-
166
- <%= react_component("HelloWorldApp", props: @hello_world_props, prerender: true) %>
167
172
  MSG
168
173
  end
169
174
 
@@ -0,0 +1,33 @@
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
+ args = [*ARGV]
12
+ args.shift
13
+ puts "Using #{process}"
14
+ exec "#{process} start -f Procfile.dev", args.join(" ")
15
+ rescue Errno::ENOENT
16
+ warn <<~MSG
17
+ ERROR:
18
+ Please ensure `Procfile.dev` exist in your project!
19
+ MSG
20
+ exit!
21
+ end
22
+
23
+ if installed? "overmind"
24
+ run "overmind"
25
+ elsif installed? "foreman"
26
+ run "foreman"
27
+ else
28
+ warn <<~MSG
29
+ NOTICE:
30
+ For this script to run, you need either 'overmind' or 'foreman' installed on your machine. Please try this script after installing one of them.
31
+ MSG
32
+ exit!
33
+ end
@@ -0,0 +1,33 @@
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
+ args = [*ARGV]
12
+ args.shift
13
+ puts "Using #{process}"
14
+ exec "#{process} start -f Procfile.dev-static", args.join(" ")
15
+ rescue Errno::ENOENT
16
+ warn <<~MSG
17
+ ERROR:
18
+ Please ensure `Procfile.dev-static` exist in your project!
19
+ MSG
20
+ exit!
21
+ end
22
+
23
+ if installed? "overmind"
24
+ run "overmind"
25
+ elsif installed? "foreman"
26
+ run "foreman"
27
+ else
28
+ warn <<~MSG
29
+ NOTICE:
30
+ For this script to run, you need either 'overmind' or 'foreman' installed on your machine. Please try this script after installing one of them.
31
+ MSG
32
+ exit!
33
+ end
@@ -28,6 +28,7 @@ module ReactOnRails
28
28
  def run_generators
29
29
  if installation_prerequisites_met? || options.ignore_warnings?
30
30
  invoke_generators
31
+ add_bin_scripts
31
32
  else
32
33
  error = "react_on_rails generator prerequisites not met!"
33
34
  GeneratorMessages.add_error(error)
@@ -75,6 +76,10 @@ module ReactOnRails
75
76
  GeneratorMessages.add_error(error)
76
77
  true
77
78
  end
79
+
80
+ def add_bin_scripts
81
+ directory "#{__dir__}/bin", "bin"
82
+ end
78
83
  end
79
84
  end
80
85
  end
@@ -1,6 +1,6 @@
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|
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Metrics/ClassLength
4
+
3
5
  module ReactOnRails
4
6
  def self.configure
5
7
  yield(configuration)
@@ -109,6 +111,7 @@ module ReactOnRails
109
111
 
110
112
  # on ReactOnRails
111
113
  def setup_config_values
114
+ check_autobundling_requirements_if_configured
112
115
  ensure_webpack_generated_files_exists
113
116
  configure_generated_assets_dirs_deprecation
114
117
  configure_skip_display_none_deprecation
@@ -121,14 +124,37 @@ module ReactOnRails
121
124
 
122
125
  private
123
126
 
127
+ def check_autobundling_requirements_if_configured
128
+ raise_missing_components_subdirectory if auto_load_bundle && !components_subdirectory.present?
129
+ return unless components_subdirectory.present?
130
+
131
+ ReactOnRails::WebpackerUtils.raise_shakapacker_not_installed unless ReactOnRails::WebpackerUtils.using_webpacker?
132
+ ReactOnRails::WebpackerUtils.raise_shakapacker_version_incompatible_for_autobundling unless
133
+ ReactOnRails::WebpackerUtils.shackapacker_version_requirement_met?(
134
+ ReactOnRails::PacksGenerator::MINIMUM_SHAKAPACKER_VERSION
135
+ )
136
+ ReactOnRails::WebpackerUtils.raise_nested_entries_disabled unless ReactOnRails::WebpackerUtils.nested_entries?
137
+ end
138
+
124
139
  def adjust_precompile_task
125
140
  skip_react_on_rails_precompile = %w[no false n f].include?(ENV["REACT_ON_RAILS_PRECOMPILE"])
126
141
 
127
142
  return if skip_react_on_rails_precompile || build_production_command.blank?
128
143
 
129
- # Ensure that shakacode/shakapacker does not call bin/webpacker if we're providing
130
- # the build command.
131
- ENV["WEBPACKER_PRECOMPILE"] = "false"
144
+ if Webpacker.config.webpacker_precompile?
145
+ msg = <<~MSG
146
+
147
+ React on Rails and Shakapacker error in configuration!
148
+ In order to use config/react_on_rails.rb config.build_production_command,
149
+ you must edit config/webpacker.yml to include this value in the default configuration:
150
+ 'webpacker_precompile: false'
151
+
152
+ Alternatively, remove the config/react_on_rails.rb config.build_production_command and the
153
+ default bin/webpacker script will be used for assets:precompile.
154
+
155
+ MSG
156
+ raise ReactOnRails::Error, msg
157
+ end
132
158
 
133
159
  precompile_tasks = lambda {
134
160
  Rake::Task["react_on_rails:generate_packs"].invoke
@@ -230,5 +256,16 @@ module ReactOnRails
230
256
 
231
257
  Rails.logger.warn "[DEPRECATION] ReactOnRails: remove skip_display_none from configuration."
232
258
  end
259
+
260
+ def raise_missing_components_subdirectory
261
+ msg = <<~MSG
262
+ **ERROR** ReactOnRails: auto_load_bundle is set to true, yet components_subdirectory is unconfigured.\
263
+ Please set components_subdirectory to the desired directory. For more information, please see \
264
+ https://www.shakacode.com/react-on-rails/docs/guides/file-system-based-automated-bundle-generation.md
265
+ MSG
266
+
267
+ raise ReactOnRails::Error, msg
268
+ end
233
269
  end
234
270
  end
271
+ # rubocop:enable Metrics/ClassLength
@@ -91,26 +91,6 @@ module ReactOnRails
91
91
  end
92
92
  end
93
93
 
94
- def load_pack_for_component(component_name)
95
- component_pack_file = generated_components_pack(component_name)
96
- is_component_pack_present = File.exist?("#{component_pack_file}.jsx")
97
- is_development = ENV["RAILS_ENV"] == "development"
98
-
99
- if is_development && !is_component_pack_present
100
- ReactOnRails::PacksGenerator.generate
101
- raise_generated_missing_pack_warning(component_name)
102
- end
103
-
104
- ReactOnRails::PacksGenerator.raise_nested_enteries_disabled unless ReactOnRails::WebpackerUtils.nested_entries?
105
-
106
- append_javascript_pack_tag "generated/#{component_name}"
107
- append_stylesheet_pack_tag "generated/#{component_name}"
108
- end
109
-
110
- def generated_components_pack(component_name)
111
- "#{ReactOnRails::WebpackerUtils.webpacker_source_entry_path}/generated/#{component_name}"
112
- end
113
-
114
94
  # react_component_hash is used to return multiple HTML strings for server rendering, such as for
115
95
  # adding meta-tags to a page.
116
96
  # It is exactly like react_component except for the following:
@@ -337,6 +317,25 @@ module ReactOnRails
337
317
 
338
318
  private
339
319
 
320
+ def load_pack_for_component(component_name)
321
+ is_component_pack_present = File.exist?(generated_components_pack_path(component_name))
322
+ is_development = ENV["RAILS_ENV"] == "development"
323
+
324
+ if is_development && !is_component_pack_present
325
+ ReactOnRails::PacksGenerator.instance.generate_packs_if_stale
326
+ raise_missing_pack_error(component_name)
327
+ end
328
+
329
+ ReactOnRails::WebpackerUtils.raise_nested_entries_disabled unless ReactOnRails::WebpackerUtils.nested_entries?
330
+
331
+ ApplicationController.helpers.append_javascript_pack_tag "generated/#{component_name}"
332
+ ApplicationController.helpers.append_stylesheet_pack_tag "generated/#{component_name}"
333
+ end
334
+
335
+ def generated_components_pack_path(component_name)
336
+ "#{ReactOnRails::WebpackerUtils.webpacker_source_entry_path}/generated/#{component_name}.js"
337
+ end
338
+
340
339
  def build_react_component_result_for_server_rendered_string(
341
340
  server_rendered_html: required("server_rendered_html"),
342
341
  component_specification_tag: required("component_specification_tag"),
@@ -552,10 +551,9 @@ module ReactOnRails
552
551
  result
553
552
  end
554
553
 
555
- def raise_generated_missing_pack_warning(component_name)
554
+ def raise_missing_pack_error(component_name)
556
555
  msg = <<~MSG
557
- **ERROR** ReactOnRails: Generated missing pack for Component: #{component_name}. Please refresh the webpage \
558
- once webpack has finished generating the bundles. If the problem persists
556
+ **ERROR** ReactOnRails: Generated missing pack for Component: #{component_name}. Please restart the webpack dev server or webpack in watch mode, to ensure webpack generates the chunks corresponding to #{component_name} component. If the problem persists
559
557
  1. Verify `components_subdirectory` is configured in `config/initializers/react_on_rails`.
560
558
  2. Component: #{component_name} is placed inside the configured `components_subdirectory`.
561
559
  MSG
@@ -6,45 +6,23 @@ module ReactOnRails
6
6
  # rubocop:disable Metrics/ClassLength
7
7
  class PacksGenerator
8
8
  CONTAINS_CLIENT_OR_SERVER_REGEX = /\.(server|client)($|\.)/.freeze
9
- MINIMUM_SHAKAPACKER_MAJOR_VERSION = 6
10
- MINIMUM_SHAKAPACKER_MINOR_VERSION = 5
11
- MINIMUM_SHAKAPACKER_PATCH_VERSION = 1
9
+ MINIMUM_SHAKAPACKER_VERSION = [6, 5, 1].freeze
12
10
 
13
- def self.generate
14
- packs_generator = PacksGenerator.new
15
- packs_generator.verify_setup_and_generate_packs
11
+ def self.instance
12
+ @instance ||= PacksGenerator.new
16
13
  end
17
14
 
18
- def self.raise_nested_enteries_disabled
19
- packs_generator = PacksGenerator.new
20
- packs_generator.raise_nested_enteries_disabled
21
- end
22
-
23
- def verify_setup_and_generate_packs
24
- return unless components_subdirectory.present?
25
-
26
- raise_webpacker_not_installed unless ReactOnRails::WebpackerUtils.using_webpacker?
27
- raise_shakapacker_version_incompatible unless shackapacker_version_requirement_met?
28
- raise_nested_enteries_disabled unless ReactOnRails::WebpackerUtils.nested_entries?
15
+ def generate_packs_if_stale
16
+ are_generated_files_present_and_up_to_date = Dir.exist?(generated_packs_directory_path) &&
17
+ File.exist?(generated_server_bundle_file_path) &&
18
+ !stale_or_missing_packs?
29
19
 
30
- is_generated_directory_present = Dir.exist?(generated_packs_directory_path)
31
-
32
- return if is_generated_directory_present && webpack_assets_status_checker.stale_generated_component_packs.empty?
20
+ return if are_generated_files_present_and_up_to_date
33
21
 
34
22
  clean_generated_packs_directory
35
23
  generate_packs
36
24
  end
37
25
 
38
- def raise_nested_enteries_disabled
39
- msg = <<~MSG
40
- **ERROR** ReactOnRails: `nested_entries` is configured to be disabled in shakapacker. Please update \
41
- webpacker.yml to enable nested enteries. for more information read
42
- https://www.shakacode.com/react-on-rails/docs/guides/file-system-based-automated-bundle-generation.md#enable-nested_entries-for-shakapacker
43
- MSG
44
-
45
- raise ReactOnRails::Error, msg
46
- end
47
-
48
26
  private
49
27
 
50
28
  def generate_packs
@@ -100,22 +78,26 @@ module ReactOnRails
100
78
  end
101
79
 
102
80
  def add_generated_pack_to_server_bundle
103
- relative_path_to_generated_server_bundle = relative_path(defined_server_bundle_file_path,
81
+ relative_path_to_generated_server_bundle = relative_path(server_bundle_entrypoint,
104
82
  generated_server_bundle_file_path)
105
83
  content = <<~FILE_CONTENT
106
- import "./#{relative_path_to_generated_server_bundle}"\n
84
+ // import statement added by react_on_rails:generate_packs rake task
85
+ import "./#{relative_path_to_generated_server_bundle}"
107
86
  FILE_CONTENT
108
87
 
109
- prepend_to_file_if_not_present(defined_server_bundle_file_path, content)
88
+ ReactOnRails::Utils.prepend_to_file_if_text_not_present(
89
+ file: server_bundle_entrypoint,
90
+ text_to_prepend: content,
91
+ regex: %r{import ['"]\./#{relative_path_to_generated_server_bundle}['"]}
92
+ )
110
93
  end
111
94
 
112
95
  def generated_server_bundle_file_path
113
- file_ext = File.extname(defined_server_bundle_file_path)
114
- generated_server_bundle_file_path = defined_server_bundle_file_path.sub(file_ext, "-generated#{file_ext}")
96
+ generated_server_bundle_file_path = server_bundle_entrypoint.sub(".js", "-generated.js")
115
97
  generated_server_bundle_file_name = component_name(generated_server_bundle_file_path)
116
98
  source_entry_path = ReactOnRails::WebpackerUtils.webpacker_source_entry_path
117
99
 
118
- "#{source_entry_path}/#{generated_server_bundle_file_name}#{file_ext}"
100
+ "#{source_entry_path}/#{generated_server_bundle_file_name}.js"
119
101
  end
120
102
 
121
103
  def clean_generated_packs_directory
@@ -123,8 +105,9 @@ module ReactOnRails
123
105
  FileUtils.mkdir_p(generated_packs_directory_path)
124
106
  end
125
107
 
126
- def defined_server_bundle_file_path
127
- ReactOnRails::Utils.server_bundle_js_file_path
108
+ def server_bundle_entrypoint
109
+ Rails.root.join(ReactOnRails::WebpackerUtils.webpacker_source_entry_path,
110
+ ReactOnRails.configuration.server_bundle_js_file)
128
111
  end
129
112
 
130
113
  def generated_packs_directory_path
@@ -150,7 +133,7 @@ module ReactOnRails
150
133
  end
151
134
 
152
135
  def generated_pack_path(file_path)
153
- "#{generated_packs_directory_path}/#{component_name(file_path)}.jsx"
136
+ "#{generated_packs_directory_path}/#{component_name(file_path)}.js"
154
137
  end
155
138
 
156
139
  def component_name(file_path)
@@ -197,23 +180,7 @@ module ReactOnRails
197
180
  def components_search_path
198
181
  source_path = ReactOnRails::WebpackerUtils.webpacker_source_path
199
182
 
200
- "#{source_path}/**/#{components_subdirectory}"
201
- end
202
-
203
- def components_subdirectory
204
- ReactOnRails.configuration.components_subdirectory
205
- end
206
-
207
- def webpack_assets_status_checker
208
- source_path = ReactOnRails::Utils.source_path
209
- generated_assets_full_path = ReactOnRails::Utils.generated_assets_full_path
210
- webpack_generated_files = ReactOnRails.configuration.webpack_generated_files
211
-
212
- @webpack_assets_status_checker ||= ReactOnRails::TestHelper::WebpackAssetsStatusChecker.new(
213
- source_path: source_path,
214
- generated_assets_full_path: generated_assets_full_path,
215
- webpack_generated_files: webpack_generated_files
216
- )
183
+ "#{source_path}/**/#{ReactOnRails.configuration.components_subdirectory}"
217
184
  end
218
185
 
219
186
  def raise_client_component_overrides_common(component_name)
@@ -245,53 +212,15 @@ module ReactOnRails
245
212
  raise ReactOnRails::Error, msg
246
213
  end
247
214
 
248
- def raise_shakapacker_version_incompatible
249
- msg = <<~MSG
250
- **ERROR** ReactOnRails: Please upgrade Shakapacker to version #{minimum_required_shakapacker_version} or \
251
- above to use the automated bundle generation feature. The currently installed version is \
252
- #{ReactOnRails::WebpackerUtils.shakapacker_version}.
253
- MSG
254
-
255
- raise ReactOnRails::Error, msg
256
- end
257
-
258
- def raise_webpacker_not_installed
259
- msg = <<~MSG
260
- **ERROR** ReactOnRails: Missing Shakapacker gem. Please upgrade to use Shakapacker \
261
- #{minimum_required_shakapacker_version} or above to use the \
262
- automated bundle generation feature.
263
- MSG
264
-
265
- raise ReactOnRails::Error, msg
266
- end
215
+ def stale_or_missing_packs?
216
+ component_files = common_component_to_path.values + client_component_to_path.values
217
+ most_recent_mtime = Utils.find_most_recent_mtime(component_files)
267
218
 
268
- def shakapacker_major_minor_version
269
- shakapacker_version = ReactOnRails::WebpackerUtils.shakapacker_version
270
- match = shakapacker_version.match(ReactOnRails::VersionChecker::MAJOR_MINOR_PATCH_VERSION_REGEX)
219
+ component_files.each_with_object([]).any? do |file|
220
+ path = generated_pack_path(file)
271
221
 
272
- [match[1].to_i, match[2].to_i, match[3].to_i]
273
- end
274
-
275
- def shackapacker_version_requirement_met?
276
- major = shakapacker_major_minor_version[0]
277
- minor = shakapacker_major_minor_version[1]
278
- patch = shakapacker_major_minor_version[2]
279
-
280
- major >= MINIMUM_SHAKAPACKER_MAJOR_VERSION && minor >= MINIMUM_SHAKAPACKER_MINOR_VERSION &&
281
- patch >= MINIMUM_SHAKAPACKER_PATCH_VERSION
282
- end
283
-
284
- def minimum_required_shakapacker_version
285
- "#{MINIMUM_SHAKAPACKER_MAJOR_VERSION}.#{MINIMUM_SHAKAPACKER_MINOR_VERSION}.#{MINIMUM_SHAKAPACKER_PATCH_VERSION}"
286
- end
287
-
288
- def prepend_to_file_if_not_present(file, text_to_prepend)
289
- file_content = File.read(file)
290
-
291
- return if file_content.include?(text_to_prepend)
292
-
293
- content_with_prepended_text = text_to_prepend + file_content
294
- File.write(file, content_with_prepended_text)
222
+ !File.exist?(path) || File.mtime(path) < most_recent_mtime
223
+ end
295
224
  end
296
225
  end
297
226
  # rubocop:enable Metrics/ClassLength
@@ -37,7 +37,7 @@ module ReactOnRails
37
37
  # All done if no stale files!
38
38
  return if stale_gen_files.empty?
39
39
 
40
- ReactOnRails::PacksGenerator.generate
40
+ ReactOnRails::PacksGenerator.instance.generate_packs_if_stale
41
41
 
42
42
  # Inform the developer that we're ensuring gen assets are ready.
43
43
  puts_start_compile_check_message(stale_gen_files)