diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c1062047..7ee533c60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Please follow the recommendations outlined at [keepachangelog.com](http://keepac ## Versions ### [Unreleased] Changes since the last non-beta release. +#### Added +- Pack Generation: Added functionality that will add an import statement, if missing, to the server bundle entrypoint even if the autobundle generated files still exist [PR 1610](https://github.com/shakacode/react_on_rails/pull/1610) by [judahmeek](https://github.com/judahmeek). ### [14.0.0] - 2024-04-03 _Major bump because dropping support for Ruby 2.7 and deprecated `webpackConfigLoader.js`._ diff --git a/docs/guides/file-system-based-automated-bundle-generation.md b/docs/guides/file-system-based-automated-bundle-generation.md index 0c9efe160..8d739308d 100644 --- a/docs/guides/file-system-based-automated-bundle-generation.md +++ b/docs/guides/file-system-based-automated-bundle-generation.md @@ -36,15 +36,26 @@ You can change the value in `config/initializers/react_on_rails` by updating it config.auto_load_bundle = true ``` +### Location of generated files +Generated files will go to the following two directories: +* Pack files for entrypoint components will be generated in the `{Shakapacker.config.source_entry_path}/generated` directory. +* The interim server bundle file, which is only generated if you already have a server bundle entrypoint and have not set `make_generated_server_bundle_the_entrypoint` to `true`, will be generated in the `{Pathname(Shakapacker.config.source_entry_path).parent}/generated` directory. + ### Update `.gitignore` file -React on Rails automatically generates pack files for components to be registered in the `packs/generated` directory. To avoid committing generated files into the version control system, please update `.gitignore` to have +To avoid committing generated files to your version control system, please update `.gitignore` to include: ```gitignore # Generated React on Rails packs -app/javascript/packs/generated +**/generated/** ``` -*Note: the directory might be different depending on the `source_entry_path` in `config/shakapacker.yml`.* +### Commit changes to server bundle entrypoint +If you already have an existing server bundle entrypoint and have not set `make_generated_server_bundle_the_entrypoint` to `true`, then pack generation will add an import statement to your existing server bundle entrypoint similar to: +```javascript +// import statement added by react_on_rails:generate_packs rake task +import "./../generated/server-bundle-generated.js" +``` +We recommend committing this import statement to your version control system. ## Usage @@ -126,7 +137,7 @@ The tricky part is to figure out which bundles to load on any Rails view. [Shaka File-system-based automated pack generation simplifies this process with a new option for the view helpers. -For example, if you wanted to utilize our file-system based entrypoint generation for `FooComponentOne` & `BarComponentOne`, but not `BarComponentTwo` (for whatever reason), then... +For example, if you wanted to utilize our file-system based entrypoint generation for `FooComponentOne` and `BarComponentOne`, but not `BarComponentTwo` (for whatever reason), then... 1. Remove generated entrypoints from parameters passed directly to `javascript_pack_tag` and `stylesheet_pack_tag`. 2. Remove generated entrypoints from parameters passed directly to `append_javascript_pack_tag` and `append_stylesheet_pack_tag`. @@ -186,7 +197,7 @@ For example, if you wanted to utilize our file-system based entrypoint generatio If server rendering is enabled, the component will be registered for usage both in server and client rendering. In order to have separate definitions for client and server rendering, name the component files as `ComponentName.server.jsx` and `ComponentName.client.jsx`. The `ComponentName.server.jsx` file will be used for server rendering and the `ComponentName.client.jsx` file for client rendering. If you don't want the component rendered on the server, you should only have the `ComponentName.client.jsx` file. -Once generated, all server entrypoints will be imported into a file named `[ReactOnRails.configuration.server_bundle_js_file]-generated.js`, which in turn will be imported into a source file named the same as `ReactOnRails.configuration.server_bundle_js_file`. If your server bundling logic is such that your server bundle source entrypoint is not named the same as your `ReactOnRails.configuration.server_bundle_js_file` & changing it would be difficult, please let us know. +Once generated, all server entrypoints will be imported into a file named `[ReactOnRails.configuration.server_bundle_js_file]-generated.js`, which in turn will be imported into a source file named the same as `ReactOnRails.configuration.server_bundle_js_file`. If your server bundling logic is such that your server bundle source entrypoint is not named the same as your `ReactOnRails.configuration.server_bundle_js_file` and changing it would be difficult, please let us know. *Note: If specifying separate definitions for client and server rendering, please make sure to delete the generalized `ComponentName.jsx` file.* diff --git a/lib/react_on_rails/packs_generator.rb b/lib/react_on_rails/packs_generator.rb index a48bf04c5..d461e4ddf 100644 --- a/lib/react_on_rails/packs_generator.rb +++ b/lib/react_on_rails/packs_generator.rb @@ -15,6 +15,7 @@ def self.instance def generate_packs_if_stale return unless ReactOnRails.configuration.auto_load_bundle + add_generated_pack_to_server_bundle are_generated_files_present_and_up_to_date = Dir.exist?(generated_packs_directory_path) && File.exist?(generated_server_bundle_file_path) && !stale_or_missing_packs? @@ -99,8 +100,8 @@ def add_generated_pack_to_server_bundle def generated_server_bundle_file_path return server_bundle_entrypoint if ReactOnRails.configuration.make_generated_server_bundle_the_entrypoint - generated_server_bundle_file_path = server_bundle_entrypoint.sub(".js", "-generated.js") - generated_server_bundle_file_name = component_name(generated_server_bundle_file_path) + generated_interim_server_bundle_path = server_bundle_entrypoint.sub(".js", "-generated.js") + generated_server_bundle_file_name = component_name(generated_interim_server_bundle_path) source_entrypoint_parent = Pathname(ReactOnRails::WebpackerUtils.webpacker_source_entry_path).parent generated_nonentrypoints_path = "#{source_entrypoint_parent}/generated" diff --git a/spec/dummy/client/app/packs/server-bundle.js b/spec/dummy/client/app/packs/server-bundle.js index 396caff6d..517fe677e 100644 --- a/spec/dummy/client/app/packs/server-bundle.js +++ b/spec/dummy/client/app/packs/server-bundle.js @@ -1,3 +1,5 @@ +// import statement added by react_on_rails:generate_packs rake task +import './../generated/server-bundle-generated.js'; // Shows the mapping from the exported object to the name used by the server rendering. import ReactOnRails from 'react-on-rails'; // Example of server rendering with no React diff --git a/spec/dummy/spec/packs_generator_spec.rb b/spec/dummy/spec/packs_generator_spec.rb index 3fc078326..c2bfb64bf 100644 --- a/spec/dummy/spec/packs_generator_spec.rb +++ b/spec/dummy/spec/packs_generator_spec.rb @@ -234,6 +234,17 @@ module ReactOnRails end.not_to output(GENERATED_PACKS_CONSOLE_OUTPUT_REGEX).to_stdout end + it "adds a single import statement to the server bundle" do + test_string = "// import statement added by react_on_rails:generate_packs" + same_instance = described_class.instance + File.truncate(server_bundle_js_file_path, 0) + same_instance.generate_packs_if_stale + expect(File.read(server_bundle_js_file_path).scan(/(?=#{test_string})/).count).to equal(1) + # the following expectation checks that an additional import statement is not added if one already exists + same_instance.generate_packs_if_stale + expect(File.read(server_bundle_js_file_path).scan(/(?=#{test_string})/).count).to equal(1) + end + it "generate packs if a new component is added" do create_new_component("NewComponent")