Skip to content

Conversation

@justin808
Copy link
Member

@justin808 justin808 commented Nov 2, 2025

Summary

This PR upgrades Shakapacker from 9.2.0 to 9.3.0 and includes all necessary compatibility fixes and configuration updates.

Key Changes

Shakapacker Version Update

  • Updated shakapacker gem dependency to 9.3.0 across all Gemfiles
  • Updated yarn.lock files for dummy apps and Pro package
  • Updated execjs-compatible-dummy yarn.lock

SWC Compiler Support

  • Added swc-loader support for Shakapacker 9.3.0
  • Updated using_swc? helper to properly parse shakapacker.yml
  • Set SWC as default for Shakapacker 9.3.0+
  • Moved swc-loader and @swc/core to devDependencies

CSS Modules Compatibility

  • Fixed CSS Modules compatibility with Shakapacker 9.0.0+
  • Configured CSS Modules to use default exports (namedExport: false)
  • Maintained backward compatibility with existing import patterns

Generator Improvements

  • Fixed generator robustness: package manager detection, validation skip
  • Improved webpack safety checks
  • Fixed generator test failures with proper validation skipping
  • Added exact version specifications where needed

Build & CI Fixes

  • Fixed SCSS undefined variable errors by importing app-variables
  • Removed redundant SCSS @import statements
  • Fixed prepack scripts to use yarn instead of npm
  • Fixed CI frozen-lockfile errors with yalc workflow
  • Added ReScript build step before development server starts

Documentation & Testing

  • Added issue documentation for Playwright Turbo navigation regression test
  • Fixed code fence language specifiers
  • Updated PR placeholders with actual PR numbers

Testing

  • ✅ All generator tests passing
  • ✅ CSS Modules working correctly
  • ✅ SWC compilation functional
  • ✅ Dummy apps building successfully
  • ✅ Pro package tests passing
  • ✅ CI workflows updated and passing

Breaking Changes

None - this upgrade maintains backward compatibility while adding new features.

Migration Notes

For projects upgrading to Shakapacker 9.3.0:

  1. Update shakapacker gem to 9.3.0 in Gemfile
  2. Run bundle install
  3. Run yarn upgrade [email protected]
  4. SWC will be used by default (can opt-out in shakapacker.yml)

Related PRs

🤖 Generated with Claude Code


This change is Reviewable

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 2, 2025

Walkthrough

This PR upgrades Shakapacker from 8.2.0 to 9.3.0, integrates SWC compiler support with conditional dependency detection via configuration parsing, implements React 19 compatibility using named imports in TypeScript/React files, updates generators with package-manager-driven installation logic, adds @swc/core and swc-loader to dummy project dependencies, enhances CI workflows with yalc publishing steps, and provides comprehensive upgrade documentation.

Changes

Cohort / File(s) Summary
Shakapacker Version Bumps
Gemfile.development_dependencies, script/convert, rakelib/shakapacker_examples.rake, react_on_rails_pro/spec/execjs-compatible-dummy/Gemfile, react_on_rails_pro/spec/dummy/package.json
Version constraints updated from 8.2.0/8.0 to 9.3.0 across development and test dependencies; includes version substitution logic in script/convert and Rakefile generator.
SWC Compiler Dependencies
spec/dummy/package.json, react_on_rails_pro/spec/dummy/package.json, react_on_rails_pro/spec/execjs-compatible-dummy/package.json
Added devDependencies: `@swc/core` "^1.7.0" and `swc-loader` "^0.2.6" to multiple dummy and test package configurations.
React 19 Named Import Compatibility
packages/react-on-rails-pro/src/RSCProvider.tsx, packages/react-on-rails-pro/src/RSCRoute.tsx
Replaced wildcard React imports with named imports; updated type signatures from `React.ReactNode` to `ReactNode`; added `'use client'` directive update in RSCProvider.
Server Component Directive Removal
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/{AsyncOnServerSyncOnClient,LazyApolloGraphQLApp,ServerComponentRouter}.server.tsx
Removed `'use client'` directive from three server-side component files, converting them from client to server components.
Generator SWC Detection & Package Manager Logic
lib/generators/react_on_rails/base_generator.rb, lib/generators/react_on_rails/generator_helper.rb, lib/generators/react_on_rails/install_generator.rb
Implemented conditional SWC detection via config parsing, added package-manager detection across lock files (yarn.lock, pnpm-lock.yaml, bun.lockb, package-lock.json), centralized installation calls using detected package manager with exact flags.
Shakapacker Configuration Templates
lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
Added `precompile_hook` configuration; introduced commented `javascript_compiler` option (SWC alternative); removed legacy `webpack_loader` setting.
CI Workflow Updates
.github/workflows/lint-js-and-ruby.yml, .github/workflows/pro-integration-tests.yml
Added yalc publish/build steps in pro-integration-tests; updated knip linting with `--no-config-hints` flag; modified Node modules installation to use `--ignore-scripts --no-progress --no-emoji`.
SCSS Module Imports
spec/dummy/client/app/components/HelloWorld.module.scss, react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss
Added import of app-variables.scss to bring SCSS variables into scope in module files.
Pack Generation System Invocation
lib/react_on_rails/dev/pack_generator.rb
Updated bundle exec rake invocation from multi-argument array to single-string system call; behavior preserved.
Capybara Test Dependency
Gemfile.development_dependencies
Added version constraint to capybara from unversioned gem to `">=3.40"`.
ESLint Configuration & Custom Rules
eslint.config.ts, eslint-rules/README.md
Moved `no-use-client-in-server-files` ESLint rule from file-specific block to top-level plugin configuration with error severity; added comprehensive rule documentation.
Build Script Updates
package-scripts.yml
Changed prepack build command from `npm run build` to `yarn run build` in conditional logic.
Upgrade Documentation
docs/upgrading/react-19-upgrade-guide.md, docs/upgrading/react-19-quick-reference.md, docs/upgrading/upgrading-react-on-rails.md, TURBO_NAVIGATION_TEST_ISSUE.md, SHAKAPACKER_UPGRADE_PR_PLAN.md, PR_SUMMARY_REACT_19_FIX.md
Added comprehensive React 19 upgrade guides (including breaking changes, TypeScript config, import patterns), Shakapacker 9 migration planning document, Turbo navigation regression test specification, and React 19 fix summary.

Sequence Diagram(s)

sequenceDiagram
    participant Gen as Generator
    participant DetectPM as detect_package_manager_and_exact_flag
    participant FileSystem as Project Root
    participant PkgMgr as Package Manager

    Gen->>DetectPM: Check for lock files
    DetectPM->>FileSystem: Scan for yarn.lock
    DetectPM->>FileSystem: Scan for pnpm-lock.yaml
    DetectPM->>FileSystem: Scan for bun.lockb
    DetectPM->>FileSystem: Scan for package-lock.json
    
    alt Multiple lock files found
        DetectPM->>Gen: Warn about precedence
    end
    
    alt At least one lock file found
        DetectPM->>Gen: Return [package_manager, exact_flag, add_command]
    else No lock files found
        DetectPM->>Gen: Return ["npm", "--save-exact", "install"]
    end
    
    Gen->>PkgMgr: Install dependencies using detected manager
Loading
sequenceDiagram
    participant Gen as BaseGenerator
    participant Config as Config File (shakapacker.yml)
    participant YAML as YAML Parser
    participant Helper as Helper Method

    Gen->>Helper: Call using_swc?
    Helper->>Config: Read default.javascript_compiler
    
    alt File exists and parses
        YAML->>Helper: Parse YAML
        Helper->>Helper: Check if == "swc"
    else File missing or parse error
        Helper->>Gen: Log warning, default to false (Babel)
    end
    
    Gen->>Gen: Conditionally add SWC deps (`@swc/core`, swc-loader)
    Gen->>Gen: Or add Babel deps (`@babel/preset-react`, etc.)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Core generator logic changes (lib/generators/react_on_rails/base_generator.rb, install_generator.rb, generator_helper.rb): Multiple new public methods, conditional dependency logic, YAML parsing with error handling
  • React 19 TypeScript compatibility (packages/react-on-rails-pro/src/*.tsx): Public API signature changes across RSC Provider and Route components; type cascading effects
  • Version bumps across heterogeneous contexts: Shakapacker updates in Gemfiles, package.json files, and Rake generators require context verification
  • ESLint rule relocation: Moving rule from file-specific to top-level scope changes enforcement behavior globally
  • CI workflow restructuring: yalc publishing step additions and Node modules install flag changes affect build/publish flow
  • Documentation scope: Large addition of upgrade guides and migration planning docs requires verification against actual codebase changes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • Judahmeek
  • AbanoubGhadban
  • alexeyr-ci

Poem

🐰 Shakapacker leaps from eight to nine,
SWC compiles in record time,
React nineteen's imports align,
While yalc publishes—all divine!
Our generators now detect with flair,
Package managers beyond compare!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'Upgrade Shakapacker to 9.3.0' clearly and concisely summarizes the main change—upgrading the Shakapacker dependency version from 8.2.0 to 9.3.0, which is reflected throughout the changeset.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch justin808/shakapacker-9.3.0

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link

claude bot commented Nov 2, 2025

Code Review: Update shakapacker to 9.3.0

Summary

This PR updates shakapacker from version 8.2.0 to 9.3.0 across the codebase. Overall, this is a well-executed dependency update with comprehensive test coverage updates. The changes are consistent and follow the project's conventions.

✅ Strengths

  1. Comprehensive Coverage: All relevant files have been updated consistently (Gemfiles, lockfiles, package.json, test specs, conversion scripts, rake tasks)

  2. Test Coverage: The PR properly updates test expectations in spec/react_on_rails/packer_utils_spec.rb to match the new version requirement.

  3. Follows Project Guidelines: Author mentions running RuboCop and git hooks, proper formatting maintained

  4. Dependency Updates: Both Gemfile.lock and yarn.lock properly updated with new version and transitive dependencies.

⚠️ Issues Found - Action Required

CRITICAL: Multiple references to version 8.2.0 were NOT updated in this PR but should be:

1. Documentation Files (Should be updated)

  • docs/api-reference/configuration.md:240, 247, 271, 272
  • docs/pro/major-performance-breakthroughs-upgrade-guide.md:94
  • docs/upgrading/release-notes/16.0.0.md:49, 51, 59, 90

2. Source Code Files (Should be updated)

  • lib/react_on_rails/configuration.rb:180
  • lib/react_on_rails/doctor.rb:716

3. Test Files (Should be reviewed/updated)

  • spec/react_on_rails/configuration_spec.rb:281, 284, 328, 331
  • spec/lib/react_on_rails/system_checker_spec.rb:165, 173

🤔 Questions

  1. Breaking Changes: What changed between 8.2.0 and 9.3.0? Have these been tested?

  2. Async Loading Requirement: Why does supports_async_loading? now require 9.3.0 instead of 8.2.0? This is significant and should be documented.

  3. Backwards Compatibility: Can users on 8.2.0 still use earlier react_on_rails versions?

📋 Recommendations

High Priority:

  1. Update all documentation to reference 9.3.0
  2. Update error/info messages in source code
  3. Update test specs for consistency
  4. Add CHANGELOG entry with migration guidance

Medium Priority:
5. Verify CI passes completely
6. Test with example apps
7. Document why 9.3.0 is now required

Code Quality Score: 7/10

Great work on the thorough dependency update! Just needs the additional reference updates for completeness.

@claude
Copy link

claude bot commented Nov 2, 2025

Code Review: Update shakapacker to 9.3.0

Overall Assessment

APPROVED - This is a well-executed dependency update with proper version management and good backward compatibility considerations.


Strengths

1. Excellent Version Strategy 🎯

The second commit demonstrates excellent understanding of semantic versioning:

  • Correctly keeps supports_async_loading? check at 8.2.0 (when feature was introduced)
  • Allows users on any version >= 8.2.0 to use async loading
  • Prevents forcing users to upgrade unnecessarily

Code reference: lib/react_on_rails/packer_utils.rb:36

2. Comprehensive Update Coverage ✅

All necessary files were updated:

  • Development dependencies (Gemfile)
  • Test fixtures (spec/dummy/)
  • Rake tasks for example generation
  • Conversion scripts
  • Lock files properly regenerated

3. Good Testing Hygiene 🧪

  • Tests correctly validate the version check stays at 8.2.0
  • Version constants remain properly defined
  • Test coverage remains intact

Observations & Recommendations

1. Missing CHANGELOG Entry 📝

Issue: No update to CHANGELOG.md for this version bump

Recommendation: Add an entry documenting this upgrade, especially noting:

  • Shakapacker upgraded from 8.2.0 to 9.3.0
  • Backward compatibility maintained for async loading (8.2.0+)
  • Any new features from Shakapacker 9.x that users can leverage

2. Dependency Updates in yarn.lock 🔍

Observation: The update introduces new dependencies:

Question: Have these been tested for compatibility? The new dependencies appear to be internal Shakapacker requirements, which should be fine, but worth verifying CI passes.

3. Generated Examples Version Constraint ⚠️

Code: rakelib/shakapacker_examples.rake:37

Concern: This forces generated examples to require >= 9.3.0, which may be stricter than necessary.

Question: Should this be >= 8.2.0 or >= 7.0.0 to align with actual minimum version requirements (MINIMUM_SHAKAPACKER_VERSION_FOR_AUTO_BUNDLING = 7.0.0)?

Impact: Users generating new examples will be forced to use 9.3.0+, even if their actual requirements are lower.

4. Documentation Updates 📖

Files that likely reference version requirements and may need updates:

  • docs/upgrading/release-notes/ - Should document this change
  • docs/api-reference/configuration.md - May reference minimum versions
  • README/Getting Started guides - If they mention specific Shakapacker versions

5. Breaking Changes from Shakapacker? 🔍

Recommendation: Verify the Shakapacker 8.2.0 → 9.3.0 upgrade doesn't introduce breaking changes that affect react_on_rails users. The major version bump (8→9) suggests potential breaking changes.


Security Considerations

✅ No security concerns identified:

  • Upgrading to latest stable dependency version
  • No new suspicious dependencies
  • All changes are version bumps of existing, trusted packages

Performance Considerations

✅ No performance concerns:

  • Dependency updates should be neutral or positive for performance
  • No algorithmic changes in the codebase
  • Lock file properly regenerated to ensure consistent installs

Testing Recommendations

  1. Run Full Test Suite: Ensure all tests pass with the new version
  2. Test Generated Examples: Verify rake shakapacker_examples:gen_all works correctly
  3. Integration Testing: Test with a real app using different Shakapacker versions (8.2.0, 9.0.0, 9.3.0)
  4. SSR Testing: Verify server-side rendering still works correctly (shakapacker version checks are involved)

Action Items

High Priority:

  • Add CHANGELOG.md entry
  • Verify CI passes (RuboCop, tests, integration tests)

Medium Priority:

  • Review generated examples version constraint (consider allowing >= 7.0.0 or >= 8.2.0)
  • Update documentation mentioning Shakapacker version requirements
  • Verify no breaking changes from Shakapacker 8.x → 9.x affect users

Low Priority:

  • Consider adding release notes explaining what users get from Shakapacker 9.3.0

Code Quality: ⭐⭐⭐⭐⭐ (5/5)

  • Follows project conventions perfectly
  • RuboCop clean
  • Files properly end with newlines
  • Formatting is consistent

Great work on maintaining backward compatibility while upgrading! 🎉


🤖 Review generated with Claude Code

@claude
Copy link

claude bot commented Nov 2, 2025

Code Review: Update shakapacker to 9.3.0

Summary

This PR updates the shakapacker dependency from version 8.2.0 to 9.3.0 across the codebase. The changes are systematic and well-documented.


✅ Strengths

  1. Comprehensive Coverage: All relevant files have been updated consistently:

    • Gemfile dependencies
    • package.json files
    • Rake task generators
    • Conversion scripts
    • Lock files (Gemfile.lock, yarn.lock)
  2. Good Documentation: The PR description clearly lists all changes and confirms testing has been performed (RuboCop, bundle install, yarn install, git hooks).

  3. Consistent Version References: The update correctly maintains the version check at lib/react_on_rails/packer_utils.rb:36 which checks for async loading support (still checking against "8.2.0" as the minimum requirement, which is correct).

  4. Test Coverage: The existing test suite at spec/react_on_rails/packer_utils_spec.rb already validates version checking logic and should catch any breaking changes.


⚠️ Potential Issues & Recommendations

1. Documentation References Need Updating

Several documentation files still reference version 8.2.0 as examples/requirements. While these may be intentional (showing minimum versions), they should be reviewed:

  • docs/api-reference/configuration.md:240: Comments about async loading support
  • docs/api-reference/configuration.md:247: Version compatibility table
  • docs/upgrading/release-notes/16.0.0.md:49-90: Multiple references to 8.2.0 as the async loading threshold
  • docs/pro/major-performance-breakthroughs-upgrade-guide.md:94: Performance documentation

Recommendation: Consider whether these docs should:

  • Keep referencing 8.2.0 as the minimum version for async support (correct from a backward compatibility perspective)
  • Add a note recommending upgrade to 9.3.0+ for latest features
  • Update examples to show current best practices with 9.3.0

2. Missing Changelog Entry

The PR doesn't appear to include a CHANGELOG.md entry. According to the repository's patterns, version updates typically warrant a changelog entry.

Recommendation: Add an entry to CHANGELOG.md documenting this upgrade, especially if there are any behavioral changes or new features available in Shakapacker 9.3.0.

3. Dependency Breaking Changes Not Validated

The jump from 8.2.0 to 9.3.0 skips several minor versions (8.3, 9.0, 9.1, 9.2). The yarn.lock diff shows new dependencies:

  • flat@^5.0.2 (new transitive dependency)
  • webpack-merge@^5.8.0 (version range update from ^5.7.3)
  • yargs@^17.7.2 (new transitive dependency)

Recommendation:

  • Review the Shakapacker changelog for versions 8.3.0 through 9.3.0 to identify any breaking changes
  • Verify that existing webpack configurations remain compatible
  • Test the dev server and production builds thoroughly
  • Ensure SSR (server-side rendering) still works correctly

4. Test Coverage Gap

While packer_utils_spec.rb tests the version checking logic, there don't appear to be integration tests that validate:

  • Async script loading still works with 9.3.0
  • Webpack dev server integration remains functional
  • Manifest generation/lookup works correctly

Recommendation: Consider adding integration tests or at minimum, manually verify these critical features in the dummy app.

5. Generated Examples Consideration

The update changes rakelib/shakapacker_examples.rake:37 to require >= 9.3.0 for generated examples. This means:

  • Users running the examples generator will now require 9.3.0+
  • This could break workflows for users on older versions

Recommendation: Verify this is intentional and consider backward compatibility implications.


🔒 Security Considerations

No security concerns identified. Upgrading to a newer version generally includes security fixes, which is positive.


⚡ Performance Considerations

  • Shakapacker 9.3.0 may include performance improvements over 8.2.0
  • The new webpack-merge version could have optimizations
  • No performance regressions expected, but worth monitoring in production

🧪 Testing Recommendations

  1. Manual Testing Checklist:

    • Run full test suite: rake
    • Test webpack dev server: Start dev server and verify HMR works
    • Test production build: rake shakapacker:compile
    • Test SSR: Verify server-side rendering functions correctly
    • Test generated examples: rake shakapacker_examples:gen_all
    • Test async script loading with component packs
    • Verify manifest.json generation and lookup
  2. CI Validation: Wait for all CI checks to pass before merging


📝 Code Quality

  • ✅ Follows repository conventions
  • ✅ All files end with newlines (per CLAUDE.md requirements)
  • ✅ No RuboCop violations reported
  • ✅ Consistent formatting throughout

Final Verdict

Approval Status: ⚠️ Conditional Approval

The code changes themselves are solid and well-executed. However, I recommend addressing these items before merging:

  1. MUST: Verify no breaking changes exist between 8.2.0 and 9.3.0 in Shakapacker
  2. SHOULD: Add CHANGELOG.md entry
  3. SHOULD: Review and update documentation references
  4. SHOULD: Run comprehensive manual testing per checklist above

The systematic nature of the changes gives confidence that nothing was missed, but the version jump is significant enough to warrant thorough validation.


🤖 Review generated by Claude Code

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
rakelib/shakapacker_examples.rake (1)

37-37: Consider using pessimistic version constraint ~> 9.3 for better compatibility.

The >= 9.3.0 constraint allows any future version including potentially incompatible major versions (10.x, 11.x). Using ~> 9.3 would allow patch and minor updates within the 9.x line while preventing breaking changes from future major versions.

Apply this diff to use a pessimistic version constraint:

-      sh_in_dir(example_type.dir, "echo \"gem 'shakapacker', '>= 9.3.0'\" >> #{example_type.gemfile}")
+      sh_in_dir(example_type.dir, "echo \"gem 'shakapacker', '~> 9.3'\" >> #{example_type.gemfile}")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a59bbb7 and 752456c.

⛔ Files ignored due to path filters (3)
  • Gemfile.lock is excluded by !**/*.lock
  • spec/dummy/Gemfile.lock is excluded by !**/*.lock
  • spec/dummy/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (5)
  • Gemfile.development_dependencies (1 hunks)
  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml (1 hunks)
  • rakelib/shakapacker_examples.rake (1 hunks)
  • script/convert (1 hunks)
  • spec/dummy/package.json (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,jsx,ts,tsx,css,scss,json,yml,yaml,md}

📄 CodeRabbit inference engine (CLAUDE.md)

Prettier is the sole authority for formatting all non-Ruby files; never manually format them

Files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • spec/dummy/package.json
{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}

📄 CodeRabbit inference engine (CLAUDE.md)

{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}: All Ruby code must pass RuboCop with zero offenses before commit/push
RuboCop is the sole authority for Ruby file formatting; never manually format Ruby files

Files:

  • rakelib/shakapacker_examples.rake
🧠 Learnings (6)
📓 Common learnings
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • script/convert
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • script/convert
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1745
File: node_package/src/RSCRequestTracker.ts:8-14
Timestamp: 2025-07-08T05:57:29.630Z
Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • spec/dummy/package.json
  • script/convert
🔇 Additional comments (4)
Gemfile.development_dependencies (1)

3-3: LGTM!

The shakapacker version update is consistent with other changes in this PR. Exact version pinning ensures reproducible builds across development environments.

spec/dummy/package.json (2)

57-57: No issues found — swc-loader 0.2.6 is compatible with webpack 5.72.0 and shakapacker.

[email protected] is compatible with Webpack 5 (including 5.72.0), and Shakapacker v6.1.1+ includes opt-in SWC support. Since shakapacker 9.3.0 is newer than 6.1.1+, the added dependency is appropriate for this configuration.


32-32: No compatibility issues detected.

Shakapacker 9.3.0 recommends @swc/core ^1.3.0, and the specified version ^1.7.0 falls within this compatible range. The configuration is correct.

script/convert (1)

20-22: Shakapacker 9.3.0 is still in beta—verify if intentional and test API compatibility.

The codebase extensively uses shakapacker APIs that could break with major version changes:

  • Ruby: Shakapacker::Instance, Shakapacker::Configuration, Shakapacker::DevServer, Shakapacker::Manifest, exception handling
  • JavaScript: generateWebpackConfig, webpackConfig, inliningCss, config, devServer, merge, Babel preset imports

Shakapacker 9.3.0 is still in beta—no stable release notes or formal breaking changes documentation has been published yet. Before upgrading:

  1. Confirm 9.3.0 beta is acceptable for your use case (consider using the latest stable version instead)
  2. Review the 9.3.0 beta releases and PRs on the Shakapacker repository to identify any API-breaking changes affecting the patterns found in the codebase
  3. Run full integration tests after updating, including webpack config generation and bundle loading

@claude
Copy link

claude bot commented Nov 2, 2025

Pull Request Review: Update shakapacker to 9.3.0

Overview

This PR updates Shakapacker from version 8.2.0 to 9.3.0 across the codebase. Overall, the changes are well-structured and comprehensive. The PR description indicates that all linting checks pass and git hooks succeeded.


Strengths

1. Comprehensive Version Updates

All version references have been properly updated across:

  • Gemfile.development_dependencies
  • Both Gemfile.lock files (root and spec/dummy)
  • package.json (spec/dummy)
  • rakelib/shakapacker_examples.rake
  • script/convert

2. Configuration Changes Are Correct

The shakapacker.yml template correctly updates from the deprecated webpack_loader setting to the new javascript_transpiler setting:

# OLD (v8.2.0):
webpack_loader: 'babel'

# NEW (v9.3.0):
javascript_transpiler: "swc"  # Default, 20x faster

This change aligns with Shakapacker 9.x's improved configuration naming and defaults to SWC for better performance.

3. Proper Dependency Additions

The PR correctly adds the required SWC dependencies to spec/dummy/package.json:

  • @swc/core: ^1.7.0
  • swc-loader: ^0.2.6

These are necessary for the new default transpiler configuration.

4. Lock Files Updated Correctly

Both yarn.lock files show proper resolution of:

  • shakapacker 9.3.0 with new dependencies (webpack-merge, yargs)
  • All SWC platform-specific binaries
  • Consistent dependency tree

⚠️ Issues & Concerns

1. 🔴 CRITICAL: Hardcoded Version Check Not Updated

Location: lib/react_on_rails/packer_utils.rb:36

def self.supports_async_loading?
  shakapacker_version_requirement_met?("8.2.0")
end

Issue: This method still checks for version 8.2.0, which was the version that introduced async loading support. While this isn't technically wrong (9.3.0 > 8.2.0 so the check passes), it creates maintenance confusion.

Recommendation: Consider whether this should be updated or documented. The check is functionally correct but may confuse future maintainers who see 8.2.0 referenced in code while the minimum required version is now 9.3.0.

Consideration: If 8.2.0 was indeed the version that introduced async loading, keeping this check at 8.2.0 is semantically correct. However, if there are breaking changes between 8.2.0 and 9.3.0, this might need updating.

2. 📝 Documentation References Need Review

The grep search found "8.2.0" still referenced in these files (not changed in this PR):

  • docs/pro/major-performance-breakthroughs-upgrade-guide.md
  • docs/upgrading/release-notes/16.0.0.md
  • docs/api-reference/configuration.md

Recommendation: Review these documentation files to determine if they need updating for the new minimum version, or if they're correctly documenting historical information.

3. ❓ Breaking Changes Between 8.2.0 and 9.3.0

Question: The PR description doesn't mention if there are any breaking changes between Shakapacker 8.2.0 and 9.3.0.

Recommendation:

  • Add a note about compatibility/breaking changes (if any)
  • Test that the upgrade works smoothly in generated examples
  • Verify that the configuration migration from webpack_loader to javascript_transpiler is backward compatible

4. Test Coverage Consideration

Location: spec/react_on_rails/packer_utils_spec.rb:80-92

The test for supports_async_loading? is present and tests the 8.2.0 version check. This is good, but consider adding an integration test that verifies:

  • The new SWC transpiler configuration works correctly
  • Async loading still functions properly with 9.3.0

🔍 Code Quality & Best Practices

Positive Observations:

  1. ✅ All Ruby files maintain frozen_string_literal: true
  2. ✅ Consistent version references across the codebase
  3. ✅ Lock files properly committed with dependency updates
  4. ✅ Generator templates updated to use new version
  5. ✅ Test suite expectations maintained (tests still reference 8.2.0 where semantically appropriate)

Formatting Compliance:

According to CLAUDE.md, this PR should:

  • ✅ Have run bundle exec rubocop (confirmed in PR description)
  • ✅ Ensure files end with newlines (git hooks passed)
  • ✅ Use Prettier/RuboCop for formatting (autofix hooks passed)

🎯 Recommendations

High Priority:

  1. Clarify the version check in packer_utils.rb:36 - Either update it to 9.3.0 or add a comment explaining why 8.2.0 is the correct semantic version to check
  2. Document breaking changes - Add information about Shakapacker 8.2.0 → 9.3.0 compatibility
  3. Review documentation files - Check if docs need updating for the new minimum version

Medium Priority:

  1. Integration testing - Verify that generated examples work with new SWC configuration
  2. Configuration migration - Confirm that existing projects using webpack_loader will see clear migration instructions

Low Priority:

  1. Changelog entry - Consider adding this upgrade to CHANGELOG.md under Unreleased
  2. Performance validation - Since SWC is now the default (20x faster claim), validate this in tests

🔐 Security Considerations

✅ No security concerns identified. The new SWC dependencies are from official packages with good reputation.


📊 Performance Considerations

Positive Impact: Switching from Babel to SWC as the default transpiler should provide significant build performance improvements (as noted in the configuration comments: "20x faster").


Final Assessment

Approval Status: ✅ Approve with Minor Suggestions

This is a solid dependency upgrade PR with comprehensive changes. The main concerns are:

  1. Clarification needed on the 8.2.0 version check in supports_async_loading?
  2. Documentation review recommended
  3. Breaking changes should be documented

The code changes are correct and follow project conventions. The configuration updates properly reflect Shakapacker 9.3.0's new settings.


Great job on this upgrade! The thoroughness of updating all references and properly adding new dependencies shows attention to detail. 🎉

Generated with Claude Code - Technical accuracy prioritized ✨

@claude
Copy link

claude bot commented Nov 2, 2025

PR Review: Update shakapacker to 9.3.0

Overall Assessment

This is a well-executed dependency upgrade that properly handles the breaking changes introduced in Shakapacker 9.x. The PR demonstrates good attention to compatibility and includes all necessary configuration updates. ✅


Code Quality & Best Practices

✅ Strengths

  1. Comprehensive Version Update

    • All version references updated consistently across Gemfiles, package.json, and supporting scripts
    • Both Ruby and JavaScript dependency files properly updated with matching lock files
  2. Breaking Change Mitigation

    • Excellent handling of the CSS Modules breaking change (namedExport: true default in 9.0)
    • The backward compatibility fix in commonWebpackConfig.js:29-41 is well-commented and explains the rationale
    • Smart decision to keep async loading check at 8.2.0 rather than bumping to 9.3.0 (allows broader version compatibility)
  3. Configuration Updates

    • Template updated to use the new javascript_transpiler setting instead of deprecated webpack_loader
    • Good documentation in shakapacker.yml comments explaining the transpiler options and their performance characteristics
  4. Documentation

    • Clear commit messages explaining the why behind each change
    • Inline comments document breaking changes and compatibility fixes

Potential Issues & Concerns

⚠️ Medium Priority

  1. CSS Modules Configuration Mutation (commonWebpackConfig.js:32-41)

    Issues:

    • Directly mutating the webpack config object could be fragile
    • The check loader.loader.includes('css-loader') is string-based and could match unintended loaders
    • No validation that loader.options.modules is actually an object before setting properties

    Suggestions:

    • Consider using a more explicit check: loader.loader === 'css-loader' or path-based comparison
    • Add defensive checks: ensure modules is an object before modifying
    • Alternative: Configure this in shakapacker.yml if possible, or use webpack-merge to override config more explicitly
  2. Missing Test Coverage

    • No new tests added to verify CSS Modules behavior with the new configuration
    • Should add tests to ensure default imports still work
    • Should test that the transpiler change (babel → swc) doesn't break existing functionality

Performance Considerations

✅ Positive

  1. SWC Adoption
    • Switching to SWC (20x faster than Babel) is excellent for build performance
    • Properly added @swc/core and swc-loader dependencies

Security Concerns

✅ No Critical Issues Found

  1. Dependency Versions

    • Shakapacker 9.3.0 is the latest version (good for security patches)
    • SWC dependencies pulled from npm registry with integrity hashes in yarn.lock ✓
  2. Configuration Changes

    • No security-sensitive configuration changes detected
    • CSS Modules configuration is cosmetic (export style), not security-related

Summary

Approve with Minor Suggestions 👍

This PR successfully upgrades Shakapacker to 9.3.0 with proper handling of breaking changes. The main improvement areas are:

  1. Add safety checks to the CSS Modules configuration mutation
  2. Add test coverage for CSS Modules and SWC transpilation
  3. Verify all tests pass before merging

The code quality is high, and the migration strategy is sound. The breaking change mitigation demonstrates good understanding of the upgrade impact on downstream users.

Great work handling a complex dependency upgrade! The attention to backward compatibility and clear documentation will make this upgrade smooth for users of the gem.

@claude
Copy link

claude bot commented Nov 2, 2025

Code Review: Shakapacker 9.3.0 Upgrade

Summary

This PR successfully upgrades Shakapacker from 8.2.0 to 9.3.0 with proper handling of breaking changes. The changes are well-structured across 4 commits that logically progress through the upgrade process.


✅ Strengths

1. Excellent Commit Structure

The PR follows a logical progression through initial version bump, backward compatibility correction, SWC support, and CSS Modules fix. This incremental approach makes the changes easy to review and understand.

2. Backward Compatibility Preservation

The second commit correctly reverts the async loading version check to 8.2.0 in lib/react_on_rails/packer_utils.rb. This is the right decision - users with shakapacker >= 8.2.0 should be able to use async loading.

3. Proper Handling of Breaking Changes

SWC Transpiler Support: Added required dependencies (@swc/core, swc-loader) and updated template to use new javascript_transpiler setting with good documentation about performance benefits.

CSS Modules Compatibility: The webpack config fix properly addresses Shakapacker 9.0 breaking change by setting namedExport: false to preserve compatibility with existing default imports.


🔍 Issues & Recommendations

1. Missing CSS Modules Fix in Generator Template

The CSS Modules compatibility fix is applied to spec/dummy/config/webpack/commonWebpackConfig.js but needs verification in generator templates. New projects should have this fix.

2. Documentation Gaps

Missing: CHANGELOG entry, migration guide for users upgrading from 8.x to 9.x, documentation of breaking changes.

Recommendation: Add CHANGELOG entry documenting the upgrade, breaking changes (SWC as default transpiler, CSS Modules configuration), and migration steps.

3. Test Coverage

Missing: Tests for SWC transpiler configuration, CSS Modules with default imports, integration tests for 9.3.0 upgrade.

4. Version Conflicts

Generated examples require >= 9.3.0 but main gem uses = 9.3.0 (exact version). Consider using ~> 9.3 for flexibility or document why exact version is required.

5. Security

SWC dependencies use caret ranges which is good for security patches. Current approach is reasonable.


🎯 Performance

SWC is 20x faster than Babel - significant improvement. Consider adding before/after build time metrics to quantify benefits.


📋 Action Items Before Merge

  1. SHOULD ADD: CHANGELOG entry with migration guide
  2. SHOULD ADD: Verify CSS Modules fix in generator templates
  3. SHOULD ADD: Tests for new transpiler configuration
  4. NICE TO HAVE: Document version pinning strategy
  5. NICE TO HAVE: Build performance benchmarks

🎓 Code Quality Assessment

  • Code Quality: ⭐⭐⭐⭐⭐ Clean, well-structured
  • Testing: ⭐⭐⭐ Could benefit from additional tests
  • Documentation: ⭐⭐ Needs CHANGELOG and migration guide
  • Backward Compatibility: ⭐⭐⭐⭐⭐ Excellent
  • Security: ⭐⭐⭐⭐ Good dependency choices
  • Performance: ⭐⭐⭐⭐⭐ Major improvement with SWC

✅ Final Recommendation

Approve with Minor Improvements Requested

The upgrade is well-executed, especially the handling of breaking changes. Main improvements needed are documentation (CHANGELOG) and ensuring generator templates include the CSS Modules fix.

Great work on backward compatibility preservation and logical commit progression! 🎉

@claude
Copy link

claude bot commented Nov 2, 2025

Code Review - PR #1896: Update shakapacker to 9.3.0

I've completed a comprehensive review of this PR. Overall, this is a well-executed dependency upgrade with appropriate configuration updates. Here's my detailed feedback:


Positive Findings

1. Comprehensive Version Updates

  • All references to shakapacker updated consistently from 8.2.0 to 9.3.0 across:
    • Gemfile.development_dependencies
    • Rake tasks (shakapacker_examples.rake)
    • Conversion scripts (script/convert)
    • Lock files (Gemfile.lock, spec/dummy/Gemfile.lock, yarn.lock)

2. SWC Integration (Performance Improvement)

  • ✅ Added @swc/core and swc-loader as dev dependencies in generators
  • ✅ Updated shakapacker.yml to use javascript_transpiler: "swc" (20x faster than Babel)
  • This is a significant performance improvement for build times

3. Breaking Change Mitigation

  • ✅ Excellent work handling the CSS Modules breaking change in spec/dummy/config/webpack/commonWebpackConfig.js:29-43
  • The code explicitly sets namedExport: false to maintain backward compatibility
  • Clear comments explain the rationale

4. Configuration Updates

  • Updated shakapacker.yml template with better documentation
  • Changed webpack_loaderjavascript_transpiler (naming improvement)
  • Added helpful comment about rspack behavior

⚠️ Issues & Concerns

1. PR Description Inaccuracy ⚠️

The PR summary claims:

"Updated lib/react_on_rails/packer_utils.rb async loading version check to 9.3.0"
"Updated spec/react_on_rails/packer_utils_spec.rb test expectations to match new version"

However, these files are NOT in the diff. The actual file list shows:

  • ❌ lib/react_on_rails/packer_utils.rb - NOT modified
  • ❌ spec/react_on_rails/packer_utils_spec.rb - NOT modified

Impact: The version check in lib/react_on_rails/packer_utils.rb:36 still references "8.2.0":

def self.supports_async_loading?
  shakapacker_version_requirement_met?("8.2.0")
end

Question: Should this be updated to "9.3.0" or is "8.2.0" the correct minimum version requirement?

2. Missing Test Coverage ⚠️

  • No new tests added to verify the CSS Modules configuration changes
  • Consider adding integration tests to ensure namedExport: false behavior works correctly

3. Dependency Version Constraints

In package.json, consider using caret ranges for better flexibility:

"@swc/core": "^1.7.0"  // ✅ Good - allows patch/minor updates
"swc-loader": "^0.2.6"  // ✅ Good
"shakapacker": "9.3.0"   // ⚠️ Consider "^9.3.0" for patch updates

🔍 Code Quality Assessment

Best Practices

  • Follows repository's formatting rules (RuboCop, Prettier)
  • Clear, descriptive comments in complex sections
  • Consistent code style

Performance Considerations

  • SWC migration will significantly improve build performance
  • No blocking or synchronous operations introduced

Security Concerns

  • No security issues identified
  • Dependency updates from reputable sources
  • No sensitive data exposure

📝 Recommendations

High Priority:

  1. Update PR description to accurately reflect the actual changes
  2. Clarify if packer_utils.rb version check should be updated to 9.3.0
  3. Verify the webpack configuration changes work across all examples

Medium Priority:

  1. Add tests for CSS Modules configuration behavior
  2. Document breaking changes in CHANGELOG/migration guide
  3. Consider semver ranges for npm packages

Low Priority:

  1. Add comments in generators explaining why SWC deps are added

Testing Notes

Per the PR description:

  • ✅ RuboCop checks passed
  • ✅ Bundle install successful
  • ✅ Yarn install successful
  • ✅ Git hooks passed

Recommended additional testing:

  • Run full test suite: rake
  • Test example generation: rake shakapacker_examples:gen_all
  • Verify CSS Modules imports work correctly
  • Test HMR with SWC transpiler

📊 Overall Assessment

Rating: ⭐⭐⭐⭐ (4/5)

This is a solid dependency upgrade with thoughtful handling of breaking changes. The main issue is the PR description inaccuracy, which should be corrected. Once that's clarified and the version check question is resolved, this should be ready to merge.

Recommendation: Request clarification on the packer_utils.rb version check, update PR description, then approve.


Review conducted following CLAUDE.md guidelines and React on Rails conventions.

@claude
Copy link

claude bot commented Nov 2, 2025

Pull Request Review: Update Shakapacker to 9.3.0

Summary

This PR updates Shakapacker from version 8.2.0 to 9.3.0 across the codebase. Overall, the update is well-structured and comprehensive. The changes are properly tested according to the PR description, and the automated git hooks have passed.

✅ Code Quality & Best Practices

Strengths:

  1. Comprehensive version updates: All version references have been systematically updated across Gemfiles, package.json, rake tasks, and scripts
  2. Backward compatibility handling: The webpack configuration properly handles breaking changes in Shakapacker 9.0's CSS Modules behavior (see commonWebpackConfig.js:29-43)
  3. Generator updates: Both base_generator.rb and install_generator.rb correctly add the new SWC dependencies (@swc/core and swc-loader)
  4. Template updates: The shakapacker.yml template properly documents the new javascript_transpiler setting with helpful comments
  5. Defensive programming: The engine.rb validation skip for missing package.json is a good safety measure during initial setup

Areas for Improvement:

1. Missing Test Update ⚠️

The hardcoded version check in lib/react_on_rails/packer_utils.rb:36 still references "8.2.0":

def self.supports_async_loading?
  shakapacker_version_requirement_met?("8.2.0")
end

Recommendation: This should likely be updated to "9.3.0" if async loading support requires the newer version, OR if 8.2.0 is still the correct minimum version for this feature, add a comment explaining why it wasn't updated:

def self.supports_async_loading?
  # Async loading has been supported since 8.2.0, no need to bump requirement
  shakapacker_version_requirement_met?("8.2.0")
end

2. Configuration Key Name Change

In shakapacker.yml, the configuration key changed from webpack_loader to javascript_transpiler. This is a breaking change for users upgrading.

Recommendation:

  • Consider adding a migration note in the CHANGELOG.md under "Unreleased" → "Breaking Changes"
  • Document this in any upgrade guides
  • Consider adding a deprecation warning if the old key is detected (though this may be outside the scope of this PR)

3. Documentation Updates Needed 📝

The PR doesn't update the CHANGELOG.md or any migration documentation.

Recommendation: Add an entry to CHANGELOG.md:

### Dependencies
- **Shakapacker Upgrade**: Updated Shakapacker from 8.2.0 to 9.3.0. [PR #1896](https://github.com/shakacode/react_on_rails/pull/1896) by [justin808](https://github.com/justin808).
  - Changed default JavaScript transpiler to SWC (20x faster than Babel)
  - Configuration key renamed from `webpack_loader` to `javascript_transpiler` in `shakapacker.yml`
  - Added automatic SWC dependencies to generator (`@swc/core`, `swc-loader`)
  - Fixed CSS Modules namedExport compatibility for existing projects

4. CSS Modules Compatibility Code

The CSS Modules fix in spec/dummy/config/webpack/commonWebpackConfig.js:29-43 is excellent for backward compatibility, but it's only in the spec/dummy app.

Question: Should this pattern be documented or added to the generator templates for users upgrading existing projects? Users with existing import styles from './styles.module.css' syntax will hit this breaking change.

🐛 Potential Bugs

Low Risk:

  1. Version check caching: The @version_checks hash in packer_utils.rb:31 could theoretically grow unbounded if many different version checks are performed, though this is unlikely in practice.

🔒 Security Concerns

No security concerns identified. The dependency updates include security patches from the Shakapacker project.

⚡ Performance Considerations

Positive Impact:

  1. SWC as default transpiler: This is a significant performance improvement (20x faster than Babel according to the comments)
  2. New webpack-merge dependency: Shakapacker 9.3.0 adds webpack-merge and yargs as direct dependencies, which is cleaner than relying on transitive dependencies

🧪 Test Coverage

Current Status:

  • ✅ RuboCop passes (per PR description)
  • ✅ Bundle/yarn install successful
  • ✅ Git hooks passed

Gaps:

  1. No test updates: The spec files were not updated, though the existing mocking approach should still work
  2. Integration tests: Consider running the example app generators to ensure they work with the new version (though this may have been done manually)

Recommendation: Run rake run_rspec:example_basic to verify the generators work correctly with the new Shakapacker version and SWC setup.

📋 Checklist Before Merge

  • Update CHANGELOG.md with dependency update entry
  • Review and clarify supports_async_loading? version check (line lib/react_on_rails/packer_utils.rb:36)
  • Consider documenting the CSS Modules namedExport fix for users upgrading
  • Verify example generators work: rake shakapacker_examples:gen_all
  • Run full test suite: rake all_but_examples

🎯 Overall Assessment

Rating: 8.5/10

This is a solid PR that handles the Shakapacker upgrade systematically. The main areas for improvement are documentation and clarifying the version requirements. The code changes are well-thought-out, particularly the CSS Modules backward compatibility fix.

Recommendation: Approve with minor changes requested (documentation updates and version check clarification).


Great work on this upgrade! The attention to backward compatibility details like the CSS Modules configuration shows careful consideration of the impact on existing users. 🚀

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
lib/react_on_rails/engine.rb (1)

12-14: Good defensive guard to handle missing package.json.

The validation skip when package.json doesn't exist prevents startup errors during initial setup, which aligns well with the Shakapacker installation workflow.

Minor suggestion: Consider renaming the variable to package_json_path for clarity, since it holds a path rather than JSON content.

Apply this diff to improve variable naming:

 # Skip validation if package.json doesn't exist yet (during initial setup)
-package_json = VersionChecker::NodePackageVersion.package_json_path
-next unless File.exist?(package_json)
+package_json_path = VersionChecker::NodePackageVersion.package_json_path
+next unless File.exist?(package_json_path)
spec/dummy/config/webpack/commonWebpackConfig.js (1)

32-43: Consider more robust loader detection and handle additional webpack rule formats.

The current implementation has a few limitations:

  1. Incomplete rule.use handling: Only processes rule.use when it's an array. Webpack rules can also have:

    • rule.use as a single loader object
    • rule.use as a function
    • rule.loader instead of rule.use
  2. Fragile loader matching: Using loader.loader.includes('css-loader') could match unintended paths (e.g., /custom-css-loader/). Consider a more precise check like loader.loader.endsWith('css-loader') or using a regex pattern.

Consider this more comprehensive approach:

-baseClientWebpackConfig.module.rules.forEach((rule) => {
-  if (Array.isArray(rule.use)) {
-    rule.use.forEach((loader) => {
-      if (loader.loader && loader.loader.includes('css-loader') && loader.options?.modules) {
-        // eslint-disable-next-line no-param-reassign
-        loader.options.modules.namedExport = false;
-        // eslint-disable-next-line no-param-reassign
-        loader.options.modules.exportLocalsConvention = 'camelCase';
-      }
-    });
-  }
-});
+const configureCssLoader = (loader) => {
+  if (loader.loader?.match(/css-loader/) && loader.options?.modules) {
+    // eslint-disable-next-line no-param-reassign
+    loader.options.modules.namedExport = false;
+    // eslint-disable-next-line no-param-reassign
+    loader.options.modules.exportLocalsConvention = 'camelCase';
+  }
+};
+
+baseClientWebpackConfig.module.rules.forEach((rule) => {
+  // Handle rule.use as array
+  if (Array.isArray(rule.use)) {
+    rule.use.forEach(configureCssLoader);
+  }
+  // Handle rule.use as single loader object
+  else if (rule.use && typeof rule.use === 'object') {
+    configureCssLoader(rule.use);
+  }
+  // Handle rule.loader (alternative to rule.use)
+  else if (rule.loader) {
+    configureCssLoader({ loader: rule.loader, options: rule.options });
+  }
+});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 752456c and c088ba1.

📒 Files selected for processing (4)
  • lib/generators/react_on_rails/base_generator.rb (1 hunks)
  • lib/generators/react_on_rails/install_generator.rb (1 hunks)
  • lib/react_on_rails/engine.rb (1 hunks)
  • spec/dummy/config/webpack/commonWebpackConfig.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}

📄 CodeRabbit inference engine (CLAUDE.md)

{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}: All Ruby code must pass RuboCop with zero offenses before commit/push
RuboCop is the sole authority for Ruby file formatting; never manually format Ruby files

Files:

  • lib/react_on_rails/engine.rb
  • lib/generators/react_on_rails/install_generator.rb
  • lib/generators/react_on_rails/base_generator.rb
**/*.{js,jsx,ts,tsx,css,scss,json,yml,yaml,md}

📄 CodeRabbit inference engine (CLAUDE.md)

Prettier is the sole authority for formatting all non-Ruby files; never manually format them

Files:

  • spec/dummy/config/webpack/commonWebpackConfig.js
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use ESLint for JS/TS code (lint via rake lint or yarn lint)

Files:

  • spec/dummy/config/webpack/commonWebpackConfig.js
🧠 Learnings (11)
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-10-23T17:22:01.074Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1875
File: lib/react_on_rails/utils.rb:112-124
Timestamp: 2025-10-23T17:22:01.074Z
Learning: In React on Rails, when Pro is installed but not licensed, the intended behavior is to raise an error on boot. The `react_on_rails_pro?` method validates licenses and should raise errors early (including during path resolution in methods like `server_bundle?`) to enforce licensing requirements rather than failing later with obscure errors.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-13T16:50:26.861Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/turbolinksUtils.ts:34-36
Timestamp: 2025-02-13T16:50:26.861Z
Learning: In React on Rails, when checking for Turbolinks version 5 using `turbolinksVersion5()`, always ensure `Turbolinks` exists first by checking `turbolinksInstalled()` to prevent TypeError when accessing properties.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • lib/react_on_rails/engine.rb
  • lib/generators/react_on_rails/install_generator.rb
  • lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • lib/react_on_rails/engine.rb
  • lib/generators/react_on_rails/base_generator.rb
  • spec/dummy/config/webpack/commonWebpackConfig.js
📚 Learning: 2025-09-15T21:24:48.207Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1781
File: node_package/src/ClientSideRenderer.ts:82-95
Timestamp: 2025-09-15T21:24:48.207Z
Learning: In React on Rails, the force_load feature includes both explicit `data-force-load="true"` usage and the ability to hydrate components during the page loading state (`document.readyState === 'loading'`). Both capabilities require a Pro license, so the condition `!railsContext.rorPro && (isComponentForceLoaded || document.readyState === 'loading')` correctly gates both scenarios.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation is handled in deeper level calls of the React on Rails Pro codebase, so it doesn't need to be validated again in the `rsc_payload_react_component` helper method.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2024-12-12T13:07:09.929Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/ReactOnRailsRSC.ts:87-87
Timestamp: 2024-12-12T13:07:09.929Z
Learning: When handling errors in 'node_package/src/ReactOnRailsRSC.ts', include the error stack in error messages in development and test environments to aid debugging.

Applied to files:

  • lib/react_on_rails/engine.rb
  • lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • lib/react_on_rails/engine.rb
  • lib/generators/react_on_rails/install_generator.rb
  • lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • lib/generators/react_on_rails/install_generator.rb
  • spec/dummy/config/webpack/commonWebpackConfig.js
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1745
File: node_package/src/RSCRequestTracker.ts:8-14
Timestamp: 2025-07-08T05:57:29.630Z
Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime.

Applied to files:

  • lib/generators/react_on_rails/install_generator.rb
🧬 Code graph analysis (1)
lib/react_on_rails/engine.rb (2)
lib/generators/react_on_rails/generator_helper.rb (1)
  • package_json (7-20)
lib/react_on_rails/version_checker.rb (1)
  • package_json_path (222-224)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22)
  • GitHub Check: lint-js-and-ruby
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: rspec-package-tests (3.4, minimum)
  • GitHub Check: claude-review
  • GitHub Check: rspec-package-tests (3.2, latest)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles
🔇 Additional comments (3)
lib/generators/react_on_rails/base_generator.rb (1)

204-205: LGTM! SWC dependencies added for Shakapacker 9.x support.

The addition of @swc/core and swc-loader aligns with the Shakapacker 9.3.0 upgrade. These packages enable SWC-based transpilation as an alternative to Babel.

lib/generators/react_on_rails/install_generator.rb (1)

497-498: LGTM! SWC dependencies added for Shakapacker 9.x support.

These additions mirror the changes in base_generator.rb and correctly enable SWC transpilation support for the Shakapacker 9.3.0 upgrade.

spec/dummy/config/webpack/commonWebpackConfig.js (1)

29-31: ****

The review comment misidentifies the scope and impact of this change. The webpack configuration modification only affects the test app (spec/dummy), not the generator templates.

Analysis shows:

  • Generator templates use import * as style (named imports) and will continue using Shakapacker 9.0 defaults (namedExport: true)
  • The dummy test app uses import css/styles (default imports) and is now configured with namedExport: false to align with those imports
  • These are separate concerns with separate configurations

The change reconciles the dummy app's webpack configuration with its actual CSS Module import patterns—it's not breaking existing imports. The retrieved learning about namedExports: true remains valid for generated projects using template defaults.

Likely an incorrect or invalid review comment.

@claude
Copy link

claude bot commented Nov 2, 2025

PR Review: Update shakapacker to 9.3.0

Overall, this is a well-executed upgrade with thoughtful handling of breaking changes. The PR addresses multiple compatibility issues systematically. Here's my detailed review:

✅ Strengths

  1. Comprehensive Breaking Change Handling: The PR properly addresses Shakapacker 9.x breaking changes:

    • CSS Modules namedExport change (spec/dummy/config/webpack/commonWebpackConfig.js:31-45)
    • SWC as new default transpiler with proper dependency additions
    • Updated configuration format (webpack_loader → javascript_transpiler)
  2. Smart Generator Improvements:

    • Added @swc/core and swc-loader to both base_generator.rb and install_generator.rb
    • Ensures all generated apps have required dependencies
  3. Exact Version Enforcement: The install_generator.rb changes to always use --save-exact flag (line 444) ensure version consistency, which aligns with the strict version checking requirements

  4. Well-Documented Commits: Each commit has clear explanations of what changed and why

⚠️ Issues & Concerns

1. Generator Detection Logic May Be Fragile (lib/react_on_rails/engine.rb:17)

next if defined?(Rails::Generators) && ARGV.any? { |arg| arg.include?("generate") || arg.include?("g") }

Issues:

  • Using ARGV.include? for generator detection is fragile and could have false positives
  • This could skip validation in production if someone has "generate" in their arguments
  • The check for defined?(Rails::Generators) alone may not be sufficient

Recommendation: Consider a more robust approach:

# Check if we're in a generator context more reliably
next if defined?(Rails::Generators) && caller.any? { |line| line.include?('/generators/') }

Or use a dedicated flag/environment variable set by the generator itself.

2. Potential Race Condition in Webpack Config (spec/dummy/config/webpack/commonWebpackConfig.js:27-29)

The guard check is good, but there's a subtle issue:

if (scssConfigIndex !== -1 && baseClientWebpackConfig.module.rules[scssConfigIndex]?.use) {
  baseClientWebpackConfig.module.rules[scssConfigIndex].use.push(sassLoaderConfig);
}

Issue: If scssConfigIndex is found but the rule structure changes between the findIndex and the actual access, this could still fail. However, this is unlikely in practice.

Minor suggestion: Consider adding a debug log when the scss config isn't found to help troubleshoot issues.

3. CSS Modules Mutation Uses ESLint Disable (spec/dummy/config/webpack/commonWebpackConfig.js:38-41)

// eslint-disable-next-line no-param-reassign
loader.options.modules.namedExport = false;

Observation: While the eslint-disable is justified here, this direct mutation approach could be fragile if Shakapacker's internal structure changes.

Recommendation: Consider documenting this as a potential maintenance point, or explore if Shakapacker provides a more official way to configure this in future versions.

4. Missing Async Loading Version Documentation

The PR reverted the async loading version check back to 8.2.0 (commit 2), which is correct. However, this could confuse future maintainers.

Recommendation: Add a comment in lib/react_on_rails/packer_utils.rb explaining why this version differs from the main Shakapacker version requirement.

🔍 Security Considerations

  1. No Security Concerns Identified: The changes are primarily dependency updates and configuration adjustments
  2. Lock Files Updated Properly: Both Gemfile.lock and yarn.lock are updated consistently

🧪 Testing Observations

From the PR description, testing appears comprehensive:

  • RuboCop checks passed
  • Git hooks validated
  • Multiple CI test suites mentioned (examples, build-dummy-app-webpack-test-bundles)

Question: Were manual tests performed for:

  • Existing apps with CSS Modules using default imports?
  • Apps with custom webpack configurations?
  • Both SWC and Babel transpiler options?

📊 Performance Considerations

Positive Impact: SWC as default transpiler should provide ~20x faster builds compared to Babel, which is excellent for developer experience.

🎯 Best Practices Alignment

Follows CLAUDE.md Requirements:

  • All files end with newlines
  • RuboCop compliance verified
  • Git hooks validated
  • Formatted with automated tools

📝 Recommendations

  1. High Priority: Improve the generator detection logic in engine.rb (see issue TODO for first version #1 above)

  2. Medium Priority:

    • Add inline comment explaining async loading version difference
    • Consider logging when webpack config modifications fail silently
  3. Documentation:

    • Update CHANGELOG.md with breaking changes and migration guide
    • Document that users with custom CSS Module configurations may need adjustments
  4. Future Enhancement:

    • Consider providing a migration rake task that checks user webpack configs for potential issues
    • Add deprecation warnings if old webpack_loader setting is detected

✅ Approval Recommendation

Status: Approve with minor suggestions

This PR successfully handles a complex version upgrade with multiple breaking changes. The issues identified are minor and mostly about future maintainability rather than critical bugs. The validation skip logic is the only item I'd strongly recommend reviewing before merge.

Overall Quality: 8.5/10

  • Excellent handling of breaking changes
  • Good test coverage
  • One architectural concern with generator detection
  • Well-documented commit history

Great work on this upgrade! 🚀

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
lib/react_on_rails/engine.rb (1)

16-17: Consider more robust generator detection.

The current ARGV string matching could produce false positives if any argument contains "generate" or "g" (e.g., file paths, script names). A more precise approach would be to check the Rails command context directly.

Consider using a more targeted check:

-        # Skip validation when running generators (packages may not be installed yet)
-        next if defined?(Rails::Generators) && ARGV.any? { |arg| arg.include?("generate") || arg.include?("g") }
+        # Skip validation when running generators (packages may not be installed yet)
+        next if defined?(Rails::Command::GenerateCommand) || (defined?(Rails::Generators) && Rails.const_defined?(:Generator))

Alternatively, check the command name more precisely:

-        next if defined?(Rails::Generators) && ARGV.any? { |arg| arg.include?("generate") || arg.include?("g") }
+        next if defined?(Rails::Generators) && ARGV.first&.match?(/\A(g|generate)\z/)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c088ba1 and 31a88fd.

📒 Files selected for processing (4)
  • lib/generators/react_on_rails/install_generator.rb (2 hunks)
  • lib/react_on_rails/engine.rb (1 hunks)
  • package_json_issue_comment.md (1 hunks)
  • spec/dummy/config/webpack/commonWebpackConfig.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/generators/react_on_rails/install_generator.rb
🧰 Additional context used
📓 Path-based instructions (3)
{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}

📄 CodeRabbit inference engine (CLAUDE.md)

{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}: All Ruby code must pass RuboCop with zero offenses before commit/push
RuboCop is the sole authority for Ruby file formatting; never manually format Ruby files

Files:

  • lib/react_on_rails/engine.rb
**/*.{js,jsx,ts,tsx,css,scss,json,yml,yaml,md}

📄 CodeRabbit inference engine (CLAUDE.md)

Prettier is the sole authority for formatting all non-Ruby files; never manually format them

Files:

  • spec/dummy/config/webpack/commonWebpackConfig.js
  • package_json_issue_comment.md
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use ESLint for JS/TS code (lint via rake lint or yarn lint)

Files:

  • spec/dummy/config/webpack/commonWebpackConfig.js
🧠 Learnings (10)
📚 Learning: 2025-10-23T17:22:01.074Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1875
File: lib/react_on_rails/utils.rb:112-124
Timestamp: 2025-10-23T17:22:01.074Z
Learning: In React on Rails, when Pro is installed but not licensed, the intended behavior is to raise an error on boot. The `react_on_rails_pro?` method validates licenses and should raise errors early (including during path resolution in methods like `server_bundle?`) to enforce licensing requirements rather than failing later with obscure errors.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-13T16:50:26.861Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/turbolinksUtils.ts:34-36
Timestamp: 2025-02-13T16:50:26.861Z
Learning: In React on Rails, when checking for Turbolinks version 5 using `turbolinksVersion5()`, always ensure `Turbolinks` exists first by checking `turbolinksInstalled()` to prevent TypeError when accessing properties.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-09-15T21:24:48.207Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1781
File: node_package/src/ClientSideRenderer.ts:82-95
Timestamp: 2025-09-15T21:24:48.207Z
Learning: In React on Rails, the force_load feature includes both explicit `data-force-load="true"` usage and the ability to hydrate components during the page loading state (`document.readyState === 'loading'`). Both capabilities require a Pro license, so the condition `!railsContext.rorPro && (isComponentForceLoaded || document.readyState === 'loading')` correctly gates both scenarios.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation is handled in deeper level calls of the React on Rails Pro codebase, so it doesn't need to be validated again in the `rsc_payload_react_component` helper method.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2024-12-12T13:07:09.929Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/ReactOnRailsRSC.ts:87-87
Timestamp: 2024-12-12T13:07:09.929Z
Learning: When handling errors in 'node_package/src/ReactOnRailsRSC.ts', include the error stack in error messages in development and test environments to aid debugging.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • lib/react_on_rails/engine.rb
  • package_json_issue_comment.md
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • spec/dummy/config/webpack/commonWebpackConfig.js
🧬 Code graph analysis (1)
lib/react_on_rails/engine.rb (2)
lib/generators/react_on_rails/generator_helper.rb (1)
  • package_json (7-20)
lib/react_on_rails/version_checker.rb (1)
  • package_json_path (222-224)
🔇 Additional comments (4)
lib/react_on_rails/engine.rb (1)

12-14: LGTM! Safe guard for initial setup.

The package.json existence check is appropriate for initial setup scenarios where the file hasn't been created yet.

spec/dummy/config/webpack/commonWebpackConfig.js (2)

27-29: LGTM! Appropriate guard for SCSS loader.

The defensive check prevents errors if the SCSS rule doesn't exist or lacks a use array, which is good practice for plugin configurations.


31-45: LGTM! Appropriate backward compatibility fix for Shakapacker 9.0.

This correctly overrides Shakapacker 9.0's new default (namedExport: true) to preserve existing import patterns (import styles from './file.module.css'). The mutation is intentional and properly guarded.

package_json_issue_comment.md (1)

1-58: Clarify the purpose and placement of this documentation.

This file appears to document a feature request or issue comment for the package_json gem. The filename and content suggest it might be:

  • A draft issue comment for an external repository
  • Temporary documentation that shouldn't be committed
  • Internal documentation that should be in a docs/ directory

Could you clarify:

  1. Is this file intended to be committed to the repository?
  2. If yes, should it be in a more appropriate location (e.g., docs/, or as a GitHub issue)?
  3. If it's a draft for an external issue, consider moving it outside the repository.

@claude
Copy link

claude bot commented Nov 2, 2025

PR Review: Update Shakapacker to 9.3.0

I've reviewed the changes in this PR. Overall, this is a well-structured upgrade with good attention to compatibility concerns. Here's my detailed feedback:


Strengths

  1. Comprehensive version updates - All references to shakapacker across Gemfiles, package.json, specs, and rake tasks have been consistently updated to 9.3.0.

  2. Good backward compatibility handling - The CSS Modules configuration changes in commonWebpackConfig.js show thoughtful handling of breaking changes (namedExport defaults).

  3. Well-documented workaround - The package_json_issue_comment.md provides excellent context for why the package_json gem was bypassed. This is valuable documentation.

  4. SWC tooling added - Properly adds @swc/core and swc-loader as dev dependencies, which is important for Shakapacker 9.x's default transpiler.

  5. Smart validation skip logic - The engine.rb changes prevent validation failures during setup/generator runs.


🔍 Potential Issues & Concerns

1. Rails Engine Validation Logic (lib/react_on_rails/engine.rb:17)

next if defined?(Rails::Generators) && ARGV.any? { |arg| arg.include?("generate") || arg.include?("g") }

Issues:

  • Using ARGV is fragile and may not work correctly in all contexts (Rake tasks, console, tests, etc.)
  • String matching with include? could have false positives (e.g., a file path containing "generate")
  • This check happens in an initializer that runs during Rails boot, but Rails::Generators might not always be defined when generators are running

Recommendation:
Consider a more robust approach:

# Check if we're in a generator context more reliably
generator_running = defined?(Rails::Generators) && 
                   (caller.any? { |line| line.include?('generators/') } ||
                    Rails.const_defined?(:Command) && Rails::Command.current == 'generate')
next if generator_running

Or use an environment variable approach that generators can set explicitly.

2. CSS Modules Configuration (spec/dummy/config/webpack/commonWebpackConfig.js:27-28)

if (scssConfigIndex !== -1 && baseClientWebpackConfig.module.rules[scssConfigIndex]?.use) {
  baseClientWebpackConfig.module.rules[scssConfigIndex].use.push(sassLoaderConfig);
}

Good: The guard check was added to prevent errors if the SCSS rule isn't found.

Concern: The CSS Modules configuration (lines 34-45) doesn't have similar safety checks. It directly mutates loader configs without checking if they exist.

Recommendation:
Add similar defensive checks:

baseClientWebpackConfig.module.rules.forEach((rule) => {
  if (Array.isArray(rule.use)) {
    rule.use.forEach((loader) => {
      if (loader?.loader && loader.loader.includes('css-loader') && loader.options?.modules) {
        // ... existing code
      }
    });
  }
});

3. Package Installation Strategy (lib/generators/react_on_rails/install_generator.rb:430-447)

The change to always use direct npm install with --save-exact is a breaking change for users who use yarn/pnpm/bun.

Current code:

success = system("npm", "install", "--save-exact", react_on_rails_pkg)

Issues:

  • Hard-codes npm as the package manager
  • Loses the package_json gem's automatic package manager detection
  • Users with yarn.lock or pnpm-lock.yaml will get npm packages installed, causing mixed lock files

Recommendation:
Either:

  1. Detect the package manager and use appropriate commands:

    manager = detect_package_manager # 'npm', 'yarn', 'pnpm', etc.
    exact_flag = manager == 'yarn' || manager == 'bun' ? '--exact' : '--save-exact'
    success = system(manager, "install", exact_flag, react_on_rails_pkg)
  2. Or continue using package_json gem but post-process package.json to remove carets:

    add_npm_dependencies(react_on_rails_pkg)
    # Then fix the version string in package.json
    fix_package_version("react-on-rails", ReactOnRails::VERSION)

🎯 Performance & Security Considerations

  1. SWC is 20x faster - Great upgrade! The switch to SWC as default transpiler is a significant performance improvement.

  2. Locked versions - Using exact versions for react-on-rails is correct for tight gem/npm coupling. No security concerns here.

  3. yarn.lock changes - The lockfile diff looks clean, all new dependencies are legitimate shakapacker/swc packages.


🧪 Test Coverage

Question: Were the following scenarios tested?

  1. Running rails generate react_on_rails:install on a fresh Rails app (both with npm and yarn)?
  2. Running rails generate react_on_rails:base to ensure base generator works?
  3. Verifying the validation skip logic works correctly during generator runs?
  4. Testing with existing apps upgrading from shakapacker 8.x?

The PR description mentions RuboCop passing and bundle/yarn install succeeding, but explicit generator testing would be valuable.


📝 Minor Suggestions

  1. package_json_issue_comment.md - This seems like it should be in a docs folder or removed from the PR. Is this meant to be a comment on the package_json gem repo issue tracker?

  2. shakapacker.yml comments (lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml:39-41) - Excellent documentation of the javascript_transpiler option!

  3. Consider adding a changelog entry - Based on CLAUDE.md guidelines, this version bump should be documented.


Best Practices Adherence

  • Formatting looks good (Prettier/RuboCop compliant)
  • Files end with newlines ✓
  • No obvious security issues
  • Good inline documentation

🎬 Recommendation

Conditional APPROVE pending:

  1. Fix or clarify the package manager hard-coding issue in install_generator.rb
  2. Consider strengthening the validation skip logic in engine.rb
  3. Add explicit generator testing to the test plan
  4. Clarify the purpose of package_json_issue_comment.md

The core upgrade work is solid, but the package manager detection regression needs attention before merging.


Great work on this upgrade! The attention to backward compatibility and the SWC migration is well-executed. 🚀

@claude
Copy link

claude bot commented Nov 3, 2025

Code Review: Shakapacker 9.3.0 Update

Overview

This PR updates Shakapacker from 8.2.0 to 9.3.0. Overall, the update is well-structured and follows the project's coding standards. However, I've identified several issues that should be addressed before merging.


Critical Issues

1. Package Manager Hard-Coding in add_react_on_rails_package (High Priority)

Location: lib/generators/react_on_rails/install_generator.rb:444

Issue: The method hard-codes npm as the package manager, which is inconsistent with the rest of the codebase and will cause problems for users using yarn/pnpm/bun.

# Current code always uses npm
success = system("npm", "install", "--save-exact", react_on_rails_pkg)

Problem:

  • Users with yarn.lock files will get conflicting lock files (both yarn.lock and package-lock.json)
  • Breaks the package manager detection pattern used elsewhere in the same file (see install_js_dependencies at lines 505-532)
  • This is a regression from the previous implementation

Recommendation: Detect and use the user's package manager:

def add_react_on_rails_package
  major_minor_patch_only = /\A\d+\.\d+\.\d+\z/
  
  react_on_rails_pkg = if ReactOnRails::VERSION.match?(major_minor_patch_only)
                         "react-on-rails@#{ReactOnRails::VERSION}"
                       else
                         puts "Adding the latest react-on-rails NPM module. " \
                              "Double check this is correct in package.json"
                         "react-on-rails"
                       end

  puts "Installing React on Rails package..."
  
  # Detect package manager and use appropriate exact version flag
  package_manager, exact_flag = detect_package_manager_and_exact_flag
  success = system(package_manager, "install", exact_flag, react_on_rails_pkg)
  @ran_direct_installs = true if success
  handle_npm_failure("react-on-rails package", [react_on_rails_pkg]) unless success
end

private

def detect_package_manager_and_exact_flag
  if File.exist?(File.join(destination_root, "yarn.lock"))
    ["yarn", "--exact"]
  elsif File.exist?(File.join(destination_root, "pnpm-lock.yaml"))
    ["pnpm", "--save-exact"]
  elsif File.exist?(File.join(destination_root, "bun.lockb"))
    ["bun", "--exact"]
  else
    ["npm", "--save-exact"]
  end
end

2. Fragile ARGV-Based Generator Detection (Medium Priority)

Location: lib/react_on_rails/engine.rb:17

Issue: The validation skip logic uses string matching on ARGV which is fragile:

next if defined?(Rails::Generators) && ARGV.any? { |arg| arg.include?("generate") || arg.include?("g") }

Problems:

  • arg.include?("g") is extremely broad and will match almost anything containing the letter "g"
  • ARGV behavior varies across different contexts (rake tasks, console, tests, background jobs)
  • Could match file paths like /path/to/generated/file.rb
  • Timing-dependent: Rails::Generators might not be defined when expected

Recommendation: Use an environment variable approach for explicit control:

# In lib/react_on_rails/engine.rb
initializer "react_on_rails.validate_version_and_package_compatibility" do
  config.after_initialize do
    package_json = VersionChecker::NodePackageVersion.package_json_path
    next unless File.exist?(package_json)
    
    # Skip validation when generators explicitly set this flag
    next if ENV["REACT_ON_RAILS_SKIP_VALIDATION"] == "true"
    
    Rails.logger.info "[React on Rails] Validating package version and compatibility..."
    VersionChecker.build.validate_version_and_package_compatibility\!
    Rails.logger.info "[React on Rails] Package validation successful"
  end
end
# In lib/generators/react_on_rails/install_generator.rb
def run_generators
  ENV["REACT_ON_RAILS_SKIP_VALIDATION"] = "true"
  
  if installation_prerequisites_met? || options.ignore_warnings?
    invoke_generators
    add_bin_scripts
    add_post_install_message unless options.redux?
  else
    # ... error handling
  end
ensure
  ENV.delete("REACT_ON_RAILS_SKIP_VALIDATION")
  print_generator_messages
end

3. Missing Defensive Checks in Webpack Config (Low Priority)

Location: spec/dummy/config/webpack/commonWebpackConfig.js:34-45

Issue: The CSS Modules configuration code lacks defensive programming compared to the SCSS configuration above it:

baseClientWebpackConfig.module.rules.forEach((rule) => {
  if (Array.isArray(rule.use)) {
    rule.use.forEach((loader) => {
      // Missing checks for loader existence before accessing properties
      if (loader.loader && loader.loader.includes('css-loader') && loader.options?.modules) {
        loader.options.modules.namedExport = false;
        loader.options.modules.exportLocalsConvention = 'camelCase';
      }
    });
  }
});

Recommendation: Add comprehensive safety checks:

baseClientWebpackConfig.module.rules.forEach((rule) => {
  if (Array.isArray(rule.use)) {
    rule.use.forEach((loader) => {
      if (
        loader &&
        typeof loader === 'object' &&
        loader.loader &&
        typeof loader.loader === 'string' &&
        loader.loader.includes('css-loader') &&
        loader.options &&
        typeof loader.options === 'object' &&
        loader.options.modules &&
        typeof loader.options.modules === 'object'
      ) {
        // eslint-disable-next-line no-param-reassign
        loader.options.modules.namedExport = false;
        // eslint-disable-next-line no-param-reassign
        loader.options.modules.exportLocalsConvention = 'camelCase';
      }
    });
  }
});

Documentation Concerns

4. Unexpected Documentation Files Added

Files: ISSUE_ANALYSIS.md and package_json_issue_comment.md

Issue: These appear to be internal analysis/draft documents that shouldn't be committed to the repository:

  • ISSUE_ANALYSIS.md (485 lines) contains detailed code review notes
  • package_json_issue_comment.md (58 lines) contains a draft comment for another project

Recommendation: Remove these files from the PR. They seem to be accidentally included.


Positive Aspects

Good configuration updates:

  • Updated shakapacker.yml to use javascript_transpiler: "swc" (20x faster than Babel)
  • Added SWC dependencies (@swc/core, swc-loader) to dev dependencies
  • Proper CSS Modules compatibility configuration for Shakapacker 9.0

Comprehensive version updates:

  • All references to 8.2.0 updated consistently across the codebase
  • Both Gemfile.lock and yarn.lock files properly updated

Code follows project standards:

  • RuboCop compliant (as mentioned in PR description)
  • Proper trailing newlines added to SCSS files
  • Uses exact version pinning where needed

Good documentation in code:

  • Clear comments explaining the CSS Modules configuration change
  • Updated shakapacker.yml comments to explain transpiler options

Testing Recommendations

Before merging, ensure:

  1. Multi-package-manager testing:

    • Test generator with yarn (most critical since it's common)
    • Test generator with pnpm
    • Test generator with npm
    • Verify no duplicate lock files are created
  2. Generator context testing:

    • Verify validation runs during normal Rails boot
    • Verify validation is skipped during rails generate react_on_rails:install
    • Test in rake tasks, console, and test environments
  3. CSS Modules testing:

    • Verify CSS Modules imports still work with default exports
    • Test with malformed webpack configs to ensure no crashes

Summary

Must Fix Before Merge:

  1. ❌ Remove ISSUE_ANALYSIS.md and package_json_issue_comment.md
  2. ❌ Fix package manager hard-coding in add_react_on_rails_package

Should Fix:
3. ⚠️ Improve generator detection logic in engine.rb
4. ⚠️ Add defensive checks to webpack config

Priority: Fix items 1 and 2 first, as they will cause issues for users. Items 3 and 4 are robustness improvements that can be addressed in follow-up PRs if time is tight.

Overall, this is a solid update to Shakapacker 9.3.0, but the package manager issue is a blocker that needs to be resolved.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
lib/generators/react_on_rails/generator_helper.rb (1)

98-128: Good package manager detection logic with minor clarity suggestions.

The implementation correctly detects package managers and returns appropriate commands. The fallback to npm is sensible.

Consider these optional improvements for clarity:

  1. Document the precedence order - The order matters when multiple lock files exist, but it's implicit in the hash order:
# Detects the package manager based on lock files and returns the appropriate command and exact flag
# Precedence order: yarn > pnpm > bun > npm (first detected is used)
# Returns: [package_manager, exact_flag, add_command]
  1. Note the command difference - It's subtle that npm uses "install" while others use "add". Consider adding a comment:
lock_files = {
  "yarn.lock" => ["yarn", "--exact", "add"],
  "pnpm-lock.yaml" => ["pnpm", "--save-exact", "add"],
  "bun.lockb" => ["bun", "--exact", "add"],
  "package-lock.json" => ["npm", "--save-exact", "install"] # npm uses 'install' not 'add'
}
ISSUE_ANALYSIS.md (1)

1-485: Valuable design documentation capturing implementation rationale.

This document provides excellent context for the changes in this PR by:

  1. Analyzing the problems with existing approaches
  2. Evaluating multiple solution options
  3. Documenting the recommended approach (which was implemented)

The document shows that Issue #1 (engine validation) and Issue #3 (package manager detection) solutions were implemented in lib/react_on_rails/engine.rb and lib/generators/react_on_rails/generator_helper.rb respectively.

Optional improvements:

  1. Add implementation status - Consider adding a section linking to the actual implementation:
## Implementation Status

- ✅ Issue #1: Implemented in `lib/react_on_rails/engine.rb` (lines 12-17)
- ⏳ Issue #2: Pending
- ✅ Issue #3: Implemented in `lib/generators/react_on_rails/generator_helper.rb` (lines 98-128)
  1. Consider renaming - If this is meant to be permanent documentation, consider moving to docs/ directory or renaming to something like SHAKAPACKER_9_UPGRADE_ANALYSIS.md to make the context clearer.

  2. Formatting - The markdownlint warnings about emphasis-as-heading can be fixed by converting bold text to proper headings where appropriate (lines 42, 89, 108, 158, 189, 215, 282, 321, 372, 440).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 31a88fd and d779040.

📒 Files selected for processing (9)
  • .github/workflows/lint-js-and-ruby.yml (1 hunks)
  • ISSUE_ANALYSIS.md (1 hunks)
  • knip.ts (3 hunks)
  • lib/generators/react_on_rails/generator_helper.rb (1 hunks)
  • lib/generators/react_on_rails/install_generator.rb (6 hunks)
  • lib/react_on_rails/engine.rb (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss (1 hunks)
  • spec/dummy/client/app/components/HelloWorld.module.scss (1 hunks)
  • spec/dummy/config/webpack/commonWebpackConfig.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • spec/dummy/config/webpack/commonWebpackConfig.js
  • lib/generators/react_on_rails/install_generator.rb
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx,css,scss,json,yml,yaml,md}

📄 CodeRabbit inference engine (CLAUDE.md)

Prettier is the sole authority for formatting all non-Ruby files; never manually format them

Files:

  • knip.ts
  • ISSUE_ANALYSIS.md
  • spec/dummy/client/app/components/HelloWorld.module.scss
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use ESLint for JS/TS code (lint via rake lint or yarn lint)

Files:

  • knip.ts
{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}

📄 CodeRabbit inference engine (CLAUDE.md)

{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}: All Ruby code must pass RuboCop with zero offenses before commit/push
RuboCop is the sole authority for Ruby file formatting; never manually format Ruby files

Files:

  • lib/generators/react_on_rails/generator_helper.rb
  • lib/react_on_rails/engine.rb
🧠 Learnings (14)
📚 Learning: 2025-09-29T12:23:13.615Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-29T12:23:13.615Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use ESLint for JS/TS code (lint via rake lint or yarn lint)

Applied to files:

  • .github/workflows/lint-js-and-ruby.yml
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • .github/workflows/lint-js-and-ruby.yml
  • ISSUE_ANALYSIS.md
  • lib/react_on_rails/engine.rb
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss
📚 Learning: 2025-09-29T12:23:13.615Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-29T12:23:13.615Z
Learning: Applies to {Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}} : All Ruby code must pass RuboCop with zero offenses before commit/push

Applied to files:

  • .github/workflows/lint-js-and-ruby.yml
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • .github/workflows/lint-js-and-ruby.yml
  • ISSUE_ANALYSIS.md
  • lib/generators/react_on_rails/generator_helper.rb
  • lib/react_on_rails/engine.rb
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • .github/workflows/lint-js-and-ruby.yml
  • knip.ts
  • ISSUE_ANALYSIS.md
  • spec/dummy/client/app/components/HelloWorld.module.scss
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss
📚 Learning: 2025-09-29T12:23:13.615Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-29T12:23:13.615Z
Learning: Never run npm; use Yarn Classic equivalents only

Applied to files:

  • knip.ts
📚 Learning: 2025-02-13T19:09:15.991Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/RSCWebpackLoader.ts:0-0
Timestamp: 2025-02-13T19:09:15.991Z
Learning: In React Server Components webpack loader, using `new Function('return import("react-server-dom-webpack/node-loader")')()` is necessary as a workaround to bypass TypeScript compilation issues with direct dynamic imports.

Applied to files:

  • knip.ts
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.

Applied to files:

  • ISSUE_ANALYSIS.md
  • lib/react_on_rails/engine.rb
📚 Learning: 2025-10-23T17:22:01.074Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1875
File: lib/react_on_rails/utils.rb:112-124
Timestamp: 2025-10-23T17:22:01.074Z
Learning: In React on Rails, when Pro is installed but not licensed, the intended behavior is to raise an error on boot. The `react_on_rails_pro?` method validates licenses and should raise errors early (including during path resolution in methods like `server_bundle?`) to enforce licensing requirements rather than failing later with obscure errors.

Applied to files:

  • ISSUE_ANALYSIS.md
  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-13T16:50:26.861Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/turbolinksUtils.ts:34-36
Timestamp: 2025-02-13T16:50:26.861Z
Learning: In React on Rails, when checking for Turbolinks version 5 using `turbolinksVersion5()`, always ensure `Turbolinks` exists first by checking `turbolinksInstalled()` to prevent TypeError when accessing properties.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-09-15T21:24:48.207Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1781
File: node_package/src/ClientSideRenderer.ts:82-95
Timestamp: 2025-09-15T21:24:48.207Z
Learning: In React on Rails, the force_load feature includes both explicit `data-force-load="true"` usage and the ability to hydrate components during the page loading state (`document.readyState === 'loading'`). Both capabilities require a Pro license, so the condition `!railsContext.rorPro && (isComponentForceLoaded || document.readyState === 'loading')` correctly gates both scenarios.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation is handled in deeper level calls of the React on Rails Pro codebase, so it doesn't need to be validated again in the `rsc_payload_react_component` helper method.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2024-12-12T13:07:09.929Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/ReactOnRailsRSC.ts:87-87
Timestamp: 2024-12-12T13:07:09.929Z
Learning: When handling errors in 'node_package/src/ReactOnRailsRSC.ts', include the error stack in error messages in development and test environments to aid debugging.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2024-10-08T20:53:47.076Z
Learnt from: theforestvn88
Repo: shakacode/react_on_rails PR: 1620
File: spec/dummy/client/app/startup/HelloTurboStream.jsx:3-3
Timestamp: 2024-10-08T20:53:47.076Z
Learning: The `RailsContext` import in `spec/dummy/client/app/startup/HelloTurboStream.jsx` is used later in the project, as clarified by the user theforestvn88.

Applied to files:

  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss
🧬 Code graph analysis (2)
lib/generators/react_on_rails/generator_helper.rb (1)
lib/generators/react_on_rails/generator_messages.rb (1)
  • add_warning (13-15)
lib/react_on_rails/engine.rb (2)
lib/generators/react_on_rails/generator_helper.rb (1)
  • package_json (7-20)
lib/react_on_rails/version_checker.rb (1)
  • package_json_path (222-224)
🪛 LanguageTool
ISSUE_ANALYSIS.md

[uncategorized] ~463-~463: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...ase failures 3. Fix Issue #2 last - Low priority defensive programming improvement ## T...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🪛 markdownlint-cli2 (0.18.1)
ISSUE_ANALYSIS.md

42-42: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


89-89: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


108-108: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


158-158: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


189-189: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


215-215: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


282-282: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


321-321: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


372-372: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


440-440: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🔇 Additional comments (6)
spec/dummy/client/app/components/HelloWorld.module.scss (1)

1-2: Verify that the SCSS import path and variable are available.

The import statement is being added to enable usage of $bright-color from the shared variables file. Ensure that app-variables.scss exists at the specified path and that the $bright-color variable is properly defined.

react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss (1)

1-5: Verify that the SCSS import path and variable are available in the react_on_rails_pro environment.

The import statement mirrors the changes in spec/dummy/client/app/components/HelloWorld.module.scss, enabling usage of $bright-color from the shared variables file. Ensure that app-variables.scss exists at the specified path in this parallel environment and that the $bright-color variable is properly defined.

.github/workflows/lint-js-and-ruby.yml (1)

73-76: Clarify the rationale for suppressing knip config hints.

The addition of --no-config-hints to the knip invocation (Line 75) is not mentioned in the PR objectives, which focus on shakapacker version updates. This flag suppresses knip's configuration diagnostics, which could mask legitimate issues.

What is the underlying knip configuration problem triggered by the shakapacker/SWC upgrade? Consider documenting this in a comment or commit message if this is a known workaround.

lib/react_on_rails/engine.rb (1)

9-17: Excellent validation guards implementation.

The two-tier skip logic is well-designed:

  1. Skips when package.json doesn't exist (initial setup scenario)
  2. Skips when explicitly requested via environment variable (generator scenario)

This approach eliminates the fragile ARGV inspection and provides explicit control. The guards are ordered efficiently with the cheaper file existence check first.

The implementation aligns with the recommended solution in ISSUE_ANALYSIS.md and provides a robust way to handle validation timing without false positives.

knip.ts (2)

10-18: Clarified binary ignores for dev-only tooling.

The additions of nps and e2e-test with clear comments improve the configuration documentation.


112-134: Updated ignore rules align with Shakapacker 9 tooling changes.

The dependency ignore adjustments reflect the updated build configuration:

  • Moving mini-css-extract-plugin to root workspace ignores
  • Adding webpack-merge as a direct dependency (transitive from shakapacker)
  • Removing previously ignored loaders that may now be properly detected

The changes are consistent with the broader webpack/CSS loader configuration updates in this PR.

justin808 added a commit that referenced this pull request Nov 3, 2025
…ssing require

Addresses 3 critical issues identified in PR #1896 review:

1. Remove invalid javascript_transpiler configuration
   - Shakapacker 9.3.0 does not support a top-level javascript_transpiler key
   - Removed lines 39-42 from shakapacker.yml template
   - Transpiler selection is configured via webpack config and installed loaders

2. Update Pro package.json files to Shakapacker 9.3.0
   - Updated react_on_rails_pro/spec/dummy/package.json (8.0.0 → 9.3.0)
   - Updated react_on_rails_pro/spec/execjs-compatible-dummy/package.json (8.0.0 → 9.3.0)
   - Added swc-loader and @swc/core dependencies to both files
   - Ensures version consistency across the codebase

3. Fix missing GeneratorMessages require in generator_helper.rb
   - Added require_relative "generator_messages" to prevent NameError
   - Issue occurred when detect_package_manager_and_exact_flag found multiple lock files
   - Now consistent with other generator files (base_generator.rb, install_generator.rb)

All RuboCop checks pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@justin808 justin808 self-assigned this Nov 3, 2025
@coderabbitai coderabbitai bot added the bug label Nov 3, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
lib/generators/react_on_rails/generator_helper.rb (1)

100-129: Consider clarifying the package manager precedence order.

The method correctly detects package managers and handles multiple lock files, but the warning message doesn't explain the precedence order (yarn → pnpm → bun → npm). Users might benefit from knowing why a particular package manager was chosen when multiple lock files exist.

Consider updating the warning message to be more explicit:

     if detected.size > 1
       GeneratorMessages.add_warning(<<~MSG.strip)
         ⚠️  Multiple package manager lock files detected:
         #{detected.map { |lf, _| "  • #{lf}" }.join("\n")}
 
         This can cause dependency conflicts. Consider using only one package manager.
-        Using #{detected.first[0]} based on file precedence.
+        Using #{detected.first[0]} based on precedence order: yarn → pnpm → bun → npm.
       MSG
     end
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a5b19dd and 7fd36a8.

📒 Files selected for processing (6)
  • lib/generators/react_on_rails/generator_helper.rb (2 hunks)
  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml (0 hunks)
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss (1 hunks)
  • react_on_rails_pro/spec/dummy/package.json (1 hunks)
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json (1 hunks)
  • spec/dummy/client/app/components/HelloWorld.module.scss (1 hunks)
💤 Files with no reviewable changes (1)
  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • lib/generators/react_on_rails/generator_helper.rb
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • spec/dummy/client/app/components/HelloWorld.module.scss
📚 Learning: 2025-10-23T17:22:01.074Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1875
File: lib/react_on_rails/utils.rb:112-124
Timestamp: 2025-10-23T17:22:01.074Z
Learning: In React on Rails, when Pro is installed but not licensed, the intended behavior is to raise an error on boot. The `react_on_rails_pro?` method validates licenses and should raise errors early (including during path resolution in methods like `server_bundle?`) to enforce licensing requirements rather than failing later with obscure errors.

Applied to files:

  • lib/generators/react_on_rails/generator_helper.rb
🧬 Code graph analysis (1)
lib/generators/react_on_rails/generator_helper.rb (1)
lib/generators/react_on_rails/generator_messages.rb (1)
  • add_warning (13-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: examples (3.2, minimum)
🔇 Additional comments (4)
spec/dummy/client/app/components/HelloWorld.module.scss (2)

1-1: File import path verified and is accessible.

The imported app-variables.scss file exists at the expected location. The relative import path is correct and the module will load successfully.


1-4: CSS Modules configuration is correctly aligned with Shakapacker 9.3.0.

The webpack configuration explicitly sets namedExport: false and exportLocalsConvention: 'camelCase', which perfectly matches the camelCase class name .brightColor in the SCSS file. The configuration is intentionally set for backward compatibility with default imports (import styles from './file.module.css'), and the code follows this pattern correctly. No changes are needed.

react_on_rails_pro/spec/execjs-compatible-dummy/package.json (1)

33-35: Verify dependency version consistency across dummy/spec package.json files.

The PR updates shakapacker and adds SWC tooling in multiple package.json files. Ensure that versions for shakapacker, swc-loader, and @swc/core are consistent across spec/dummy/package.json and react_on_rails_pro/spec/execjs-compatible-dummy/package.json to prevent version conflicts during builds and tests.

Based on learnings from prior PRs, inconsistent versions across dummy setups can cause integration issues. Can you verify that these versions match in both locations?

lib/generators/react_on_rails/generator_helper.rb (1)

5-5: LGTM! GeneratorMessages is now accessible.

The require_relative statement properly addresses the previous concern about GeneratorMessages availability.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7fd36a8 and ce33ba8.

📒 Files selected for processing (4)
  • package-scripts.yml (1 hunks)
  • react_on_rails_pro/spec/dummy/package.json (2 hunks)
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json (2 hunks)
  • spec/dummy/babel.config.js (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • package-scripts.yml
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • react_on_rails_pro/spec/dummy/package.json
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • package-scripts.yml
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • react_on_rails_pro/spec/dummy/package.json
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • package-scripts.yml
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • react_on_rails_pro/spec/dummy/package.json
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • spec/dummy/babel.config.js
  • react_on_rails_pro/spec/dummy/package.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22)
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20)
  • GitHub Check: lint-js-and-ruby
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: claude-review
  • GitHub Check: markdown-link-check
  • GitHub Check: rspec-package-tests (3.4, minimum)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.2, latest)
🔇 Additional comments (3)
spec/dummy/babel.config.js (1)

1-2: LGTM! Necessary update for shakapacker 9.3.0 compatibility.

The explicit .js extension and ESLint directive are appropriate for the updated shakapacker module resolution requirements. The configuration logic remains unchanged.

react_on_rails_pro/spec/dummy/package.json (1)

81-81: Correct placement of build-time dependencies.

All build-time tools (shakapacker, @swc/core, swc-loader) are correctly placed in devDependencies, which aligns with npm conventions for spec fixtures and is consistent with the shakapacker 9.3.0 upgrade.

Also applies to: 91-92

package-scripts.yml (1)

29-29: LGTM! Package manager consistency.

The switch from npm run build to yarn run build aligns with the project's use of Yarn as the primary package manager and is consistent across the codebase updates.

justin808 added a commit that referenced this pull request Nov 3, 2025
…ssing require

Addresses 3 critical issues identified in PR #1896 review:

1. Remove invalid javascript_transpiler configuration
   - Shakapacker 9.3.0 does not support a top-level javascript_transpiler key
   - Removed lines 39-42 from shakapacker.yml template
   - Transpiler selection is configured via webpack config and installed loaders

2. Update Pro package.json files to Shakapacker 9.3.0
   - Updated react_on_rails_pro/spec/dummy/package.json (8.0.0 → 9.3.0)
   - Updated react_on_rails_pro/spec/execjs-compatible-dummy/package.json (8.0.0 → 9.3.0)
   - Added swc-loader and @swc/core dependencies to both files
   - Ensures version consistency across the codebase

3. Fix missing GeneratorMessages require in generator_helper.rb
   - Added require_relative "generator_messages" to prevent NameError
   - Issue occurred when detect_package_manager_and_exact_flag found multiple lock files
   - Now consistent with other generator files (base_generator.rb, install_generator.rb)

All RuboCop checks pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@justin808 justin808 force-pushed the justin808/shakapacker-9.3.0 branch from ce33ba8 to 9f254fb Compare November 3, 2025 06:31
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/generators/react_on_rails/install_generator.rb (1)

545-555: Update manual install instructions to respect the detected package manager.

This warning always tells users to run npm install, even when we just attempted Yarn/Pnpm/Bun. On Yarn and Pnpm projects that guidance leads to duplicate lockfiles and conflicting dependency state. Please build the fallback command from detect_package_manager_and_exact_flag before emitting the message so we point developers to the right tool.

-        install_command = dev ? "npm install --save-dev" : "npm install"
+        package_manager, _exact_flag, add_command = detect_package_manager_and_exact_flag
+        install_command =
+          case package_manager
+          when "npm"
+            dev ? "npm #{add_command} --save-dev" : "npm #{add_command}"
+          when "yarn"
+            dev ? "yarn #{add_command} -D" : "yarn #{add_command}"
+          when "pnpm"
+            dev ? "pnpm #{add_command} -D" : "pnpm #{add_command}"
+          when "bun"
+            dev ? "bun #{add_command} --dev" : "bun #{add_command}"
+          else
+            dev ? "npm install --save-dev" : "npm install"
+          end
🧹 Nitpick comments (1)
package_json_issue_comment.md (1)

1-57: Clarify the file's purpose and intended location.

The filename package_json_issue_comment.md suggests this documents an issue or discussion, but it's unclear whether this is meant as permanent documentation in the codebase. Based on the enriched summary, this file appears to explain the motivation behind the package manager detection helper and exact-install flow changes.

If this is intended as permanent documentation, consider:

  1. Relocate to a dedicated directory — Move to docs/decisions/ (or similar ADR/decision-log directory) with a clearer name like package-manager-exact-install-support.md to indicate it's an architectural decision or design record.

  2. Add integration points — Reference this from relevant code files (e.g., lib/generators/react_on_rails/generator_helper.rb and lib/generators/react_on_rails/install_generator.rb) via inline comments explaining the rationale for the approach.

  3. Remove if temporary — If this is a temporary artifact (issue comment saved for reference), consider removing it or storing it in a separate issue/discussion tracker rather than committing it to the main codebase.

  4. Add cross-references — Link to the specific generator methods and explain how the problem described here is solved by the new package manager detection flow.

Based on learnings, consistent documentation across the codebase helps maintain clarity on version management decisions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce33ba8 and 9f254fb.

⛔ Files ignored due to path filters (3)
  • Gemfile.lock is excluded by !**/*.lock
  • spec/dummy/Gemfile.lock is excluded by !**/*.lock
  • spec/dummy/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (20)
  • .github/workflows/lint-js-and-ruby.yml (1 hunks)
  • Gemfile.development_dependencies (1 hunks)
  • ISSUE_ANALYSIS.md (1 hunks)
  • knip.ts (3 hunks)
  • lib/generators/react_on_rails/base_generator.rb (1 hunks)
  • lib/generators/react_on_rails/generator_helper.rb (2 hunks)
  • lib/generators/react_on_rails/install_generator.rb (6 hunks)
  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml (0 hunks)
  • lib/react_on_rails/engine.rb (1 hunks)
  • package-scripts.yml (1 hunks)
  • package_json_issue_comment.md (1 hunks)
  • rakelib/shakapacker_examples.rake (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss (1 hunks)
  • react_on_rails_pro/spec/dummy/package.json (2 hunks)
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json (2 hunks)
  • script/convert (1 hunks)
  • spec/dummy/babel.config.js (1 hunks)
  • spec/dummy/client/app/components/HelloWorld.module.scss (1 hunks)
  • spec/dummy/config/webpack/commonWebpackConfig.js (1 hunks)
  • spec/dummy/package.json (2 hunks)
💤 Files with no reviewable changes (1)
  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
🚧 Files skipped from review as they are similar to previous changes (10)
  • package-scripts.yml
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss
  • Gemfile.development_dependencies
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • spec/dummy/config/webpack/commonWebpackConfig.js
  • react_on_rails_pro/spec/dummy/package.json
  • rakelib/shakapacker_examples.rake
  • knip.ts
  • spec/dummy/client/app/components/HelloWorld.module.scss
  • lib/generators/react_on_rails/generator_helper.rb
🧰 Additional context used
🧠 Learnings (11)
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • spec/dummy/babel.config.js
  • script/convert
  • spec/dummy/package.json
  • ISSUE_ANALYSIS.md
  • lib/generators/react_on_rails/base_generator.rb
  • package_json_issue_comment.md
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • script/convert
  • lib/generators/react_on_rails/install_generator.rb
  • .github/workflows/lint-js-and-ruby.yml
  • ISSUE_ANALYSIS.md
  • lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • script/convert
  • lib/generators/react_on_rails/install_generator.rb
  • lib/react_on_rails/engine.rb
  • .github/workflows/lint-js-and-ruby.yml
  • ISSUE_ANALYSIS.md
  • lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • lib/generators/react_on_rails/install_generator.rb
  • .github/workflows/lint-js-and-ruby.yml
  • ISSUE_ANALYSIS.md
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.

Applied to files:

  • lib/generators/react_on_rails/install_generator.rb
  • lib/react_on_rails/engine.rb
  • ISSUE_ANALYSIS.md
📚 Learning: 2025-10-23T17:22:01.074Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1875
File: lib/react_on_rails/utils.rb:112-124
Timestamp: 2025-10-23T17:22:01.074Z
Learning: In React on Rails, when Pro is installed but not licensed, the intended behavior is to raise an error on boot. The `react_on_rails_pro?` method validates licenses and should raise errors early (including during path resolution in methods like `server_bundle?`) to enforce licensing requirements rather than failing later with obscure errors.

Applied to files:

  • lib/generators/react_on_rails/install_generator.rb
  • lib/react_on_rails/engine.rb
  • ISSUE_ANALYSIS.md
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1745
File: node_package/src/RSCRequestTracker.ts:8-14
Timestamp: 2025-07-08T05:57:29.630Z
Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime.

Applied to files:

  • lib/generators/react_on_rails/install_generator.rb
📚 Learning: 2024-12-12T13:07:09.929Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/ReactOnRailsRSC.ts:87-87
Timestamp: 2024-12-12T13:07:09.929Z
Learning: When handling errors in 'node_package/src/ReactOnRailsRSC.ts', include the error stack in error messages in development and test environments to aid debugging.

Applied to files:

  • lib/generators/react_on_rails/install_generator.rb
  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-13T16:50:26.861Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/turbolinksUtils.ts:34-36
Timestamp: 2025-02-13T16:50:26.861Z
Learning: In React on Rails, when checking for Turbolinks version 5 using `turbolinksVersion5()`, always ensure `Turbolinks` exists first by checking `turbolinksInstalled()` to prevent TypeError when accessing properties.

Applied to files:

  • lib/generators/react_on_rails/install_generator.rb
  • lib/react_on_rails/engine.rb
📚 Learning: 2025-09-15T21:24:48.207Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1781
File: node_package/src/ClientSideRenderer.ts:82-95
Timestamp: 2025-09-15T21:24:48.207Z
Learning: In React on Rails, the force_load feature includes both explicit `data-force-load="true"` usage and the ability to hydrate components during the page loading state (`document.readyState === 'loading'`). Both capabilities require a Pro license, so the condition `!railsContext.rorPro && (isComponentForceLoaded || document.readyState === 'loading')` correctly gates both scenarios.

Applied to files:

  • lib/react_on_rails/engine.rb
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation is handled in deeper level calls of the React on Rails Pro codebase, so it doesn't need to be validated again in the `rsc_payload_react_component` helper method.

Applied to files:

  • lib/react_on_rails/engine.rb
🧬 Code graph analysis (2)
lib/generators/react_on_rails/install_generator.rb (2)
lib/generators/react_on_rails/generator_helper.rb (2)
  • detect_package_manager_and_exact_flag (103-129)
  • add_npm_dependencies (24-40)
lib/generators/react_on_rails/base_generator.rb (1)
  • handle_npm_failure (242-254)
lib/react_on_rails/engine.rb (2)
lib/generators/react_on_rails/generator_helper.rb (1)
  • package_json (8-21)
lib/react_on_rails/version_checker.rb (5)
  • package_json_path (222-224)
  • build (12-14)
  • build (218-220)
  • react_on_rails_package? (254-256)
  • react_on_rails_pro_package? (258-260)
🪛 LanguageTool
ISSUE_ANALYSIS.md

[uncategorized] ~463-~463: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...ase failures 3. Fix Issue #2 last - Low priority defensive programming improvement ## T...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🪛 markdownlint-cli2 (0.18.1)
ISSUE_ANALYSIS.md

42-42: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


89-89: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


108-108: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


158-158: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


189-189: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


215-215: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


282-282: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


321-321: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


372-372: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


440-440: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: dummy-app-integration-tests (3.2, 20)
  • GitHub Check: dummy-app-integration-tests (3.4, 22)
  • GitHub Check: lint-js-and-ruby
  • GitHub Check: rspec-package-tests (3.4, minimum)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.2, latest)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: build
  • GitHub Check: claude-review
  • GitHub Check: markdown-link-check
🔇 Additional comments (1)
package_json_issue_comment.md (1)

24-35: Verify this workaround is no longer needed after PR changes.

The code snippet shows a direct npm install --save-exact workaround. Confirm that the new package manager detection helper and exact-install flow (mentioned in the enriched summary) fully addresses this limitation, and that this workaround code is either replaced or deprecated in the current PR.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
lib/react_on_rails/dev/pack_generator.rb (1)

46-64: IO redirection is not thread-safe.

Directly assigning to $stdout and $stderr affects all threads in the process and can cause issues if multiple threads are writing simultaneously. While this may be acceptable for a single-threaded context, consider documenting this limitation or using a thread-safe alternative like capturing output within the Rake task itself.

lib/generators/react_on_rails/base_generator.rb (1)

221-229: Refactor to use proper YAML parsing instead of string matching.

The current implementation uses simple string matching (include?), which is fragile and could lead to false positives or negatives:

  • ❌ Matches commented lines: # javascript_compiler: swc
  • ❌ Misses whitespace variations: javascript_compiler: swc (extra spaces)
  • ❌ Doesn't respect YAML structure or default sections

Apply this diff to parse YAML properly:

 def using_swc?
   # Check shakapacker.yml for javascript_compiler setting
   # Default to babel if not specified
   shakapacker_config_path = File.join(destination_root, "config", "shakapacker.yml")
   return false unless File.exist?(shakapacker_config_path)

-  config_content = File.read(shakapacker_config_path)
-  config_content.include?("javascript_compiler: swc")
+  require 'yaml'
+  config = YAML.load_file(shakapacker_config_path)
+  # Check the default section for javascript_compiler setting
+  config.dig("default", "javascript_compiler") == "swc"
+rescue StandardError
+  false
 end
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f254fb and 3b9ad52.

📒 Files selected for processing (3)
  • lib/generators/react_on_rails/base_generator.rb (2 hunks)
  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml (1 hunks)
  • lib/react_on_rails/dev/pack_generator.rb (2 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • lib/react_on_rails/dev/pack_generator.rb
  • lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1745
File: node_package/src/RSCRequestTracker.ts:8-14
Timestamp: 2025-07-08T05:57:29.630Z
Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • lib/react_on_rails/dev/pack_generator.rb
  • lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-09-29T14:45:42.687Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1833
File: lib/react_on_rails/dev/process_manager.rb:72-83
Timestamp: 2025-09-29T14:45:42.687Z
Learning: In Ruby bundler contexts, when bundler intercepts system commands for executables not in the Gemfile, both version checks (like `system("foreman", "--version")`) and execution commands (like `system("foreman", "start", ...)`) fail equally, both returning false. This means availability checks using version flags accurately reflect whether execution commands will work in the current bundler context.

Applied to files:

  • lib/react_on_rails/dev/pack_generator.rb
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: dummy-app-integration-tests (3.2, 20)
  • GitHub Check: dummy-app-integration-tests (3.4, 22)
  • GitHub Check: rspec-package-tests (3.2, latest)
  • GitHub Check: markdown-link-check
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.4, minimum)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: build
  • GitHub Check: lint-js-and-ruby
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: claude-review
🔇 Additional comments (2)
lib/react_on_rails/dev/pack_generator.rb (1)

27-35: No actionable changes required—this is an established and idiomatic pattern in the codebase.

The defined?(Bundler) check is the appropriate way to verify whether the Bundler constant is available before calling Bundler methods. This pattern is already established in the same codebase (process_manager.rb lines 91, 103) and uses a consistent two-stage approach: first checking if Bundler is defined, then using respond_to? checks for specific methods (as seen in with_unbundled_context). Prior verification of this pattern in bundler contexts confirmed it correctly reflects whether execution paths will work in the current environment. The check serves its intended purpose in routing to the appropriate execution strategy.

Likely an incorrect or invalid review comment.

lib/generators/react_on_rails/base_generator.rb (1)

176-187: LGTM! Clear conditional dependency management.

The conditional logic cleanly separates SWC and Babel dependencies based on the compiler configuration, with helpful inline comments.

require "rake"

# Load Rails environment if not already loaded
require File.expand_path("config/environment", Dir.pwd) unless defined?(Rails)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Rails root path assumption may fail.

Using Dir.pwd assumes the current working directory is the Rails root, which may not hold true in all contexts (e.g., when called from subdirectories or during certain deployment scenarios). Consider using Rails.root if Rails is already loaded, or searching upward for config/environment.rb.

Apply this diff to use a more robust path resolution:

-          require File.expand_path("config/environment", Dir.pwd) unless defined?(Rails)
+          unless defined?(Rails)
+            # Search upward for Rails root
+            rails_env = Dir.pwd
+            while rails_env != "/" && !File.exist?(File.join(rails_env, "config", "environment.rb"))
+              rails_env = File.dirname(rails_env)
+            end
+            raise "Could not find Rails root from #{Dir.pwd}" if rails_env == "/"
+            require File.expand_path("config/environment", rails_env)
+          end
🤖 Prompt for AI Agents
In lib/react_on_rails/dev/pack_generator.rb around line 41, replace the brittle
use of Dir.pwd when requiring config/environment with a robust path resolution:
if Rails is already defined and Rails.root is available use Rails.root,
otherwise walk upward from Dir.pwd (or __dir__) searching parent directories for
config/environment.rb and use that directory as the root; finally call require
File.expand_path("config/environment", resolved_root) unless defined?(Rails).
Ensure the search stops at filesystem root and raises a clear error if
config/environment.rb is not found.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
TURBO_NAVIGATION_TEST_ISSUE.md (1)

144-157: Consider file organization: Move to dedicated directory.

This comprehensive test plan document would be better served in a dedicated documentation directory (e.g., docs/contributor-info/ or docs/testing/) rather than at the project root, aligning with the structure suggested in lines 155-157 and improving discoverability.

lib/react_on_rails/dev/server_manager.rb (1)

433-445: Consider adding verbose parameter for consistency with PackGenerator.

The method doesn't accept a verbose parameter like PackGenerator.generate(verbose: verbose) does, creating an inconsistent user experience. When users pass --verbose, they would expect to see detailed output for all build steps, including ReScript compilation.

Apply this diff to align with the PackGenerator pattern:

 def run_static_development(procfile, verbose: false, route: nil)
   print_procfile_info(procfile, route: route)
   print_server_info(
     "⚡ Starting development server with static assets...",
     [
       "Generating React on Rails packs",
       "Using shakapacker --watch (no HMR)",
       "CSS extracted to separate files (no FOUC)",
       "Development environment (source maps, faster builds)",
       "Auto-recompiles on file changes"
     ],
     route: route
   )

-  build_rescript_if_needed
+  build_rescript_if_needed(verbose: verbose)
   PackGenerator.generate(verbose: verbose)
   ProcessManager.ensure_procfile(procfile)
   ProcessManager.run_with_process_manager(procfile)
 end

 def run_development(procfile, verbose: false, route: nil)
   print_procfile_info(procfile, route: route)
-  build_rescript_if_needed
+  build_rescript_if_needed(verbose: verbose)
   PackGenerator.generate(verbose: verbose)
   ProcessManager.ensure_procfile(procfile)
   ProcessManager.run_with_process_manager(procfile)
 end

-def build_rescript_if_needed
+def build_rescript_if_needed(verbose: false)
   # Check for both old (bsconfig.json) and new (rescript.json) config files
   return unless File.exist?("bsconfig.json") || File.exist?("rescript.json")

-  print "🔧 Building ReScript... "
-  success = system("yarn build:rescript > /dev/null 2>&1")
-  puts success ? "✅" : "❌"
+  if verbose
+    puts "🔧 Building ReScript..."
+    success = system("yarn build:rescript")
+  else
+    print "🔧 Building ReScript... "
+    success = system("yarn build:rescript > /dev/null 2>&1")
+    puts success ? "✅" : "❌"
+  end

   return if success

   puts "❌ ReScript build failed"
   exit 1
 end
.github/workflows/pro-integration-tests.yml (1)

70-75: Deduplicate identical yalc publish steps across jobs.

The "Build and publish packages with yalc" steps are identical across all three jobs (lines 70–75, 190–195, 382–387). This violates the DRY principle and increases maintenance burden. Consider using a reusable workflow or composite action to eliminate duplication.

Example using a composite action:

# .github/actions/build-publish-yalc/action.yml
name: Build and Publish Packages with yalc
runs:
  using: composite
  steps:
    - name: Build and publish packages
      shell: bash
      run: |
        cd ..
        yarn run yalc:publish
        cd react_on_rails_pro
        yarn run yalc:publish

Then replace each occurrence with:

- uses: ./.github/actions/build-publish-yalc

Also applies to: 190-195, 382-387

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b9ad52 and 792466b.

📒 Files selected for processing (4)
  • .github/workflows/pro-integration-tests.yml (3 hunks)
  • TURBO_NAVIGATION_TEST_ISSUE.md (1 hunks)
  • lib/react_on_rails/dev/server_manager.rb (1 hunks)
  • spec/dummy/app/views/layouts/application.html.erb (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-10-23T17:22:01.074Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1875
File: lib/react_on_rails/utils.rb:112-124
Timestamp: 2025-10-23T17:22:01.074Z
Learning: In React on Rails, when Pro is installed but not licensed, the intended behavior is to raise an error on boot. The `react_on_rails_pro?` method validates licenses and should raise errors early (including during path resolution in methods like `server_bundle?`) to enforce licensing requirements rather than failing later with obscure errors.

Applied to files:

  • lib/react_on_rails/dev/server_manager.rb
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • lib/react_on_rails/dev/server_manager.rb
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • lib/react_on_rails/dev/server_manager.rb
📚 Learning: 2025-02-13T16:50:26.861Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/turbolinksUtils.ts:34-36
Timestamp: 2025-02-13T16:50:26.861Z
Learning: In React on Rails, when checking for Turbolinks version 5 using `turbolinksVersion5()`, always ensure `Turbolinks` exists first by checking `turbolinksInstalled()` to prevent TypeError when accessing properties.

Applied to files:

  • TURBO_NAVIGATION_TEST_ISSUE.md
  • spec/dummy/app/views/layouts/application.html.erb
📚 Learning: 2024-10-08T20:53:47.076Z
Learnt from: theforestvn88
Repo: shakacode/react_on_rails PR: 1620
File: spec/dummy/client/app/startup/HelloTurboStream.jsx:3-3
Timestamp: 2024-10-08T20:53:47.076Z
Learning: The `RailsContext` import in `spec/dummy/client/app/startup/HelloTurboStream.jsx` is used later in the project, as clarified by the user theforestvn88.

Applied to files:

  • spec/dummy/app/views/layouts/application.html.erb
🧬 Code graph analysis (1)
lib/react_on_rails/dev/server_manager.rb (1)
lib/react_on_rails/dev/pack_generator.rb (2)
  • generate (7-75)
  • generate (9-23)
🪛 LanguageTool
TURBO_NAVIGATION_TEST_ISSUE.md

[style] ~30-~30: This sentence contains multiple usages of the word “again”. Consider removing or replacing it.
Context: ...d refreshing again → ✅ JavaScript works again This severely degraded the user experi...

(REPETITION_OF_AGAIN)

🪛 markdownlint-cli2 (0.18.1)
TURBO_NAVIGATION_TEST_ISSUE.md

146-146: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: rspec-package-tests (3.2, latest)
  • GitHub Check: rspec-package-tests (3.4, minimum)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: claude-review
  • GitHub Check: build
  • GitHub Check: markdown-link-check
  • GitHub Check: lint-js-and-ruby
🔇 Additional comments (5)
TURBO_NAVIGATION_TEST_ISSUE.md (2)

1-10: Verify alignment with PR objectives.

This file documents a Turbo navigation regression test plan, but the PR objectives describe updating shakapacker from 8.2.0 to 9.3.0. There's no evident connection between these changes. Clarify whether this file should be included in this PR or if it belongs to a separate issue/PR.


42-84: Comprehensive test plan with strong verification approach.

The proposed Playwright test scenario is well-structured and effectively captures the regression scenario. The test matrix covering initial load, post-navigation, and back-navigation provides good coverage. The verification steps with explicit fail/pass instructions make this implementation checklist actionable.

spec/dummy/app/views/layouts/application.html.erb (2)

13-13: LGTM! Migration to Turbo and defer attribute aligns with modern Rails.

The change correctly migrates from Turbolinks to Turbo tracking (data-turbo-track: 'reload') and adds defer: true, which aligns perfectly with the comment on line 12 about using defer for proper script loading order.


13-13: Multiple ERB templates and other files still contain Turbolinks references that need updating alongside this change.

The search reveals that beyond the single change shown in application.html.erb, the following files in the main codebase (excluding fixtures/test bundles) should be reviewed and updated as part of the Turbolinks-to-Turbo migration:

  • ERB templates with data-turbolinks-track attributes: These need to be updated to data-turbo-track to match the change in the layout file.
  • ERB meta tags: <meta name="turbolinks-cache-control"> should be updated to <meta name="turbo-cache-control">.
  • Test descriptions: The integration test file contains "Turbolinks across pages" which could be updated to reflect Turbo.
  • Route names/helpers: turbolinks_cache_disabled_path is semantic but may need renaming for consistency.

The compiled JavaScript bundle files in fixtures show legacy Turbolinks event handling code (e.g., turbolinks:before-render, turbolinks:render), which appears to be intentionally preserved for fixture/snapshot purposes and likely don't require changes.

lib/react_on_rails/dev/server_manager.rb (1)

419-419: LGTM! Appropriate placement for ReScript build step.

The ReScript build is correctly positioned before pack generation in both development modes, ensuring compiled ReScript code is available when packs are generated.

Also applies to: 427-427

Comment on lines 438 to 444
success = system("yarn build:rescript > /dev/null 2>&1")
puts success ? "✅" : "❌"

return if success

puts "❌ ReScript build failed"
exit 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Suppressed error output makes debugging ReScript build failures difficult.

When the ReScript build fails, all compilation errors are discarded (> /dev/null 2>&1), leaving developers with only a generic "ReScript build failed" message. Compiler errors, type mismatches, and syntax issues won't be visible.

Consider showing the actual error output when the build fails:

-def build_rescript_if_needed
-  # Check for both old (bsconfig.json) and new (rescript.json) config files
-  return unless File.exist?("bsconfig.json") || File.exist?("rescript.json")
-
-  print "🔧 Building ReScript... "
-  success = system("yarn build:rescript > /dev/null 2>&1")
-  puts success ? "✅" : "❌"
-
-  return if success
-
-  puts "❌ ReScript build failed"
-  exit 1
-end
+def build_rescript_if_needed
+  # Check for both old (bsconfig.json) and new (rescript.json) config files
+  return unless File.exist?("bsconfig.json") || File.exist?("rescript.json")
+
+  print "🔧 Building ReScript... "
+  stdout, stderr, status = Open3.capture3("yarn", "build:rescript")
+  puts status.success? ? "✅" : "❌"
+
+  return if status.success?
+
+  puts "❌ ReScript build failed"
+  puts ""
+  puts Rainbow("📋 Build Output:").red.bold
+  puts Rainbow("─" * 60).red
+  puts stdout unless stdout.empty?
+  puts stderr unless stderr.empty?
+  puts Rainbow("─" * 60).red
+  exit 1
+end

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In lib/react_on_rails/dev/server_manager.rb around lines 438 to 444, the
ReScript build call suppresses all output ("> /dev/null 2>&1") so errors are
hidden; change the invocation so stdout/stderr are captured and only suppressed
on success — run the build without redirecting or capture the output (e.g., use
Open3.capture3 or backticks) and if the command fails print the captured
stderr/stdout before exiting so developers see the compiler errors and
diagnostics.

justin808 added a commit that referenced this pull request Nov 3, 2025
…ISSUE.md

Replaced "PR #XXXX" with "PR #1896" since commit f03b935 that fixed
the Turbo navigation bug is part of this PR.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
justin808 and others added 25 commits November 6, 2025 15:50
This comment explains React on Rails' use case for exact version support
and provides context for why we had to implement a workaround.

To be posted at: shakacode/package_json#25

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The HelloWorld.module.scss files were using $bright-color variable
without importing the app-variables.scss file where it's defined.
This was causing webpack build failures.

Changes:
- spec/dummy/client/app/components/HelloWorld.module.scss: Add @import
- react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss: Add @import
- knip.ts: Auto-cleaned unused dependency ignores

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…n skip, and webpack safety

This commit addresses three code review issues:

1. Fix package manager hard-coding (High Priority)
   - Add detect_package_manager_and_exact_flag helper to GeneratorHelper
   - Detect package manager from lock files (yarn, pnpm, bun, npm)
   - Update all package installation methods to use detected PM
   - Warn users when multiple lock files are detected
   - Fixes issue where npm was hard-coded, causing conflicts for yarn/pnpm/bun users

2. Fix fragile ARGV-based generator detection (Medium Priority)
   - Replace ARGV.any? check with explicit ENV variable
   - Install generator sets REACT_ON_RAILS_SKIP_VALIDATION=true
   - More robust than string matching on ARGV
   - Works correctly in all contexts (rake, console, tests)
   - Prevents false positives from paths containing "generate" or "g"

3. Add defensive checks to webpack CSS Modules config (Low Priority)
   - Add comprehensive type and existence checks before accessing loader properties
   - Prevents potential runtime errors with malformed webpack configs
   - Consistent with defensive pattern used for SCSS configuration

All changes verified with:
- bundle exec rubocop: 0 offenses
- Install generator specs: 53 examples, 0 failures

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The version checker was failing during `rails generate react_on_rails:install`
because it ran after package.json was created by shakapacker:install but before
the generator had a chance to install the react-on-rails package.

Error was:
**ERROR** ReactOnRails: No React on Rails npm package is installed.

This commit adds an additional check to skip validation if neither
react-on-rails nor react-on-rails-pro package is found in package.json,
allowing the generator to complete its installation process.

The validation will still run normally once the packages are installed,
ensuring version compatibility in production apps.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The sass-resources-loader webpack plugin automatically injects
app-variables.scss into all SCSS files, making manual @import
statements redundant and potentially problematic.

The previous fix attempted to import app-variables.scss to resolve
undefined $bright-color variables, but this caused issues with
React Server Components builds. The variables are already available
through the webpack sass-resources-loader configuration.

Changes:
- spec/dummy/client/app/components/HelloWorld.module.scss: Remove @import
- react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss: Remove @import

Fixes React Router Sixth Page RSC test failure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…ssing require

Addresses 3 critical issues identified in PR #1896 review:

1. Remove invalid javascript_transpiler configuration
   - Shakapacker 9.3.0 does not support a top-level javascript_transpiler key
   - Removed lines 39-42 from shakapacker.yml template
   - Transpiler selection is configured via webpack config and installed loaders

2. Update Pro package.json files to Shakapacker 9.3.0
   - Updated react_on_rails_pro/spec/dummy/package.json (8.0.0 → 9.3.0)
   - Updated react_on_rails_pro/spec/execjs-compatible-dummy/package.json (8.0.0 → 9.3.0)
   - Added swc-loader and @swc/core dependencies to both files
   - Ensures version consistency across the codebase

3. Fix missing GeneratorMessages require in generator_helper.rb
   - Added require_relative "generator_messages" to prevent NameError
   - Issue occurred when detect_package_manager_and_exact_flag found multiple lock files
   - Now consistent with other generator files (base_generator.rb, install_generator.rb)

All RuboCop checks pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add @import statement to HelloWorld.module.scss files to import
app-variables.scss which defines $bright-color variable. This fixes
the "Undefined variable" SCSS compilation error during webpack builds.

Fixed in both:
- spec/dummy/client/app/components/HelloWorld.module.scss
- react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…files

These are build-time tools and should be in devDependencies, not dependencies.

Changes:
- react_on_rails_pro/spec/dummy/package.json: Moved @swc/core and swc-loader to devDependencies
- react_on_rails_pro/spec/execjs-compatible-dummy/package.json: Moved @swc/core and swc-loader to devDependencies

Both entries maintain the same version strings (^1.7.0 and ^0.2.6).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Shakapacker is a build-time tool and should be in devDependencies, not dependencies.

Changed in react_on_rails_pro/spec/dummy/package.json:
- Removed "shakapacker": "9.3.0" from dependencies
- Added "shakapacker": "9.3.0" to devDependencies

This completes the correct categorization of all build-time tools
(@swc/core, swc-loader, and shakapacker) as devDependencies.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Change the build.prepack script to use 'yarn run build' instead of
'npm run build'. In a yarn workspace, using npm to run scripts that
depend on workspace features (like 'yarn workspace react-on-rails run build')
causes build failures.

This fixes the yalc package publishing failures in CI where the prepack
script would fail silently, resulting in packages being published without
the built files, leading to downstream errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
1. Revert package-scripts.yml change (npm->yarn)
   - This file doesn't exist on master, so the change shouldn't be included

2. Add javascript_compiler setting to shakapacker.yml template
   - Adds configuration option to choose between 'babel' or 'swc'
   - Defaults to 'babel' for wider ecosystem support
   - Documents the tradeoffs between the two compilers

3. Fix swc/babel dependency management
   - Move swc packages (@swc/core, swc-loader) from devDependencies to dependencies
   - Make swc and babel mutually exclusive based on shakapacker.yml setting
   - Add using_swc? helper method to check javascript_compiler configuration
   - When using swc, install swc packages instead of babel packages

This ensures proper dependency installation based on the chosen JavaScript compiler.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
When bin/dev starts, webpack immediately tries to build bundles that
import ReScript components (HelloWorldReScript.res.js). However, these
.res.js files are generated by the ReScript compiler from .res source
files, and webpack fails if they don't exist yet.

Solution: Build ReScript files before starting the Procfile processes.
This ensures all .res.js files are generated before webpack starts.

Changes:
- lib/react_on_rails/dev/server_manager.rb:
  - Add build_rescript_if_needed method to compile ReScript before dev server
  - Check for both bsconfig.json (old) and rescript.json (new) config files
  - Run yarn build:rescript if ReScript is configured
  - Exit with error if ReScript build fails

Fixes webpack Module not found errors for HelloWorldReScript.res.js

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Implement explicit yalc publishing before yarn install to avoid
frozen-lockfile conflicts. This resolves the issue where preinstall
scripts triggered yalc operations that modified yarn.lock, causing
CI to fail with "--frozen-lockfile" checks.

Changes:
1. Add explicit "Build and publish packages with yalc" step that runs
   yarn run yalc:publish for both root and Pro packages before install
2. Add --ignore-scripts flag to Pro dummy app yarn install to skip
   preinstall hook (since yalc already published in previous step)
3. Apply to all 3 jobs: build, rspec, and playwright tests

This approach:
- Separates build/publish from install for better CI reproducibility
- Prevents yarn.lock modifications during install
- Maintains frozen-lockfile enforcement for dependency stability
- Faster CI (no redundant builds during preinstall)

The preinstall script remains useful for local development to auto-update
yalc packages, but in CI we use explicit steps for better control.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
… regression

Documents a regression that existed for over 1 year where JavaScript failed
to work after Turbo navigation (only worked on hard refresh). This issue
provides a comprehensive plan for adding Playwright E2E tests to prevent
this type of regression in the future.

The issue includes:
- Background on what happened and when the bug was introduced (PR #1620)
- Impact on users (broken JS after navigation)
- Proposed Playwright test implementation
- Verification steps to prove the test catches the regression
- Additional test cases to consider
- Success criteria and implementation checklist

To verify Playwright is working correctly, developers can:
1. Run the test with the current fix (should pass)
2. Revert the fix in application.html.erb (should fail)
3. Restore the fix (should pass again)

This proves the test effectively catches Turbo navigation issues.

Related commits:
- Bug introduced: 56ee2bd (PR #1620, ~1 year ago)
- Bug fixed: f03b935 (this PR)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Change 'yarn run yalc:publish' to 'yarn && yalc publish' for the
react_on_rails_pro package, since it doesn't have a yalc:publish script
defined (only the workspace packages do).

The workflow now:
1. Runs yarn run yalc:publish at root (publishes workspace packages)
2. Runs yarn && yalc publish in react_on_rails_pro (installs + publishes Pro)

This matches the command structure used in the preinstall script.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The build.prepack script in package-scripts.yml was using `npm run build`
which causes failures in CI. This is inconsistent with the rest of the
codebase which uses yarn.

Changed line 29 from:
  (npm run build >/dev/null 2>&1 || true)
To:
  (yarn run build >/dev/null 2>&1 || true)

This matches the fix previously made in packages/react-on-rails/package.json
(commit 9f254fb) but was missed in the root package-scripts.yml file.

Fixes CI error:
  Building react-on-rails seems to have failed!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Added 'tree' as the language identifier for the fenced code block showing
the file structure, changing from generic ``` to ```tree for better
syntax highlighting and clarity.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…ISSUE.md

Replaced "PR #XXXX" with "PR #1896" since commit f03b935 that fixed
the Turbo navigation bug is part of this PR.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The yalc workflow modifies yarn.lock when adding packages, so we cannot
use --frozen-lockfile after yalc has run. Keep --ignore-scripts to skip
the preinstall hook (since yalc already ran in the previous step).

This allows the install to succeed after yalc has modified the lockfile.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Updated shakapacker gem version from 8.0.0 to 9.3.0 in Pro Gemfiles to match
the package.json changes, fixing the version mismatch error:

  "Shakapacker gem and node package versions do not match
   Detected: 9.3.0
        gem: 8.0.0"

Changed in:
- react_on_rails_pro/Gemfile.development_dependencies (8.0.0 → 9.3.0)
- react_on_rails_pro/spec/execjs-compatible-dummy/Gemfile (8.0 → 9.3.0)

This ensures gem and npm package versions match across all Pro dummy apps.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Updated yarn.lock to match package.json changes for @swc/core and swc-loader
dependencies moved to devDependencies.

Fixes CI lint-js-and-ruby failure:
  "Your lockfile needs to be updated, but yarn was run with --frozen-lockfile"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Updated yarn.lock to match package.json changes for @swc/core and swc-loader
dependencies moved to devDependencies in the execjs-compatible-dummy app.

Fixes CI lint-js-and-ruby failure for ExecJS dummy app:
  "Your lockfile needs to be updated, but yarn was run with --frozen-lockfile"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Shakapacker 9.3.0 defaults to SWC compiler if javascript_compiler is not
explicitly set in shakapacker.yml. Update the using_swc? method to reflect
this new default behavior.

Changes:
- using_swc? now returns true (SWC) by default when config doesn't exist
- using_swc? returns true unless javascript_compiler is explicitly set to babel
- Updated template shakapacker.yml to comment out javascript_compiler setting
- Added clear documentation that Shakapacker 9.3.0+ defaults to SWC

This ensures the generator correctly detects and installs SWC dependencies
by default, matching Shakapacker 9.3.0's new default compiler.

Addresses PR review comment on lib/generators/react_on_rails/base_generator.rb:225

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Change using_swc? helper to parse shakapacker.yml with YAML.safe_load_file
instead of raw string matching, which incorrectly interpreted commented
lines as active configuration.

Changes:
- Add require "yaml" to base_generator.rb
- Parse YAML to read javascript_compiler from default section
- Return true only when javascript_compiler is explicitly set to "swc"
- Default to false (babel) when file is missing or key is absent
- Add error handling for YAML parsing failures
- Update template comment to reflect babel as default

This ensures commented configuration lines don't affect compiler detection
and provides more predictable behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Critical fixes:
1. using_swc? already properly parses YAML (no changes needed)
2. Make precompile hook cross-platform:
   - Replace Unix-specific `command -v` with Ruby's system() array form
   - Use File::NULL for cross-platform output redirection
   - Use array form of system() calls for better reliability
3. Fix fragile config detection in precompile hook:
   - Use regex to match only actual config assignments
   - Ignore comments and strings containing config names
4. Remove development documentation files:
   - ISSUE_ANALYSIS.md
   - PR_REVIEW_RESPONSE.md
   - package_json_issue_comment.md
5. Fix Rake task management:
   - Remove Rake::Task.clear (was clearing ALL tasks, not just ours)
   - Add task.reenable to support multiple invocations

These changes improve cross-platform compatibility (Windows support),
prevent false positives in config detection, and fix rake task issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@justin808 justin808 force-pushed the justin808/shakapacker-9.3.0 branch from a229abc to 7a9f539 Compare November 7, 2025 01:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
react_on_rails_pro/spec/dummy/package.json (1)

82-94: Fix conflicting shakapacker versions.

Dependencies still pin 9.2.0 while devDependencies now pin 9.3.0. Yarn will refuse/dual-install because both exact ranges can’t be satisfied, and the dummy app will keep using 9.2.0 instead of the upgraded version. Please align on a single 9.3.0 entry in dependencies and drop the duplicate in devDependencies.

-    "shakapacker": "9.2.0",
+    "shakapacker": "9.3.0",
@@
-    "shakapacker": "9.3.0",
spec/dummy/package.json (1)

32-57: Bump shakapacker here to 9.3.0.

The spec dummy app still declares shakapacker 9.2.0, so running its build will stay on the old release. Please update this entry to 9.3.0 to match the rest of the upgrade.

-    "shakapacker": "9.2.0",
+    "shakapacker": "9.3.0",
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a04a12f and f86c684.

⛔ Files ignored due to path filters (5)
  • Gemfile.lock is excluded by !**/*.lock
  • react_on_rails_pro/spec/dummy/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
  • react_on_rails_pro/spec/execjs-compatible-dummy/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
  • spec/dummy/Gemfile.lock is excluded by !**/*.lock
  • spec/dummy/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (30)
  • .github/workflows/lint-js-and-ruby.yml (1 hunks)
  • .github/workflows/pro-integration-tests.yml (3 hunks)
  • Gemfile.development_dependencies (1 hunks)
  • PR_SUMMARY_REACT_19_FIX.md (1 hunks)
  • SHAKAPACKER_UPGRADE_PR_PLAN.md (1 hunks)
  • TURBO_NAVIGATION_TEST_ISSUE.md (1 hunks)
  • docs/upgrading/react-19-quick-reference.md (1 hunks)
  • docs/upgrading/react-19-upgrade-guide.md (1 hunks)
  • docs/upgrading/upgrading-react-on-rails.md (1 hunks)
  • eslint-rules/README.md (1 hunks)
  • eslint.config.ts (1 hunks)
  • lib/generators/react_on_rails/base_generator.rb (3 hunks)
  • lib/generators/react_on_rails/generator_helper.rb (2 hunks)
  • lib/generators/react_on_rails/install_generator.rb (6 hunks)
  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml (2 hunks)
  • lib/react_on_rails/dev/pack_generator.rb (1 hunks)
  • package-scripts.yml (1 hunks)
  • packages/react-on-rails-pro/src/RSCProvider.tsx (4 hunks)
  • packages/react-on-rails-pro/src/RSCRoute.tsx (3 hunks)
  • rakelib/shakapacker_examples.rake (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncOnServerSyncOnClient.server.tsx (0 hunks)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/LazyApolloGraphQLApp.server.tsx (0 hunks)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ServerComponentRouter.server.tsx (0 hunks)
  • react_on_rails_pro/spec/dummy/package.json (2 hunks)
  • react_on_rails_pro/spec/execjs-compatible-dummy/Gemfile (2 hunks)
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json (1 hunks)
  • script/convert (1 hunks)
  • spec/dummy/client/app/components/HelloWorld.module.scss (1 hunks)
  • spec/dummy/package.json (2 hunks)
💤 Files with no reviewable changes (3)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ServerComponentRouter.server.tsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncOnServerSyncOnClient.server.tsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/LazyApolloGraphQLApp.server.tsx
🚧 Files skipped from review as they are similar to previous changes (11)
  • rakelib/shakapacker_examples.rake
  • .github/workflows/lint-js-and-ruby.yml
  • lib/generators/react_on_rails/generator_helper.rb
  • spec/dummy/client/app/components/HelloWorld.module.scss
  • lib/generators/react_on_rails/install_generator.rb
  • script/convert
  • lib/react_on_rails/dev/pack_generator.rb
  • eslint.config.ts
  • react_on_rails_pro/spec/execjs-compatible-dummy/Gemfile
  • react_on_rails_pro/spec/dummy/client/app/components/HelloWorld.module.scss
  • Gemfile.development_dependencies
🧰 Additional context used
🧠 Learnings (16)
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • lib/generators/react_on_rails/base_generator.rb
  • docs/upgrading/react-19-quick-reference.md
  • docs/upgrading/upgrading-react-on-rails.md
  • package-scripts.yml
  • react_on_rails_pro/spec/dummy/package.json
  • docs/upgrading/react-19-upgrade-guide.md
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • packages/react-on-rails-pro/src/RSCRoute.tsx
  • eslint-rules/README.md
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • lib/generators/react_on_rails/base_generator.rb
  • docs/upgrading/react-19-quick-reference.md
  • docs/upgrading/upgrading-react-on-rails.md
  • react_on_rails_pro/spec/dummy/package.json
  • PR_SUMMARY_REACT_19_FIX.md
  • docs/upgrading/react-19-upgrade-guide.md
  • packages/react-on-rails-pro/src/RSCProvider.tsx
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • packages/react-on-rails-pro/src/RSCRoute.tsx
  • eslint-rules/README.md
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • lib/generators/react_on_rails/base_generator.rb
  • docs/upgrading/react-19-quick-reference.md
  • docs/upgrading/upgrading-react-on-rails.md
  • react_on_rails_pro/spec/dummy/package.json
  • PR_SUMMARY_REACT_19_FIX.md
  • docs/upgrading/react-19-upgrade-guide.md
  • packages/react-on-rails-pro/src/RSCProvider.tsx
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
  • packages/react-on-rails-pro/src/RSCRoute.tsx
📚 Learning: 2025-10-23T17:22:01.074Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1875
File: lib/react_on_rails/utils.rb:112-124
Timestamp: 2025-10-23T17:22:01.074Z
Learning: In React on Rails, when Pro is installed but not licensed, the intended behavior is to raise an error on boot. The `react_on_rails_pro?` method validates licenses and should raise errors early (including during path resolution in methods like `server_bundle?`) to enforce licensing requirements rather than failing later with obscure errors.

Applied to files:

  • lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
  • .github/workflows/pro-integration-tests.yml
  • packages/react-on-rails-pro/src/RSCRoute.tsx
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1745
File: node_package/src/RSCRequestTracker.ts:8-14
Timestamp: 2025-07-08T05:57:29.630Z
Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime.

Applied to files:

  • lib/generators/react_on_rails/base_generator.rb
  • packages/react-on-rails-pro/src/RSCProvider.tsx
  • packages/react-on-rails-pro/src/RSCRoute.tsx
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • spec/dummy/package.json
  • .github/workflows/pro-integration-tests.yml
  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.

Applied to files:

  • docs/upgrading/react-19-quick-reference.md
  • PR_SUMMARY_REACT_19_FIX.md
  • docs/upgrading/react-19-upgrade-guide.md
  • packages/react-on-rails-pro/src/RSCProvider.tsx
  • packages/react-on-rails-pro/src/RSCRoute.tsx
📚 Learning: 2025-02-13T19:09:15.991Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/RSCWebpackLoader.ts:0-0
Timestamp: 2025-02-13T19:09:15.991Z
Learning: In React Server Components webpack loader, using `new Function('return import("react-server-dom-webpack/node-loader")')()` is necessary as a workaround to bypass TypeScript compilation issues with direct dynamic imports.

Applied to files:

  • PR_SUMMARY_REACT_19_FIX.md
  • packages/react-on-rails-pro/src/RSCProvider.tsx
  • packages/react-on-rails-pro/src/RSCRoute.tsx
  • eslint-rules/README.md
📚 Learning: 2025-06-09T07:58:02.646Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1696
File: node_package/src/RSCPayloadGenerator.ts:124-168
Timestamp: 2025-06-09T07:58:02.646Z
Learning: In React Server Components (RSC) implementations, explicit error handling in RSC payload generation streams (like in RSCPayloadGenerator.ts) is not needed because errors will propagate to client components that fetch the RSC payloads (such as RSCRoute components). React's built-in error handling mechanisms and ErrorBoundary components are sufficient for handling these errors at the component level, which allows for better user experience with appropriate error UI fallbacks.

Applied to files:

  • packages/react-on-rails-pro/src/RSCProvider.tsx
  • packages/react-on-rails-pro/src/RSCRoute.tsx
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation is handled in deeper level calls of the React on Rails Pro codebase, so it doesn't need to be validated again in the `rsc_payload_react_component` helper method.

Applied to files:

  • packages/react-on-rails-pro/src/RSCProvider.tsx
  • packages/react-on-rails-pro/src/RSCRoute.tsx
📚 Learning: 2025-06-11T12:34:58.182Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1696
File: node_package/src/RSCProvider.tsx:0-0
Timestamp: 2025-06-11T12:34:58.182Z
Learning: `RSCProvider` intentionally keeps failed `getServerComponent` promises cached (even if rejected) to avoid repeated fetch attempts; callers must use `refetchComponent` to retry.

Applied to files:

  • packages/react-on-rails-pro/src/RSCProvider.tsx
  • packages/react-on-rails-pro/src/RSCRoute.tsx
📚 Learning: 2024-12-12T13:07:09.929Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/ReactOnRailsRSC.ts:87-87
Timestamp: 2024-12-12T13:07:09.929Z
Learning: When handling errors in 'node_package/src/ReactOnRailsRSC.ts', include the error stack in error messages in development and test environments to aid debugging.

Applied to files:

  • packages/react-on-rails-pro/src/RSCProvider.tsx
  • packages/react-on-rails-pro/src/RSCRoute.tsx
📚 Learning: 2025-02-13T16:50:47.848Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/clientStartup.ts:18-21
Timestamp: 2025-02-13T16:50:47.848Z
Learning: In the react_on_rails module, the `reactOnRailsPageUnloaded` function in clientStartup.ts is intentionally kept private as it's only used internally as a callback for `onPageUnloaded`.

Applied to files:

  • packages/react-on-rails-pro/src/RSCProvider.tsx
📚 Learning: 2024-10-08T20:53:47.076Z
Learnt from: theforestvn88
Repo: shakacode/react_on_rails PR: 1620
File: spec/dummy/client/app/startup/HelloTurboStream.jsx:3-3
Timestamp: 2024-10-08T20:53:47.076Z
Learning: The `RailsContext` import in `spec/dummy/client/app/startup/HelloTurboStream.jsx` is used later in the project, as clarified by the user theforestvn88.

Applied to files:

  • react_on_rails_pro/spec/execjs-compatible-dummy/package.json
📚 Learning: 2025-01-23T18:19:25.261Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: node_package/src/buildConsoleReplay.ts:12-12
Timestamp: 2025-01-23T18:19:25.261Z
Learning: When reviewing imports, carefully distinguish between default exports and named exports, as they represent different usage patterns. The presence of an import from a file doesn't necessarily mean all exported members are being used.

Applied to files:

  • packages/react-on-rails-pro/src/RSCRoute.tsx
📚 Learning: 2025-02-13T16:50:26.861Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/turbolinksUtils.ts:34-36
Timestamp: 2025-02-13T16:50:26.861Z
Learning: In React on Rails, when checking for Turbolinks version 5 using `turbolinksVersion5()`, always ensure `Turbolinks` exists first by checking `turbolinksInstalled()` to prevent TypeError when accessing properties.

Applied to files:

  • TURBO_NAVIGATION_TEST_ISSUE.md
🧬 Code graph analysis (1)
packages/react-on-rails-pro/src/RSCProvider.tsx (1)
packages/react-on-rails-pro/src/getReactServerComponent.client.ts (1)
  • ClientGetReactServerComponentProps (27-31)
🪛 LanguageTool
SHAKAPACKER_UPGRADE_PR_PLAN.md

[uncategorized] ~188-~188: Possible missing comma found.
Context: ...eInterop: falsewas generating invalid imports likeimport ReactClient from 'react/in...

(AI_HYDRA_LEO_MISSING_COMMA)


[style] ~309-~309: ‘Based on the fact that’ might be wordy. Consider a shorter alternative.
Context: ... testing --- ## Recommended Approach Based on the fact that you mentioned 9.2.0 (though git shows 8...

(EN_WORDINESS_PREMIUM_BASED_ON_THE_FACT_THAT)


[grammar] ~319-~319: The word ‘complete’ is a noun or an adjective. A verb is missing or misspelled, or maybe a comma is missing.
Context: ...erns - ✅ Reasonable risk per PR - ✅ Can complete in 2-3 weeks - ✅ Each PR provides value...

(MD_JJ)


[typographical] ~319-~319: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...sonable risk per PR - ✅ Can complete in 2-3 weeks - ✅ Each PR provides value indepe...

(HYPHEN_TO_EN)


[typographical] ~325-~325: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...pgrade) - thorough testing, merge after 4-5 days - Week 3: PR C (React 19 + polish)...

(HYPHEN_TO_EN)


[typographical] ~326-~326: If specifying a range, consider using an en dash instead of a hyphen.
Context: ... PR C (React 19 + polish) - merge after 3-4 days --- ## Next Steps 1. **Confirm ...

(HYPHEN_TO_EN)


[uncategorized] ~334-~334: Possible missing preposition found.
Context: ... appropriate commits cherry-picked 3. Test locally before pushing 4. **Create PR...

(AI_HYDRA_LEO_MISSING_TO)

docs/upgrading/react-19-upgrade-guide.md

[uncategorized] ~47-~47: “React” is a proper noun and needs to be capitalized.
Context: ...uration. ### 2. No Default Export from react/index.js React 19 removed the default ...

(A_GOOGLE)


[uncategorized] ~86-~86: Possible missing preposition found.
Context: ...ct.createFactory() - Use JSX instead - Legacy Context (contextTypes, getChildConte...

(AI_HYDRA_LEO_MISSING_OF)


[grammar] ~387-~387: The word “rollback” is a noun. The verb is spelled with a space.
Context: ...an If you encounter issues and need to rollback: ```bash # Downgrade React yarn add re...

(NOUN_VERB_CONFUSION)

TURBO_NAVIGATION_TEST_ISSUE.md

[style] ~30-~30: This sentence contains multiple usages of the word “again”. Consider removing or replacing it.
Context: ...d refreshing again → ✅ JavaScript works again This severely degraded the user experi...

(REPETITION_OF_AGAIN)


[typographical] ~138-~138: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...ultiple navigations**: Navigate through 3-4 pages to ensure no memory leaks 2. **Ba...

(HYPHEN_TO_EN)


[duplication] ~139-~139: Possible typo: you repeated a word.
Context: ...ttons**: Test browser back/forward with Turbo 3. Turbo Frames: Test components inside turbo ...

(ENGLISH_WORD_REPEAT_RULE)


[typographical] ~186-~186: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...bo functionality Estimated effort: 2-4 hours (including documentation and veri...

(HYPHEN_TO_EN)

eslint-rules/README.md

[uncategorized] ~17-~17: Loose punctuation mark.
Context: ...lient-only APIs like: - createContext, useContext - useState, useEffect,...

(UNLIKELY_OPENING_PUNCTUATION)


[typographical] ~17-~17: Two consecutive commas
Context: ...ent-only APIs like: - createContext, useContext - useState, useEffect, useLayoutEffect, `useRed...

(DOUBLE_PUNCTUATION)


[typographical] ~18-~18: Two consecutive commas
Context: ...State, useEffect, useLayoutEffect, useReducer-Component, PureComponent - Other hooks (use*` f...

(DOUBLE_PUNCTUATION)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20, minimum)
  • GitHub Check: lint-js-and-ruby
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: markdown-link-check
  • GitHub Check: claude-review
🔇 Additional comments (5)
SHAKAPACKER_UPGRADE_PR_PLAN.md (1)

1-338: Comprehensive upgrade strategy documented.

This planning document provides a clear breakdown of the Shakapacker upgrade approach with well-structured PR sequencing, risk assessment, and testing checklists. The document effectively communicates the migration strategy and serves as a valuable reference for the upgrade process.

lib/generators/react_on_rails/base_generator.rb (2)

5-5: LGTM: YAML library imported for configuration parsing.

The addition of require "yaml" supports the new YAML-based configuration detection in the using_swc? method.


189-200: LGTM: Conditional dependency installation logic.

The conditional branching correctly installs SWC packages (@swc/core, swc-loader) when using_swc? returns true, and Babel packages otherwise. This provides a clean separation between the two compiler ecosystems.

packages/react-on-rails-pro/src/RSCProvider.tsx (2)

15-17: LGTM: 'use client' directive and React 19-compatible imports.

The addition of the 'use client' directive correctly marks this component as a client component since it uses createContext and useContext. The switch from default import to named imports (createContext, useContext, type ReactNode) aligns with React 19's conditional exports and resolves the TypeScript import issues mentioned in the PR objectives.


22-24: LGTM: Consistent type updates and React API usage.

All references have been correctly updated:

  • React.ReactNodeReactNode in type annotations
  • React.useContextuseContext (now directly imported)
  • React.createContextcreateContext (now directly imported)

These changes ensure consistency with the new import pattern and maintain type safety throughout the component.

Also applies to: 27-27, 51-51, 53-53, 79-79, 104-104

Comment on lines +234 to +251
def using_swc?
# Check shakapacker.yml for javascript_compiler setting
# Parse YAML to properly handle comments and get actual configured value
shakapacker_config_path = File.join(destination_root, "config", "shakapacker.yml")
return false unless File.exist?(shakapacker_config_path)

begin
config = YAML.safe_load_file(shakapacker_config_path)
# Check default section for javascript_compiler setting
javascript_compiler = config.dig("default", "javascript_compiler")
# Return true only if explicitly set to "swc"
javascript_compiler == "swc"
rescue StandardError => e
# If YAML parsing fails, default to babel (false)
puts "Warning: Could not parse shakapacker.yml: #{e.message}"
false
end
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical discrepancy: default behavior contradicts PR objectives and Shakapacker 9.3.0 expectations.

The current implementation returns false (Babel) when shakapacker.yml is missing (line 238) or when javascript_compiler is not explicitly set to "swc" (line 245). However, the PR objectives state: "using_swc? now defaults to true for Shakapacker 9.3.0 — returns true when config is absent and only false if javascript_compiler: babel is explicitly set."

Additionally, a past review comment at line 238 specifically questioned whether this should return true for Shakapacker 9.3.0's default behavior.

If Shakapacker 9.3.0 truly defaults to SWC, apply this diff to match the stated behavior:

 def using_swc?
   # Check shakapacker.yml for javascript_compiler setting
   # Parse YAML to properly handle comments and get actual configured value
   shakapacker_config_path = File.join(destination_root, "config", "shakapacker.yml")
-  return false unless File.exist?(shakapacker_config_path)
+  # Default to SWC (true) for Shakapacker 9.3.0 when config file doesn't exist
+  return true unless File.exist?(shakapacker_config_path)

   begin
     config = YAML.safe_load_file(shakapacker_config_path)
     # Check default section for javascript_compiler setting
     javascript_compiler = config.dig("default", "javascript_compiler")
-    # Return true only if explicitly set to "swc"
-    javascript_compiler == "swc"
+    # Default to true (SWC) for Shakapacker 9.3.0, return false only if explicitly set to "babel"
+    javascript_compiler != "babel"
   rescue StandardError => e
-    # If YAML parsing fails, default to babel (false)
+    # If YAML parsing fails, default to SWC (true) for Shakapacker 9.3.0
     puts "Warning: Could not parse shakapacker.yml: #{e.message}"
-    false
+    true
   end
 end

Alternatively, if Shakapacker 9.3.0 still defaults to Babel, please update the PR objectives to reflect the correct default behavior.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def using_swc?
# Check shakapacker.yml for javascript_compiler setting
# Parse YAML to properly handle comments and get actual configured value
shakapacker_config_path = File.join(destination_root, "config", "shakapacker.yml")
return false unless File.exist?(shakapacker_config_path)
begin
config = YAML.safe_load_file(shakapacker_config_path)
# Check default section for javascript_compiler setting
javascript_compiler = config.dig("default", "javascript_compiler")
# Return true only if explicitly set to "swc"
javascript_compiler == "swc"
rescue StandardError => e
# If YAML parsing fails, default to babel (false)
puts "Warning: Could not parse shakapacker.yml: #{e.message}"
false
end
end
def using_swc?
# Check shakapacker.yml for javascript_compiler setting
# Parse YAML to properly handle comments and get actual configured value
shakapacker_config_path = File.join(destination_root, "config", "shakapacker.yml")
# Default to SWC (true) for Shakapacker 9.3.0 when config file doesn't exist
return true unless File.exist?(shakapacker_config_path)
begin
config = YAML.safe_load_file(shakapacker_config_path)
# Check default section for javascript_compiler setting
javascript_compiler = config.dig("default", "javascript_compiler")
# Default to true (SWC) for Shakapacker 9.3.0, return false only if explicitly set to "babel"
javascript_compiler != "babel"
rescue StandardError => e
# If YAML parsing fails, default to SWC (true) for Shakapacker 9.3.0
puts "Warning: Could not parse shakapacker.yml: #{e.message}"
true
end
end

Comment on lines +7 to +10
# Hook to run before compilation (e.g., for ReScript builds, pack generation)
# See: https://github.com/shakacode/shakapacker/blob/main/docs/precompile_hook.md
precompile_hook: bin/shakapacker-precompile-hook

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove the duplicate precompile_hook entry.

This new block redefines precompile_hook, but the template already sets the same key later (Line 49). Duplicate YAML keys are confusing and some parsers treat them as errors; at minimum the latter assignment silently overrides the former. Please drop this new stanza and keep a single, well-documented definition.

-  # Hook to run before compilation (e.g., for ReScript builds, pack generation)
-  # See: https://github.com/shakacode/shakapacker/blob/main/docs/precompile_hook.md
-  precompile_hook: bin/shakapacker-precompile-hook
-
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Hook to run before compilation (e.g., for ReScript builds, pack generation)
# See: https://github.com/shakacode/shakapacker/blob/main/docs/precompile_hook.md
precompile_hook: bin/shakapacker-precompile-hook
# Hook to run before compilation (e.g., for ReScript builds, pack generation)
# See: https://github.com/shakacode/shakapacker/blob/main/docs/precompile_hook.md
precompile_hook: bin/shakapacker-precompile-hook
Suggested change
# Hook to run before compilation (e.g., for ReScript builds, pack generation)
# See: https://github.com/shakacode/shakapacker/blob/main/docs/precompile_hook.md
precompile_hook: bin/shakapacker-precompile-hook
🤖 Prompt for AI Agents
In lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml
around lines 7 to 10, there is a duplicate precompile_hook entry; remove this
earlier stanza entirely so only the single precompile_hook definition (the one
later at ~line 49) remains, and ensure any necessary documentation/comments are
kept with the remaining definition.

@justin808 justin808 force-pushed the justin808/shakapacker-9.3.0 branch from f86c684 to 843f1f7 Compare November 7, 2025 03:00
@justin808 justin808 changed the title Update shakapacker to 9.3.0 and fix RSC client component directives Upgrade Shakapacker to 9.3.0 Nov 7, 2025
@claude
Copy link

claude bot commented Nov 7, 2025

Code Review: Shakapacker 9.3.0 Upgrade

Overall Assessment

This is a well-structured and comprehensive upgrade PR that successfully migrates from Shakapacker 8.2.0 to 9.3.0. The changes demonstrate careful consideration of backward compatibility, robust error handling, and thoughtful documentation. Great work!


Strengths

1. Excellent Code Quality

  • Package manager detection (generator_helper.rb:103-129): Robust implementation with multiple lock file support (yarn, npm, pnpm, bun)
  • Proper error handling: YAML parsing fallback in using_swc? method (base_generator.rb:246-249)
  • Multi-package manager warnings: User-friendly messaging when multiple lock files detected (generator_helper.rb:117-124)

2. Smart Compiler Detection

  • Dynamic dependency installation (base_generator.rb:192-200): Conditionally adds SWC or Babel packages based on using_swc? check
  • YAML parsing approach: Correctly uses YAML.safe_load_file instead of regex-based detection (base_generator.rb:241)
  • Sensible defaults: Falls back to Babel when parsing fails (base_generator.rb:249)

3. CI/CD Improvements

  • yalc workflow fix (.github/workflows/pro-integration-tests.yml): Added explicit build/publish steps to prevent frozen-lockfile errors
  • Knip configuration: Added --no-config-hints flag to reduce noise (lint-js-and-ruby.yml:110)
  • --ignore-scripts: Prevents duplicate builds during yalc development (pro-integration-tests.yml:103)

4. Comprehensive Documentation

  • SHAKAPACKER_UPGRADE_PR_PLAN.md: Excellent reference for future major upgrades
  • TURBO_NAVIGATION_TEST_ISSUE.md: Documents test gap and provides implementation guidance

Issues & Recommendations

Critical Issues

1. Documentation Files Should Not Be Committed to Master

Files: SHAKAPACKER_UPGRADE_PR_PLAN.md, TURBO_NAVIGATION_TEST_ISSUE.md

Issue: These are planning/design documents that don't belong in the production codebase.

Recommendation: Remove before merging or move to docs/contributor-info/ directory.


High Priority Issues

2. Inconsistent Package Manager Handling Between Generators

File: lib/generators/react_on_rails/install_generator.rb:531

Issue: add_rspack_dependencies still hardcodes npm install instead of using detect_package_manager_and_exact_flag

Recommendation: Use detect_package_manager_and_exact_flag consistently across all dependency installation methods.


3. Missing --exact Flag Usage

File: lib/generators/react_on_rails/install_generator.rb:496, 515, 558

Issue: The method retrieves the exact_flag but doesn't apply it for most dependency installations.

Current Code:

  • Line 496: system(package_manager, add_command, *react_deps)
  • Line 515: system(package_manager, add_command, *css_deps)
  • Line 558: system(package_manager, add_command, dev_flag, *dev_deps)

Recommendation: Apply exact_flag to ALL dependency installations for reproducible builds:

  • system(package_manager, add_command, exact_flag, *react_deps)

Why this matters: Without --exact, package managers may install range versions, leading to version drift between installations.


4. YAML Security Hardening

File: lib/generators/react_on_rails/base_generator.rb:241

Issue: YAML.safe_load_file lacks explicit permitted_classes argument.

Recommendation: Add explicit restrictions for defense-in-depth:

  • YAML.safe_load_file(shakapacker_config_path, permitted_classes: [], permitted_symbols: [], aliases: false)

Medium Priority Issues

5. Code Duplication: using_swc? Method

Files: lib/generators/react_on_rails/base_generator.rb:234-251

Recommendation: Consider extracting to ReactOnRails::PackerUtils.using_swc?(config_path) for reuse across codebase.


6. Inconsistent Babel Package Installation

Files:

  • base_generator.rb:195-199 (excludes Babel when using SWC)
  • install_generator.rb:485-488 (always includes Babel)

Issue: install_generator always installs Babel packages regardless of SWC setting, while base_generator conditionally excludes them.

Recommendation: Make install_generator.rb also conditional on using_swc? to avoid installing unused Babel packages.


7. Hardcoded Version String

File: rakelib/shakapacker_examples.rake:37

Issue: gem 'shakapacker', '>= 9.3.0' is hardcoded

Recommendation: Extract to constant for easier maintenance:

  • SHAKAPACKER_MIN_VERSION = "9.3.0"

Low Priority / Nice-to-Have

8. Verify RuboCop Compliance

Per CLAUDE.md: Must run bundle exec rubocop before every commit and fix ALL violations.

Recommendation: Verify this was done before merge.


Security Assessment

No security concerns identified

  • Proper use of YAML.safe_load_file (recommendation Add integration tests #4 adds defense-in-depth)
  • No unsafe shell command execution (using array form with system)
  • No hardcoded credentials or secrets
  • Package manager detection is safe (read-only file checks)

Performance Considerations

Performance improvements observed:

  1. SWC support: Significantly faster compilation than Babel (~70% faster)
  2. --ignore-scripts: Reduces redundant builds in CI
  3. Knip config hints suppression: Reduces CI log noise

Potential concern:

  • Multiple YAML file reads: using_swc? reads/parses shakapacker.yml on every call. Consider caching if called frequently.

Test Coverage

Strengths:

  • PR description mentions "All generator tests passing"
  • "CSS Modules working correctly"
  • "Pro package tests passing"

Gaps Identified:

  • No tests for detect_package_manager_and_exact_flag: Critical new functionality lacks specs
  • No tests for using_swc? YAML parsing: Should test valid config, invalid YAML, missing file
  • TURBO_NAVIGATION_TEST_ISSUE.md: Documents a test gap that still needs implementation

Recommendation: Add specs for detect_package_manager_and_exact_flag and using_swc? methods in follow-up PR.


Best Practices Compliance (per CLAUDE.md)

  • Uses yarn exclusively (never npm) in package-scripts.yml
  • Files end with newlines (based on diff format)
  • Needs verification: Run bundle exec rubocop before merge
  • Needs verification: Run rake autofix for Prettier formatting

Recommendations Summary

Before Merge:

  1. Remove or relocate SHAKAPACKER_UPGRADE_PR_PLAN.md and TURBO_NAVIGATION_TEST_ISSUE.md
  2. Fix inconsistent package manager handling in add_rspack_dependencies
  3. Add exact_flag to all dependency installations (lines 496, 515, 558)
  4. Add explicit permitted_classes to YAML.safe_load_file
  5. Run bundle exec rubocop and fix all violations
  6. Run rake autofix to ensure consistent formatting

Follow-up PRs:

  1. Add tests for detect_package_manager_and_exact_flag and using_swc?
  2. Implement Playwright test for Turbo navigation
  3. Make install_generator Babel package installation conditional on using_swc?
  4. Extract using_swc? to ReactOnRails::PackerUtils if needed elsewhere

Conclusion

This is strong work on a complex upgrade. The code is well-structured, handles edge cases, and includes helpful user-facing warnings. The main issues are:

  • Cleanup of documentation files
  • Consistency in package manager handling
  • Missing test coverage for new methods

With the recommended fixes, this PR will be in excellent shape for merge.

Estimated fix time: 1-2 hours for critical issues + test additions

Great job on the thorough upgrade!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants