react_on_rails 16.2.0.beta.10 → 16.2.0.beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -21
  3. data/CLAUDE.md +180 -5
  4. data/CONTRIBUTING.md +3 -1
  5. data/Gemfile.lock +1 -1
  6. data/Steepfile +4 -0
  7. data/analysis/rake-task-duplicate-analysis.md +149 -0
  8. data/analysis/v8-crash-retry-solution.md +148 -0
  9. data/bin/ci-run-failed-specs +6 -4
  10. data/bin/ci-switch-config +4 -3
  11. data/lib/generators/react_on_rails/base_generator.rb +2 -1
  12. data/lib/generators/react_on_rails/generator_helper.rb +29 -0
  13. data/lib/generators/react_on_rails/js_dependency_manager.rb +29 -7
  14. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt +19 -0
  15. data/lib/generators/react_on_rails/templates/base/base/config/{shakapacker.yml → shakapacker.yml.tt} +9 -0
  16. data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +38 -4
  17. data/lib/react_on_rails/configuration.rb +89 -10
  18. data/lib/react_on_rails/dev/pack_generator.rb +49 -11
  19. data/lib/react_on_rails/dev/server_manager.rb +1 -0
  20. data/lib/react_on_rails/doctor.rb +94 -4
  21. data/lib/react_on_rails/helper.rb +32 -5
  22. data/lib/react_on_rails/packs_generator.rb +47 -35
  23. data/lib/react_on_rails/system_checker.rb +7 -4
  24. data/lib/react_on_rails/utils.rb +54 -0
  25. data/lib/react_on_rails/version.rb +1 -1
  26. data/lib/tasks/generate_packs.rake +12 -6
  27. data/react_on_rails_pro/CHANGELOG.md +11 -4
  28. data/react_on_rails_pro/Gemfile.lock +3 -3
  29. data/react_on_rails_pro/app/helpers/react_on_rails_pro_helper.rb +2 -1
  30. data/react_on_rails_pro/lib/react_on_rails_pro/version.rb +1 -1
  31. data/react_on_rails_pro/package.json +1 -1
  32. data/react_on_rails_pro/spec/dummy/Gemfile.lock +3 -3
  33. data/react_on_rails_pro/spec/dummy/spec/helpers/react_on_rails_pro_helper_spec.rb +15 -7
  34. data/react_on_rails_pro/spec/dummy/spec/requests/renderer_console_logging_spec.rb +9 -4
  35. data/sig/react_on_rails/dev/file_manager.rbs +15 -0
  36. data/sig/react_on_rails/dev/pack_generator.rbs +19 -0
  37. data/sig/react_on_rails/dev/process_manager.rbs +22 -0
  38. data/sig/react_on_rails/dev/server_manager.rbs +39 -0
  39. metadata +9 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da10987e43490e2a8da60fccb2033038aa9fa6a9b5ccce9add3f9d0da795474c
4
- data.tar.gz: 9e7a3a46c8bb8e0fcc57142b5a1218ea58d5155d54614038d035e2e6b39fdf47
3
+ metadata.gz: 1f1f3592776a1d9cc69f832cdd3df34f4f1b696be6dd681d341614830d97a3d3
4
+ data.tar.gz: d7563d35d02ccd555be46984c21be8bf2cc9b9998d0ad70d0aefd4588940cda5
5
5
  SHA512:
6
- metadata.gz: d9f6d5be2b5bf2437adc711b6ac77e64fb7c6540d34bdce6380e98bf919872ec59e897b87869e25221f1f461ac91b25fc146c48701eb161630cb9bea7c44c7a1
7
- data.tar.gz: 5ec66977d53c808a8983277c6534e24fe966123105c4738e20995a9bb45be34a139030fe3e70ffe3251bb9961470371841bea040e558deb3fc974c154d6bdb7d
6
+ metadata.gz: b7284eb5e6ef0133546d405f441ae7c0f2099108353d7f6de9d9eff889c0d9d411c2952b37d98c905fb31dd4dc88cb7b3b8ef1dab5d12f6b5856c0172973d0b1
7
+ data.tar.gz: df238dcf4c71cd74547ff523c52974d752aa1bb53d53de50ec3d9c7227b3d55c4d96102c508561991dc41bba3aa3077eb5b3d81f1c08c0e53fa7ebff2ea1430c
data/CHANGELOG.md CHANGED
@@ -23,14 +23,20 @@ After a release, please make sure to run `bundle exec rake update_changelog`. Th
23
23
 
24
24
  Changes since the last non-beta release.
25
25
 
26
- #### Fixed
26
+ #### Added
27
27
 
28
- - **Duplicate Rake Task Execution**: Fixed rake tasks executing twice during asset precompilation and other rake operations. Rails Engine was loading task files twice: once via explicit `load` calls in the `rake_tasks` block (Railtie layer) and once via automatic file loading from `lib/tasks/` (Engine layer). This caused `react_on_rails:assets:webpack`, `react_on_rails:generate_packs`, and `react_on_rails:locale` tasks to run twice, significantly increasing build times. Removed explicit `load` calls and now rely on Rails Engine's standard auto-loading behavior. [PR 2052](https://github.com/shakacode/react_on_rails/pull/2052) by [justin808](https://github.com/justin808).
28
+ - **CSP Nonce Support for Console Replay**: Added Content Security Policy (CSP) nonce support for the `consoleReplay` script generated during server-side rendering. When Rails CSP is configured, the console replay script will automatically include the nonce attribute, allowing it to execute under restrictive CSP policies like `script-src: 'self'`. The implementation includes cross-version Rails compatibility (5.2-7.x) and defense-in-depth nonce sanitization to prevent attribute injection attacks. [PR 2059](https://github.com/shakacode/react_on_rails/pull/2059) by [justin808](https://github.com/justin808).
29
+
30
+ #### Bug Fixes
31
+
32
+ - [PR 2085](https://github.com/shakacode/react_on_rails/pull/2085) by [justin808](https://github.com/justin808): Fix pack generation in bin/dev when running from Bundler context. Pack generation was failing with "Could not find command 'react_on_rails:generate_packs'" because Bundler was intercepting the subprocess call. The fix wraps the bundle exec call with `Bundler.with_unbundled_env` to prevent interception.
29
33
 
30
- ### [v16.2.0.beta.8] - 2025-11-16
34
+ ### [v16.2.0.beta.11] - 2025-11-19
31
35
 
32
36
  #### Added
33
37
 
38
+ - **Shakapacker 9.0+ Private Output Path Integration**: Added automatic detection and integration of Shakapacker 9.0+ `private_output_path` configuration. React on Rails now automatically reads `private_output_path` from `shakapacker.yml` and sets server bundle paths, eliminating manual configuration synchronization. Includes version-aware generator templates, enhanced doctor command diagnostics for configuration validation and upgrade recommendations, and improved security with `enforce_private_server_bundles` option. [PR 2028](https://github.com/shakacode/react_on_rails/pull/2028) by [justin808](https://github.com/justin808).
39
+
34
40
  - **Rspack Support**: Added `--rspack` flag to `react_on_rails:install` generator for significantly faster builds (~20x improvement with SWC). Includes unified webpack/rspack configuration templates and `bin/switch-bundler` utility to switch between bundlers post-installation. [PR #1852](https://github.com/shakacode/react_on_rails/pull/1852) by [justin808](https://github.com/justin808).
35
41
 
36
42
  - **Attribution Comment**: Added HTML comment attribution to Rails views containing React on Rails functionality. The comment automatically displays which version is in use (open source React on Rails or React on Rails Pro) and, for Pro users, shows the license status. This helps identify React on Rails usage across your application. [PR #1857](https://github.com/shakacode/react_on_rails/pull/1857) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
@@ -41,8 +47,6 @@ Changes since the last non-beta release.
41
47
 
42
48
  - **Improved RSC Payload Error Handling**: Errors that happen during generation of RSC payload are transferred properly to rails side and logs the error message and stack. [PR #1888](https://github.com/shakacode/react_on_rails/pull/1888) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
43
49
 
44
- - **Use as Git dependency**: All packages can now be installed as Git dependencies. This is useful for development and testing purposes. See [CONTRIBUTING.md](./CONTRIBUTING.md#git-dependencies) for documentation. [PR #1873](https://github.com/shakacode/react_on_rails/pull/1873) by [alexeyr-ci2](https://github.com/alexeyr-ci2).
45
-
46
50
  - **Doctor Checks for :async Loading Strategy**: Added proactive diagnostic checks to the React on Rails doctor tool to detect usage of the `:async` loading strategy in projects without React on Rails Pro. The feature scans view files and initializer configuration, providing clear guidance to either upgrade to Pro or use alternative loading strategies like `:defer` or `:sync` to avoid component registration race conditions. [PR 2010](https://github.com/shakacode/react_on_rails/pull/2010) by [justin808](https://github.com/justin808).
47
51
 
48
52
  #### Changed
@@ -67,23 +71,13 @@ Changes since the last non-beta release.
67
71
 
68
72
  - **Simplified Configuration Files**: Improved configuration documentation and generator template for better clarity and usability. Reduced generator template from 67 to 42 lines (37% reduction). Added comprehensive testing configuration guide. Reorganized configuration docs into Essential vs Advanced sections. Enhanced Doctor program with diagnostics for server rendering and test compilation consistency. [PR #2011](https://github.com/shakacode/react_on_rails/pull/2011) by [justin808](https://github.com/justin808).
69
73
 
70
- #### Deprecated
71
-
72
- - **Node Renderer Configuration**: Renamed `bundlePath` configuration option to `serverBundleCachePath` in the node renderer to better describe its purpose and avoid confusion with Shakapacker's public bundle path. The old `bundlePath` option continues to work with deprecation warnings. Both `RENDERER_SERVER_BUNDLE_CACHE_PATH` (new) and `RENDERER_BUNDLE_PATH` (deprecated) environment variables are supported. [PR #2008](https://github.com/shakacode/react_on_rails/pull/2008) by [justin808](https://github.com/justin808).
73
-
74
74
  #### Fixed
75
75
 
76
- - **Node Renderer Worker Restart**: Fixed "descriptor closed" error that occurred when the node renderer restarts while handling an in-progress request (especially streaming requests). Workers now perform graceful shutdowns: they disconnect from the cluster to stop receiving new requests, wait for active requests to complete, then shut down cleanly. A configurable `gracefulWorkerRestartTimeout` ensures workers are forcibly killed if they don't shut down in time. [PR 1970](https://github.com/shakacode/react_on_rails/pull/1970) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
77
-
78
- - **Body Duplication Bug On Streaming**: Fixed a bug that happens while streaming if the node renderer connection closed after streaming some chunks to the client. [PR #1995](https://github.com/shakacode/react_on_rails/pull/1995) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
76
+ - **Doctor Command Version Mismatch Detection**: Fixed false version mismatch warnings in `rake react_on_rails:doctor` when using beta/prerelease versions. The command now correctly recognizes that gem version `16.2.0.beta.10` matches npm version `16.2.0-beta.10` using proper semver conversion instead of string normalization that stripped prerelease identifiers. [PR 2064](https://github.com/shakacode/react_on_rails/pull/2064) by [ihabadham](https://github.com/ihabadham).
79
77
 
80
- - **bin/dev --verbose Option**: Fixed `OptionParser::InvalidOption` error that occurred when using the `--verbose`/`-v` flag. The flag was documented in help text but not functional. Now properly implemented with flag parsing and passing verbose option through method calls. [PR 2023](https://github.com/shakacode/react_on_rails/pull/2023) by [justin808](https://github.com/justin808).
78
+ - **Rails 5.2-6.0 Compatibility**: Fixed compatibility with Rails 5.2-6.0 by adding polyfill for `compact_blank` method (introduced in Rails 6.1). Also refactored webpack asset handling to conditionally include React on Rails Pro files only when available, preventing NoMethodErrors in open-source installations. [PR 2058](https://github.com/shakacode/react_on_rails/pull/2058) by [justin808](https://github.com/justin808).
81
79
 
82
- - **Shakapacker Template Configuration**: Fixed shakapacker.yml template to prevent unnecessary "Slow setup for development" warnings by setting `compile: false` as the default configuration. This allows development environments to inherit the setting instead of forcing on-demand compilation when using Procfiles with `bin/dev` that already run the shakapacker dev server or watch mode. [PR 2021](https://github.com/shakacode/react_on_rails/pull/2021) by [justin808](https://github.com/justin808).
83
-
84
- #### Improved
85
-
86
- - **Concurrent Streaming Performance**: Implemented concurrent draining of streamed React components using the async gem. Instead of processing components sequentially, the system now uses a producer-consumer pattern with bounded buffering to allow multiple components to stream simultaneously while maintaining per-component chunk ordering. [PR 2015](https://github.com/shakacode/react_on_rails/pull/2015) by [ihabadham](https://github.com/ihabadham).
80
+ - **Duplicate Rake Task Execution**: Fixed rake tasks executing twice during asset precompilation and other rake operations. Rails Engine was loading task files twice: once via explicit `load` calls in the `rake_tasks` block (Railtie layer) and once via automatic file loading from `lib/tasks/` (Engine layer). This caused `react_on_rails:assets:webpack`, `react_on_rails:generate_packs`, and `react_on_rails:locale` tasks to run twice, significantly increasing build times. Removed explicit `load` calls and now rely on Rails Engine's standard auto-loading behavior. [PR 2052](https://github.com/shakacode/react_on_rails/pull/2052) by [justin808](https://github.com/justin808).
87
81
 
88
82
  #### Breaking Changes
89
83
 
@@ -1845,9 +1839,8 @@ such as:
1845
1839
 
1846
1840
  - Fix several generator-related issues.
1847
1841
 
1848
- [unreleased]: https://github.com/shakacode/react_on_rails/compare/v16.2.0.beta.8...master
1849
- [v16.2.0.beta.8]: https://github.com/shakacode/react_on_rails/compare/16.2.0.beta.4...v16.2.0.beta.8
1850
- [16.2.0.beta.4]: https://github.com/shakacode/react_on_rails/compare/16.1.1...16.2.0.beta.4
1842
+ [unreleased]: https://github.com/shakacode/react_on_rails/compare/v16.2.0.beta.11...master
1843
+ [v16.2.0.beta.11]: https://github.com/shakacode/react_on_rails/compare/16.1.1...v16.2.0.beta.11
1851
1844
  [16.1.1]: https://github.com/shakacode/react_on_rails/compare/16.1.0...16.1.1
1852
1845
  [16.1.0]: https://github.com/shakacode/react_on_rails/compare/16.0.0...16.1.0
1853
1846
  [16.0.0]: https://github.com/shakacode/react_on_rails/compare/14.2.0...16.0.0
data/CLAUDE.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
4
 
5
+ ## Project Structure Guidelines
6
+
7
+ ### Analysis Documents
8
+
9
+ When creating analysis documents (deep dives, investigations, historical context):
10
+ - **Location**: Place in `/analysis` directory
11
+ - **Format**: Use Markdown (.md)
12
+ - **Naming**: Use descriptive kebab-case names (e.g., `rake-task-duplicate-analysis.md`)
13
+ - **Purpose**: Keep detailed analyses separate from top-level project files
14
+
15
+ Examples:
16
+ - `/analysis/rake-task-duplicate-analysis.md` - Historical analysis of duplicate rake task bug
17
+ - `/analysis/feature-investigation.md` - Investigation of a specific feature or issue
18
+
19
+ Top-level documentation (like README.md, CONTRIBUTING.md) should remain at the root.
20
+
5
21
  ## ⚠️ CRITICAL REQUIREMENTS
6
22
 
7
23
  **BEFORE EVERY COMMIT/PUSH:**
@@ -178,13 +194,70 @@ cd react_on_rails_pro && bundle exec rake rbs:validate
178
194
  ```
179
195
  ## Changelog
180
196
 
197
+ **IMPORTANT: This is a monorepo with TWO separate changelogs:**
198
+ - **Open Source**: `/CHANGELOG.md` - for react_on_rails gem and npm package
199
+ - **Pro**: `/react_on_rails_pro/CHANGELOG.md` - for react_on_rails_pro gem and npm packages
200
+
201
+ When making changes, update the **appropriate changelog(s)**:
202
+ - Open-source features/fixes → Update `/CHANGELOG.md`
203
+ - Pro-only features/fixes → Update `/react_on_rails_pro/CHANGELOG.md`
204
+ - Changes affecting both → Update **BOTH** changelogs
205
+
206
+ ### Changelog Guidelines
207
+
181
208
  - **Update CHANGELOG.md for user-visible changes only** (features, bug fixes, breaking changes, deprecations, performance improvements)
182
209
  - **Do NOT add entries for**: linting, formatting, refactoring, tests, or documentation fixes
183
210
  - **Format**: `[PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username)` (no hash in PR number)
184
211
  - **Use `/update-changelog` command** for guided changelog updates with automatic formatting
185
- - **Version management**: Run `bundle exec rake update_changelog` after releases to update version headers
212
+ - **Version management after releases**:
213
+ - Open source: `bundle exec rake update_changelog`
214
+ - Pro: `cd react_on_rails_pro && bundle exec rake update_changelog`
186
215
  - **Examples**: Run `grep -A 3 "^#### " CHANGELOG.md | head -30` to see real formatting examples
187
216
 
217
+ ### Beta Release Changelog Curation
218
+
219
+ When consolidating beta versions into a stable release, carefully curate entries to include only user-facing changes:
220
+
221
+ **Remove these types of entries:**
222
+
223
+ 1. **Developer-only tooling**:
224
+ - yalc publish fixes (local development tool)
225
+ - Git dependency support (contributor workflow)
226
+ - CI/build script improvements
227
+ - Internal tooling changes
228
+
229
+ 2. **Beta-specific fixes**:
230
+ - Bugs introduced during the beta cycle (not present in last stable)
231
+ - Fixes for new beta-only features (e.g., bin/dev in 16.2.0.beta)
232
+ - Generator handling of beta/RC version formats
233
+
234
+ 3. **Pro-specific features** (move to Pro changelog):
235
+ - Node renderer fixes/improvements
236
+ - Streaming-related changes
237
+ - Async loading features (Pro-exclusive)
238
+
239
+ **Keep these types of entries:**
240
+
241
+ 1. **User-facing fixes**:
242
+ - Bugs that existed in previous stable release (e.g., 16.1.x)
243
+ - Compatibility fixes (Rails version support, etc.)
244
+ - Performance improvements affecting all users
245
+
246
+ 2. **Breaking changes**:
247
+ - API changes requiring migration
248
+ - Removed methods/features
249
+ - Configuration changes
250
+
251
+ **Investigation process:**
252
+
253
+ For each suspicious entry:
254
+ 1. Check git history: `git log --oneline <last_stable>..<current_beta> -- <file>`
255
+ 2. Determine when bug was introduced (stable vs beta cycle)
256
+ 3. Verify whether fix applies to stable users or only beta users
257
+ 4. Check PR description for context about what was broken
258
+
259
+ **Example reference:** See [PR #2072](https://github.com/shakacode/react_on_rails/pull/2072) for a complete example of beta changelog curation with detailed investigation notes.
260
+
188
261
  ## ⚠️ FORMATTING RULES
189
262
 
190
263
  **Prettier is the SOLE authority for formatting non-Ruby files, and RuboCop for formatting Ruby files. NEVER manually format code.**
@@ -198,12 +271,25 @@ cd react_on_rails_pro && bundle exec rake rbs:validate
198
271
  **CRITICAL**: When resolving merge conflicts, follow this exact sequence:
199
272
 
200
273
  1. **Resolve logical conflicts only** - don't worry about formatting
201
- 2. **Add resolved files**: `git add .` (or specific files)
202
- 3. **Auto-fix everything**: `rake autofix`
203
- 4. **Add any formatting changes**: `git add .`
204
- 5. **Continue rebase/merge**: `git rebase --continue` or `git commit`
274
+ 2. **VERIFY FILE PATHS** - if the conflict involved directory structure:
275
+ - Check if any hardcoded paths need updating
276
+ - Run: `grep -r "old/path" . --exclude-dir=node_modules`
277
+ - Pay special attention to package-scripts.yml, webpack configs, package.json
278
+ - **Test affected scripts:** If package-scripts.yml changed, run `yarn run prepack`
279
+ 3. **Add resolved files**: `git add .` (or specific files)
280
+ 4. **Auto-fix everything**: `rake autofix`
281
+ 5. **Add any formatting changes**: `git add .`
282
+ 6. **Continue rebase/merge**: `git rebase --continue` or `git commit`
283
+ 7. **TEST CRITICAL SCRIPTS if build configs changed:**
284
+ ```bash
285
+ yarn run prepack # Test prepack script
286
+ yarn run yalc.publish # Test yalc publish if package structure changed
287
+ rake run_rspec:gem # Run relevant test suites
288
+ ```
205
289
 
206
290
  **❌ NEVER manually format during conflict resolution** - this causes formatting wars between tools.
291
+ **❌ NEVER blindly accept path changes** - verify they're correct for current structure.
292
+ **❌ NEVER skip testing after resolving conflicts in build configs** - silent failures are dangerous.
207
293
 
208
294
  ### Debugging Formatting Issues
209
295
  - Check current formatting: `yarn start format.listDifferent`
@@ -223,6 +309,18 @@ cd react_on_rails_pro && bundle exec rake rbs:validate
223
309
  - **Gem-only tests**: `rake run_rspec:gem`
224
310
  - **All tests except examples**: `rake all_but_examples`
225
311
 
312
+ ## Testing Build and Package Scripts
313
+
314
+ @.claude/docs/testing-build-scripts.md
315
+
316
+ ## Master Branch Health Monitoring
317
+
318
+ @.claude/docs/master-health-monitoring.md
319
+
320
+ ## Managing File Paths in Configuration Files
321
+
322
+ @.claude/docs/managing-file-paths.md
323
+
226
324
  ## Project Architecture
227
325
 
228
326
  ### Monorepo Structure
@@ -504,6 +602,83 @@ Playwright E2E tests run automatically in CI via GitHub Actions (`.github/workfl
504
602
  - Uploads HTML reports as artifacts (available for 30 days)
505
603
  - Auto-starts Rails server before running tests
506
604
 
605
+ ## Rails Engine Development Nuances
606
+
607
+ React on Rails is a **Rails Engine**, which has important implications for development:
608
+
609
+ ### Automatic Rake Task Loading
610
+
611
+ **CRITICAL**: Rails::Engine automatically loads all `.rake` files from `lib/tasks/` directory. **DO NOT** use a `rake_tasks` block to explicitly load them, as this causes duplicate task execution.
612
+
613
+ ```ruby
614
+ # ❌ WRONG - Causes duplicate execution
615
+ module ReactOnRails
616
+ class Engine < ::Rails::Engine
617
+ rake_tasks do
618
+ load File.expand_path("../tasks/generate_packs.rake", __dir__)
619
+ load File.expand_path("../tasks/assets.rake", __dir__)
620
+ load File.expand_path("../tasks/locale.rake", __dir__)
621
+ end
622
+ end
623
+ end
624
+
625
+ # ✅ CORRECT - Rails::Engine loads lib/tasks/*.rake automatically
626
+ module ReactOnRails
627
+ class Engine < ::Rails::Engine
628
+ # Rake tasks are automatically loaded from lib/tasks/*.rake by Rails::Engine
629
+ # No explicit loading needed
630
+ end
631
+ end
632
+ ```
633
+
634
+ **When to use `rake_tasks` block:**
635
+ - Tasks are in a **non-standard location** (not `lib/tasks/`)
636
+ - You need to **programmatically generate** tasks
637
+ - You need to **pass context** to the tasks
638
+
639
+ **Historical Context**: PR #1770 added explicit rake task loading, causing webpack builds and pack generation to run twice during `rake assets:precompile`. This was fixed in PR #2052. See `analysis/rake-task-duplicate-analysis.md` for full details.
640
+
641
+ ### Engine Initializers and Hooks
642
+
643
+ Engines have specific initialization hooks that run at different times:
644
+
645
+ ```ruby
646
+ module ReactOnRails
647
+ class Engine < ::Rails::Engine
648
+ # Runs after Rails initializes but before routes are loaded
649
+ config.to_prepare do
650
+ ReactOnRails::ServerRenderingPool.reset_pool
651
+ end
652
+
653
+ # Runs during Rails initialization, use for validations
654
+ initializer "react_on_rails.validate_version" do
655
+ config.after_initialize do
656
+ # Validation logic here
657
+ end
658
+ end
659
+ end
660
+ end
661
+ ```
662
+
663
+ ### Engine vs Application Code
664
+
665
+ - **Engine code** (`lib/react_on_rails/`): Runs in the gem context, has limited access to host application
666
+ - **Host application code**: The Rails app that includes the gem
667
+ - **Generators** (`lib/generators/react_on_rails/`): Run in host app context during setup
668
+
669
+ ### Testing Engines
670
+
671
+ - **Dummy app** (`spec/dummy/`): Full Rails app for integration testing
672
+ - **Unit tests** (`spec/react_on_rails/`): Test gem code in isolation
673
+ - Always test both contexts: gem code alone and gem + host app integration
674
+
675
+ ### Common Pitfalls
676
+
677
+ 1. **Assuming host app structure**: Don't assume `app/javascript/` exists—it might not in older apps
678
+ 2. **Path resolution**: Use `Rails.root` for host app paths, not relative paths
679
+ 3. **Autoloading**: Engine code follows Rails autoloading rules but with a different load path
680
+ 4. **Configuration**: Engine config is separate from host app config—use `ReactOnRails.configure`
681
+
507
682
  ## IDE Configuration
508
683
 
509
684
  Exclude these directories to prevent IDE slowdowns:
data/CONTRIBUTING.md CHANGED
@@ -426,12 +426,14 @@ For more details, see [`docs/CI_OPTIMIZATION.md`](./docs/CI_OPTIMIZATION.md).
426
426
 
427
427
  React on Rails provides PR comment commands to control CI behavior:
428
428
 
429
- #### `/run-skipped-ci` - Enable Full CI Mode
429
+ #### `/run-skipped-ci` (or `/run-skipped-tests`) - Enable Full CI Mode
430
430
 
431
431
  Runs all skipped CI checks and enables full CI mode for the PR:
432
432
 
433
433
  ```
434
434
  /run-skipped-ci
435
+ # or use the shorter alias:
436
+ /run-skipped-tests
435
437
  ```
436
438
 
437
439
  **What it does:**
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- react_on_rails (16.2.0.beta.10)
4
+ react_on_rails (16.2.0.beta.12)
5
5
  addressable
6
6
  connection_pool
7
7
  execjs (~> 2.5)
data/Steepfile CHANGED
@@ -28,6 +28,10 @@ target :lib do
28
28
  check "lib/react_on_rails.rb"
29
29
  check "lib/react_on_rails/configuration.rb"
30
30
  check "lib/react_on_rails/controller.rb"
31
+ check "lib/react_on_rails/dev/file_manager.rb"
32
+ check "lib/react_on_rails/dev/pack_generator.rb"
33
+ check "lib/react_on_rails/dev/process_manager.rb"
34
+ check "lib/react_on_rails/dev/server_manager.rb"
31
35
  check "lib/react_on_rails/git_utils.rb"
32
36
  check "lib/react_on_rails/helper.rb"
33
37
  check "lib/react_on_rails/packer_utils.rb"
@@ -0,0 +1,149 @@
1
+ # Analysis: Why rake_tasks Block Was Added in PR #1770 and Caused Duplicate Execution
2
+
3
+ ## Summary
4
+
5
+ In PR #1770 (commit `8f3d178` - "Generator Overhaul & Developer Experience Enhancement"), Ihab added a `rake_tasks` block to `lib/react_on_rails/engine.rb` that explicitly loaded three rake task files. This was part of a **massive generator overhaul** that introduced new rake tasks for the file-system auto-registration feature. However, this caused those tasks to execute **twice** during operations like `rake assets:precompile`, which was fixed in PR #2052.
6
+
7
+ ## The Problem: Double Loading of Rake Tasks
8
+
9
+ ### What Was Added in PR #1770 (8f3d178)
10
+
11
+ ```ruby
12
+ # lib/react_on_rails/engine.rb
13
+ module ReactOnRails
14
+ class Engine < ::Rails::Engine
15
+ # ... existing code ...
16
+
17
+ rake_tasks do
18
+ load File.expand_path("../tasks/generate_packs.rake", __dir__)
19
+ load File.expand_path("../tasks/assets.rake", __dir__)
20
+ load File.expand_path("../tasks/locale.rake", __dir__)
21
+ end
22
+ end
23
+ end
24
+ ```
25
+
26
+ ### Why This Caused Duplicate Execution
27
+
28
+ Rails Engines have **two different mechanisms** for loading rake tasks, and this code inadvertently activated both:
29
+
30
+ 1. **Automatic Loading (Engine Layer)**: Rails::Engine automatically loads all `.rake` files from `lib/tasks/` directory
31
+ 2. **Manual Loading (Railtie Layer)**: The `rake_tasks` block explicitly loads specific files
32
+
33
+ Because the task files existed in `lib/tasks/`:
34
+
35
+ - `lib/tasks/assets.rake`
36
+ - `lib/tasks/generate_packs.rake`
37
+ - `lib/tasks/locale.rake`
38
+
39
+ They were being loaded **twice**:
40
+
41
+ - Once automatically by Rails::Engine from the `lib/tasks/` directory
42
+ - Once explicitly by the `rake_tasks` block
43
+
44
+ ## Why Was This Added in PR #1770?
45
+
46
+ PR #1770 was a **major overhaul** with 97 files changed. Looking at the context:
47
+
48
+ ### The Generator Overhaul Introduced:
49
+
50
+ 1. **File-system auto-registration**: New feature where components auto-register under `app/javascript/src/.../ror_components`
51
+ 2. **New `react_on_rails:generate_packs` rake task**: Critical new task for the auto-registration system
52
+ 3. **Enhanced dev tooling**: New `ReactOnRails::Dev` namespace with ServerManager, ProcessManager, PackGenerator
53
+ 4. **Shakapacker as required dependency**: Made Shakapacker mandatory (removed Webpacker support)
54
+
55
+ ### Why the Explicit Loading Was Added:
56
+
57
+ Based on the PR context and commit message, the most likely reasons:
58
+
59
+ 1. **Ensuring Critical Task Availability**: The `react_on_rails:generate_packs` task was brand new and absolutely critical to the file-system auto-registration feature. Ihab may have wanted to guarantee it would be loaded in all contexts.
60
+
61
+ 2. **Following Common Rails Engine Patterns**: The `rake_tasks` block is a well-documented pattern in Rails engines. Many gems use it explicitly, even when files are in `lib/tasks/`. Ihab likely followed this pattern as "best practice."
62
+
63
+ 3. **Massive PR Complexity**: With 97 files changed, this was a huge refactor. The `rake_tasks` block addition was a tiny part of the overall changes, and the duplicate loading issue was subtle enough that it wasn't caught during review.
64
+
65
+ 4. **Lack of Awareness About Automatic Loading**: Rails::Engine's automatic loading of `lib/tasks/*.rake` files is not as well-known as it should be. Many developers (even experienced ones) don't realize this happens automatically.
66
+
67
+ 5. **"Belt and Suspenders" Approach**: Given the criticality of the new auto-registration feature, Ihab may have intentionally added explicit loading as a safety measure, not realizing it would cause duplication.
68
+
69
+ **The commit message doesn't mention the rake_tasks addition at all**—it focuses on generator improvements, dev experience, and component architecture. This suggests the `rake_tasks` block was added as a routine implementation detail, not something Ihab thought needed explanation.
70
+
71
+ ## The Impact
72
+
73
+ Tasks affected by duplicate execution:
74
+
75
+ - `react_on_rails:assets:webpack` - Webpack builds ran twice
76
+ - `react_on_rails:generate_packs` - Pack generation ran twice
77
+ - `react_on_rails:locale` - Locale file generation ran twice
78
+
79
+ This meant:
80
+
81
+ - **2x build times** during asset precompilation
82
+ - **Slower CI** builds
83
+ - **Confusing console output** showing duplicate webpack compilation messages
84
+ - **Wasted resources** running the same expensive operations twice
85
+
86
+ ## The Fix (PR #2052)
87
+
88
+ The fix was simple—remove the redundant `rake_tasks` block and rely solely on Rails' automatic loading:
89
+
90
+ ```ruby
91
+ # lib/react_on_rails/engine.rb
92
+ module ReactOnRails
93
+ class Engine < ::Rails::Engine
94
+ # ... existing code ...
95
+
96
+ # Rake tasks are automatically loaded from lib/tasks/*.rake by Rails::Engine
97
+ # No need to explicitly load them here to avoid duplicate loading
98
+ end
99
+ end
100
+ ```
101
+
102
+ ## Key Lesson
103
+
104
+ **Rails::Engine Best Practice**: If your rake task files are in `lib/tasks/`, you don't need a `rake_tasks` block. Rails will load them automatically. Only use `rake_tasks do` if:
105
+
106
+ - Tasks are in a non-standard location
107
+ - You need to programmatically generate tasks
108
+ - You need to pass context to the tasks
109
+
110
+ ## Timeline
111
+
112
+ - **Sep 16, 2025** (PR #1770, commit 8f3d178): Ihab adds `rake_tasks` block as part of massive Generator Overhaul (97 files changed)
113
+ - **Nov 18, 2025** (PR #2052, commit 3f6df6be9): Justin discovers and fixes duplicate execution issue by removing the block (~2 months later)
114
+
115
+ ## What We Learned
116
+
117
+ ### For Code Reviews
118
+
119
+ This incident highlights the challenge of reviewing massive PRs:
120
+
121
+ - **97 files changed** made it nearly impossible to catch subtle issues
122
+ - The `rake_tasks` addition was 6 lines in a file that wasn't the focus of the PR
123
+ - The duplicate loading bug only manifested during asset precompilation, not during normal development
124
+ - Smaller, focused PRs would have made this easier to catch
125
+
126
+ ### For Testing
127
+
128
+ The duplicate execution bug was subtle:
129
+
130
+ - **Didn't cause failures**—just slower builds (2x time)
131
+ - **Hard to notice locally**—developers might not realize builds were taking twice as long
132
+ - **Only obvious in CI**—where build times are closely monitored
133
+ - **Needed production-like scenarios**—requires running `rake assets:precompile` to trigger
134
+
135
+ ### For Documentation
136
+
137
+ Better documentation of Rails::Engine automatic loading would help:
138
+
139
+ - Many Rails guides show `rake_tasks` blocks without mentioning automatic loading
140
+ - The Rails Engine guide doesn't clearly state when NOT to use `rake_tasks`
141
+ - This leads to cargo-culting of the pattern
142
+
143
+ ## References
144
+
145
+ - **Original PR**: [#1770 - "React on Rails Generator Overhaul & Developer Experience Enhancement"](https://github.com/shakacode/react_on_rails/pull/1770)
146
+ - **Original commit**: `8f3d178` - 97 files changed, massive refactor
147
+ - **Fix PR**: [#2052 - "Fix duplicate rake task execution by removing explicit task loading"](https://github.com/shakacode/react_on_rails/pull/2052)
148
+ - **Fix commit**: `3f6df6be9` - Simple 6-line removal
149
+ - **Rails Engine documentation**: https://guides.rubyonrails.org/engines.html#rake-tasks
@@ -0,0 +1,148 @@
1
+ # V8 Crash Retry Solution for CI
2
+
3
+ ## Problem
4
+
5
+ CI jobs occasionally fail with a transient V8 bytecode deserialization crash during the Node.js setup phase. The error manifests as:
6
+
7
+ ```
8
+ Fatal error in , line 0
9
+ Check failed: ReadSingleBytecodeData( source_.Get(), SlotAccessorForHandle<IsolateT>(&ret, isolate())) == 1.
10
+ ```
11
+
12
+ This error occurs during the `yarn cache dir` command execution within the `actions/setup-node@v4` action.
13
+
14
+ ## Root Cause
15
+
16
+ This is a known bug in Node.js/V8 that occurs sporadically:
17
+
18
+ - **Node.js Issue**: https://github.com/nodejs/node/issues/56010
19
+ - **Setup-node Issue**: https://github.com/actions/setup-node/issues/1028
20
+
21
+ The crash happens when V8 attempts to deserialize cached bytecode and encounters corrupted or incompatible data. It's a transient issue that typically resolves on retry.
22
+
23
+ ## Previous Workarounds
24
+
25
+ Before this fix, the codebase used two workarounds:
26
+
27
+ 1. **Completely disable yarn caching** in `examples.yml`:
28
+
29
+ ```yaml
30
+ # TODO: Re-enable yarn caching once Node.js V8 cache crash is fixed
31
+ # Tracking: https://github.com/actions/setup-node/issues/1028
32
+ # cache: yarn
33
+ # cache-dependency-path: '**/yarn.lock'
34
+ ```
35
+
36
+ 2. **Conditionally disable caching for Node 22** in `integration-tests.yml`:
37
+ ```yaml
38
+ cache: ${{ matrix.node-version != '22' && 'yarn' || '' }}
39
+ ```
40
+
41
+ Both workarounds significantly slowed down CI by preventing yarn dependency caching.
42
+
43
+ ## Solution
44
+
45
+ Created a custom composite GitHub action at `.github/actions/setup-node-with-retry/` that:
46
+
47
+ ### Key Features
48
+
49
+ 1. **Pre-validation**: Tests `yarn cache dir` works before running `setup-node`
50
+ 2. **Automatic retry**: Retries up to 3 times when V8 crashes are detected
51
+ 3. **Smart error detection**: Only retries on V8 crashes, fails fast on other errors
52
+ 4. **Clear diagnostics**: Provides warning annotations in CI logs
53
+ 5. **Configurable**: Allows customizing max retries (defaults to 3)
54
+ 6. **Backward compatible**: Drop-in replacement for `actions/setup-node@v4`
55
+
56
+ ### How It Works
57
+
58
+ ```yaml
59
+ - name: Setup Node.js with retry
60
+ shell: bash
61
+ run: |
62
+ # Pre-validate yarn cache dir works
63
+ if timeout 30 yarn cache dir > "$TEMP_OUTPUT" 2>&1; then
64
+ echo "Yarn cache dir command succeeded"
65
+ else
66
+ # Check for V8 crash signature
67
+ if grep -q "Fatal error in.*Check failed: ReadSingleBytecodeData" "$TEMP_OUTPUT"; then
68
+ echo "::warning::V8 bytecode deserialization error detected"
69
+ # Retry logic...
70
+ fi
71
+ fi
72
+
73
+ - name: Actually setup Node.js
74
+ uses: actions/setup-node@v4
75
+ # ... standard setup-node configuration
76
+ ```
77
+
78
+ ### Usage
79
+
80
+ ```yaml
81
+ - name: Setup Node
82
+ uses: ./.github/actions/setup-node-with-retry
83
+ with:
84
+ node-version: 22
85
+ cache: yarn
86
+ cache-dependency-path: '**/yarn.lock'
87
+ max-retries: 3 # Optional, defaults to 3
88
+ ```
89
+
90
+ ## Changes Made
91
+
92
+ Updated all 8 CI workflow files to use the new action:
93
+
94
+ 1. ✅ `examples.yml` - **Re-enabled yarn caching**
95
+ 2. ✅ `integration-tests.yml` - **Re-enabled yarn caching for Node 22**
96
+ 3. ✅ `lint-js-and-ruby.yml`
97
+ 4. ✅ `package-js-tests.yml`
98
+ 5. ✅ `playwright.yml`
99
+ 6. ✅ `pro-integration-tests.yml`
100
+ 7. ✅ `pro-lint.yml`
101
+ 8. ✅ `pro-test-package-and-gem.yml`
102
+
103
+ ## Benefits
104
+
105
+ 1. **Improved reliability**: CI no longer fails due to transient V8 crashes
106
+ 2. **Better performance**: Yarn caching re-enabled across all workflows
107
+ 3. **Clear diagnostics**: Warning annotations show when retries occur
108
+ 4. **Maintainable**: Centralized retry logic in a reusable action
109
+ 5. **Future-proof**: Can be updated independently if V8 crash patterns change
110
+
111
+ ## Monitoring
112
+
113
+ To verify the retry logic is working when V8 crashes occur:
114
+
115
+ 1. Watch CI logs for these warning messages:
116
+
117
+ ```
118
+ ::warning::V8 bytecode deserialization error detected (attempt 1/3)
119
+ Retrying in 5 seconds...
120
+ ```
121
+
122
+ 2. Check that jobs succeed after retry instead of failing
123
+
124
+ 3. If a job exhausts all retries, it will show:
125
+ ```
126
+ ::error::All 3 retry attempts failed
127
+ ```
128
+
129
+ ## Implementation Details
130
+
131
+ - **Timeout**: Each retry attempt has a 30-second timeout for `yarn cache dir`
132
+ - **Retry delay**: 5 seconds between attempts to allow transient issues to clear
133
+ - **Max retries**: Defaults to 3, configurable via input
134
+ - **Error detection**: Regex pattern matches V8 crash signature in stderr/stdout
135
+
136
+ ## Future Improvements
137
+
138
+ If the V8 crash persists even with retries, consider:
139
+
140
+ 1. Updating Node.js to a version with the fix (when available)
141
+ 2. Increasing max-retries for particularly flaky environments
142
+ 3. Adding exponential backoff between retries
143
+ 4. Implementing cache clearing before retry
144
+
145
+ ## Pull Request
146
+
147
+ - **PR**: https://github.com/shakacode/react_on_rails/pull/2082
148
+ - **Branch**: `jg-/ci-retry-v8-crash`