Skip to content

Commit

Permalink
Improve auto-bundling logic (shakacode#1531)
Browse files Browse the repository at this point in the history
* Add bundler to improve CI gem caching

* rails => rake

* add missing generated entrypoints

* remove obsolete rake logic

* get packs_generator_spec to pass

* improve auto-load functionality

* fix for CI error message truncation

* update main github workflow

* bundler 2.4.9 for lint workflow

* update webdrivers & selenium-webdriver

* stop deferral of generated component packs
  • Loading branch information
Judahmeek authored May 2, 2023
1 parent e20b8da commit e0d5d0e
Show file tree
Hide file tree
Showing 28 changed files with 209 additions and 224 deletions.
9 changes: 5 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# CircleCI is not longer in use by this repository & this file is now for reference only.
version: 2

aliases:
Expand Down Expand Up @@ -53,15 +54,15 @@ aliases:
- &install-dummy-app-ruby-gems
name: Install Ruby Gems for dummy app
command: |
gem install bundler
gem install bundler:2.4.9
echo "Bundler version: "; bundle --version
cd spec/dummy && bundle lock --add-platform 'x86_64-linux' && bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
# Install ruby gems unless existing set of gems is satisfying bundler.
- &install-package-ruby-gems
name: Install Ruby Gems for package
command: |
gem install bundler
gem install bundler:2.4.9
echo "Bundler version: "; bundle --version
bundle lock --add-platform 'x86_64-linux'
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
Expand Down Expand Up @@ -272,12 +273,12 @@ jobs:
name: Prep for CI
# TODO -- need to leverage Circle CI containers
command: |
bundle exec rails prepare_for_ci
bundle exec rake prepare_for_ci
- run:
name: Main CI
# TODO -- need to leverage Circle CI containers
command: |
bundle exec rails run_rspec:all_dummy
bundle exec rake run_rspec:all_dummy
# The following step will run only if the main job is finished successfully.
# Build hook is triggered by curl command described here https://docs.netlify.com/configure-builds/build-hooks/
# NETLIFY_HOOK is an environment variable on CircleCI to keep sensitive data outside the repo
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/lint-js-and-ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler: 2.4.9
- name: Setup Node
uses: actions/setup-node@v2-beta
with:
Expand Down Expand Up @@ -44,7 +45,7 @@ jobs:
yarn run eslint -v
sudo yarn global add yalc
- name: Install Ruby Gems for package
run: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
run: bundle check --path=vendor/bundle || bundle _2.4.9_ install --path=vendor/bundle --jobs=4 --retry=3
- name: Linting of Ruby
run: bundle exec rubocop
- name: Linting of JS
Expand Down
37 changes: 18 additions & 19 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Main test

on: [push, pull_request]
on: [push]

jobs:
build-dummy-app-webpack-test-bundles:
Expand All @@ -15,6 +15,7 @@ jobs:
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler: 2.4.9
# libyaml-dev is needed for psych v5
# this gem depends on sdoc which depends on rdoc which depends on psych
- name: Fix dependency for libyaml-dev
Expand All @@ -33,7 +34,7 @@ jobs:
echo "Yarn version: "; yarn --version
echo "Bundler version: "; bundle --version
- name: Save root node_modules to cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: node_modules
key: v5-package-node-modules-cache-${{ hashFiles('yarn.lock') }}
Expand All @@ -45,7 +46,7 @@ jobs:
- name: yalc publish for react-on-rails
run: yalc publish
- name: Save spec/dummy/node_modules to cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: spec/dummy/node_modules
key: v5-dummy-app-node-modules-cache-${{ hashFiles('spec/dummy/yarn.lock') }}
Expand All @@ -54,20 +55,20 @@ jobs:
- name: Install Node modules with Yarn for dummy app
run: cd spec/dummy && yarn install --no-progress --no-emoji
- name: Save dummy app ruby gems to cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: spec/dummy/vendor/bundle
key: v5-dummy-app-gem-cache-${{ hashFiles('spec/dummy/Gemfile.lock') }}
- name: Install Ruby Gems for dummy app
run: cd spec/dummy && bundle lock --add-platform 'x86_64-linux' && bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
run: cd spec/dummy && bundle lock --add-platform 'x86_64-linux' && bundle check --path=vendor/bundle || bundle _2.4.9_ install --path=vendor/bundle --jobs=4 --retry=3
- name: generate file system-based packs
run: cd spec/dummy && RAILS_ENV=test bundle exec rake react_on_rails:generate_packs
- name: Build test bundles for dummy app
run: cd spec/dummy && yarn run build:test
- id: get-sha
run: echo "::set-output name=sha::$(git rev-parse HEAD)"
- name: Save test webpack bundles to cache (for build number checksum used by rspec job)
uses: actions/cache@v2
uses: actions/cache/save@v3
with:
path: spec/dummy/public/webpack
key: v5-dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}
Expand All @@ -78,14 +79,15 @@ jobs:
matrix:
ruby: [2.7]
node: [14]
rake_task: ['run_rspec:all_dummy', 'run_rspec:all_but_examples', 'run_rspec:examples']
rake_task: ['run_rspec:all_but_examples', 'run_rspec:examples']
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler: 2.4.9
- name: Setup Node
uses: actions/setup-node@v2-beta
with:
Expand All @@ -100,33 +102,32 @@ jobs:
echo "Yarn version: "; yarn --version
echo "Bundler version: "; bundle --version
- name: Save root node_modules to cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: node_modules
key: v5-package-node-modules-cache-${{ hashFiles('yarn.lock') }}
- name: Save root ruby gems to cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: vendor/bundle
key: v5-package-app-gem-cache-${{ hashFiles('react_on_rails.gemspec') }}
- name: Save dummy app ruby gems to cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: spec/dummy/vendor/bundle
key: v5-dummy-app-gem-cache-${{ hashFiles('spec/dummy/Gemfile.lock') }}
- name: Save spec/dummy/node_modules to cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: spec/dummy/node_modules
key: v5-dummy-app-node-modules-cache-${{ hashFiles('spec/dummy/yarn.lock') }}
- id: get-sha
run: echo "::set-output name=sha::$(git rev-parse HEAD)"
- name: Save test webpack bundles to cache (for build number checksum used by rspec job)
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: spec/dummy/public/webpack
key: v5-dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}

- name: Install Node modules with Yarn for renderer package
run: |
yarn install --no-progress --no-emoji
Expand All @@ -139,7 +140,7 @@ jobs:
- name: Install Ruby Gems for package
run: bundle lock --add-platform 'x86_64-linux' && bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
- name: Install Ruby Gems for dummy app
run: cd spec/dummy && bundle lock --add-platform 'x86_64-linux' && bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
run: cd spec/dummy && bundle lock --add-platform 'x86_64-linux' && bundle check --path=vendor/bundle || bundle _2.4.9_ install --path=vendor/bundle --jobs=4 --retry=3
- name: Ensure minimum required Chrome version
run: |
echo -e "Already installed $(google-chrome --version)\n"
Expand All @@ -152,16 +153,14 @@ jobs:
sudo apt-get install google-chrome-stable
echo -e "\nInstalled $(google-chrome --version)"
fi
- name: Touch webpack bundles
run: touch spec/dummy/public/webpack/test/*
- name: Install yalc globally
run: sudo yarn global add yalc
- name: Increase the amount of inotify watchers
run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
- name: Prep for CI
run: bundle exec rails prepare_for_ci
- name: generate file system-based packs
run: cd spec/dummy && RAILS_ENV=test bundle exec rake react_on_rails:generate_packs
- name: Main CI
run: bundle exec rails ${{ matrix.rake_task }}
run: bundle exec rake ${{ matrix.rake_task }}
- name: Store test results
uses: actions/upload-artifact@v2
with:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/rspec-package-specs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler: 2.4.9
- name: Print system information
run: |
echo "Linux release: "; cat /etc/issue
Expand Down
4 changes: 3 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package.json
tmp/
coverage/
**/app/assets/webpack/
spec/dummy/public
gen-examples/examples/*
node_package/lib/*
spec/react_on_rails/dummy-for-generators/app/javascript/bundles/HelloWorld/*
bundle/
spec/dummy/lib/bs/**
spec/dummy/public
**/.yalc/**
**/generated/**
*.bs.js
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ Changes since last non-beta release.

*Please add entries here for your pull requests that are not yet released.*

### Added
- Improved functionality of Filesystem-based pack generation & auto-bundling. Added `make_generated_server_bundle_the_entrypoint` configuration key. [PR 1531](https://github.com/shakacode/react_on_rails/pull/1531) by [judahmeek](https://github.com/judahmeek)

### [13.3.3] - 2022-03-21

### Fixed
Expand Down
3 changes: 2 additions & 1 deletion Gemfile.development_dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ gem "sass-rails", "~> 6.0"
gem "uglifier"
gem "jquery-rails"
gem "puma", "~> 5.0"
gem "bundler", "2.4.9"

# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem "turbolinks" if ENV["DISABLE_TURBOLINKS"].nil? || ENV["DISABLE_TURBOLINKS"].strip.empty?
Expand Down Expand Up @@ -46,5 +47,5 @@ group :test do
gem "rspec-rails"
gem "rspec-retry"
gem "selenium-webdriver"
gem "webdrivers", "3.9.4"
gem "webdrivers"
end
14 changes: 12 additions & 2 deletions docs/guides/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,21 @@ ReactOnRails.configure do |config|
# Change to a value like this example to enable this feature
# config.components_subdirectory = "ror_components"

# Default configuration to auto loading bundles for components.
# default is false. The default can be overrident as an option in calls to view helpers
# Default is false.
# The default can be overidden as an option in calls to view helpers
# `render_component` and `render_component_hash`. You may set to true to change the default to auto loading.
config.auto_load_bundle = false

# Default is false
# Set this to true & instead of trying to import the generated server components into your existing
# server bundle entrypoint, the PacksGenerator will create a server bundle entrypoint using
# config.server_bundle_js_file for the filename.
config.make_generated_server_bundle_the_entrypoint = false

# Default is true, which matches Webpacker/Shakapacker's defer default for `append_javascript_pack`
# Set this to false to have `defer: false` added to your `append_javascript_pack` calls for generated entrypoints.
config.defer_generated_component_packs = true

################################################################################
# I18N OPTIONS
################################################################################
Expand Down
35 changes: 24 additions & 11 deletions docs/guides/file-system-based-automated-bundle-generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Your layout would contain:
<%= stylesheet_pack_tag 'application' %>
```

Suppose, you want to use bundle splitting to minimize unnecessary javascript loaded on each page, you would put each of your components in the `packs` directory.
Now suppose you want to use bundle splitting to minimize unnecessary javascript loaded on each page, you would put each of your components in the `packs` directory.

```
app/javascript:
Expand All @@ -124,23 +124,26 @@ The tricky part is to figure out which bundles to load on any Rails view. [Shaka

#### Solution

File-system-based automated pack generation simplifies this process with a new option for the view helpers. The steps to use it in this example are:
File-system-based automated pack generation simplifies this process with a new option for the view helpers.

1. Remove parameters passed directly to `javascript_pack_tag` and `stylesheet_pack_tag`.
2. Remove parameters passed directly to `append_javascript_pack_tag` and `append_stylesheet_pack_tag`.
For example, if you wanted to utilize our file-system based entrypoint generation for `FooComponentOne` & `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`.

Your layout would now contain:

```erb
<%= javascript_pack_tag %>
<%= stylesheet_pack_tag %>
<%= javascript_pack_tag('BarComponentTwo') %>
<%= stylesheet_pack_tag('BarComponentTwo') %>
```

3. Create a directory structure as mentioned below:
3. Create a directory structure where the components that you want to be auto-generated are within `ReactOnRails.configuration.components_subdirectory`, which should be a subdirectory of `Shakapacker.config.source_path`:

```
app/javascript:
└── packs
└── packs:
│ └── BarComponentTwo.jsx # Internally uses ReactOnRails.register
└── src:
│ └── Foo
│ │ └── ...
Expand All @@ -150,18 +153,20 @@ app/javascript:
│ │ └── ...
│ │ └── ror_components # configured as `components_subdirectory`
│ │ │ └── BarComponentOne.jsx
│ │ └── something_else
│ │ │ └── BarComponentTwo.jsx
```

4. You no longer need to register these React components nor directly add their bundles. For example you can have a Rails view using three components:
4. You no longer need to register the React components within the `ReactOnRails.configuration.components_subdirectory` nor directly add their bundles. For example you can have a Rails view using three components:

```erb
<% append_javascript_pack('BarComponentTwo'))>
<%= react_component("FooComponentOne", {}, auto_load_bundle: true) %>
<%= react_component("BarComponentOne", {}, auto_load_bundle: true) %>
<%= react_component("BarComponentTwo", {}, auto_load_bundle: true) %>
<%= react_component("BarComponentTwo", {}) %>
```

If `FooComponentOne` uses multiple HTML strings for server rendering, the [`react_component_hash`](https://www.shakacode.com/react-on-rails/docs/api/view-helpers-api/#react_component_hash) view helper can be used on the Rails view, as illustrated below.
If a component uses multiple HTML strings for server rendering, the [`react_component_hash`](https://www.shakacode.com/react-on-rails/docs/api/view-helpers-api/#react_component_hash) view helper can be used on the Rails view, as illustrated below.

```erb
<% foo_component_one_data = react_component_hash("FooComponentOne",
Expand All @@ -185,6 +190,14 @@ Once generated, all server entrypoints will be imported into a file named `[Reac

*Note: If specifying separate definitions for client and server rendering, please make sure to delete the generalized `ComponentName.jsx` file.*

### Integrating auto-bundling into CI workflows

Currently, ReactOnRails contains conditional logic that checks for the existence of generated entrypoint files whenever `react_component` or one of its derivative methods are called. If a generated entrypoint of the same name as provided to `react_component` or `react_component_hash` exists, then an `append_javascript_pack` call is made automatically.

This means that `rake react_on_rails:generate_packs` or its programmatic equivalent must be run as a prerequisite to any sort of test or spec that would result in `react_component` or `react_component_hash` being called, even if the generated entrypoint files have already been bundled in a previous workflow/job.

Caching of the generated entrypoints between workflow/jobs should also resolve this issue.

### Using Automated Bundle Generation Feature with already defined packs

To use the Automated Bundle Generation feature with already defined packs, `config/initializers/react_on_rails` should explicitly be configured with `config.auto_load_bundle = false` and you can explicitly pass `auto_load_bundle` option in [`react_component`](https://www.shakacode.com/react-on-rails/docs/api/view-helpers-api/#react_component) and [`react_component_hash`](https://www.shakacode.com/react-on-rails/docs/api/view-helpers-api/#react_component_hash) for the components using this feature.
Expand Down
Loading

0 comments on commit e0d5d0e

Please sign in to comment.