Skip to content

Commit

Permalink
Make pack generation import statement commitable (#1610)
Browse files Browse the repository at this point in the history
* swap functions so the right errors show up
  • Loading branch information
Judahmeek authored May 16, 2024
1 parent 87fee8c commit 1295ce9
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`._
Expand Down
21 changes: 16 additions & 5 deletions docs/guides/file-system-based-automated-bundle-generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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.*

Expand Down
3 changes: 1 addition & 2 deletions lib/react_on_rails/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -441,11 +441,10 @@ def internal_react_component(react_component_name, options = {})
"data-trace" => (render_options.trace ? true : nil),
"data-dom-id" => render_options.dom_id)

load_pack_for_generated_component(react_component_name, render_options)
# Create the HTML rendering part
result = server_rendered_react_component(render_options)

load_pack_for_generated_component(react_component_name, render_options)

{
render_options: render_options,
tag: component_specification_tag,
Expand Down
5 changes: 3 additions & 2 deletions lib/react_on_rails/packs_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down Expand Up @@ -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"

Expand Down
2 changes: 2 additions & 0 deletions spec/dummy/client/app/packs/server-bundle.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down
11 changes: 11 additions & 0 deletions spec/dummy/spec/packs_generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down

0 comments on commit 1295ce9

Please sign in to comment.