Skip to content

Conversation

@justin808
Copy link
Member

@justin808 justin808 commented Nov 26, 2025

Summary

  • Add using_swc? helper method to detect SWC configuration in shakapacker.yml
  • Automatically install SWC dependencies (@swc/core, swc-loader) when SWC is configured
  • Update spec/dummy to include SWC packages

Key Changes

1. Enhanced using_swc? Helper

  • Parses shakapacker.yml for javascript_transpiler setting
  • Returns true when SWC is explicitly configured
  • Returns true for Shakapacker 9.3.0+ when not specified (SWC is the default)
  • Returns true for fresh installations (SWC is recommended)

2. Generator Updates

  • Add SWC_DEPENDENCIES constant with @swc/core and swc-loader
  • Install SWC deps automatically when using_swc? returns true
  • Add to devDependencies since they're build-time tools

3. spec/dummy Updates

  • Add @swc/core and swc-loader to devDependencies
  • Matches the javascript_transpiler: swc setting already in shakapacker.yml

Testing

  • Added comprehensive RSpec tests for using_swc? helper
  • All existing tests pass
  • RuboCop checks pass

Test Plan

  • Test generator with Shakapacker 9.3.0+
  • Verify SWC detection logic
  • Test fallback to Babel when explicitly configured

Closes #1956

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added automatic SWC transpiler support detection based on Shakapacker configuration
    • SWC dependencies are now automatically installed during project setup when applicable (Shakapacker 9.3.0+)
    • Graceful fallback handling for configuration parsing and dependency installation
  • Tests

    • Added comprehensive test coverage for SWC configuration detection and dependency installation

✏️ Tip: You can customize this high-level summary in your review settings.

Add using_swc? helper method to detect SWC configuration:
- Parses shakapacker.yml for javascript_transpiler setting
- Returns true when SWC is explicitly configured
- Returns true for Shakapacker 9.3.0+ when not specified (SWC default)
- Returns true for fresh installations (SWC is recommended)

Add SWC dependency installation to generator:
- Add SWC_DEPENDENCIES constant (@swc/core, swc-loader)
- Install SWC deps automatically when using_swc? returns true
- Add to devDependencies since they're build-time tools

Update spec/dummy to include SWC packages:
- Add @swc/core and swc-loader to devDependencies
- Matches the javascript_transpiler: swc setting in shakapacker.yml

Add comprehensive tests for using_swc? helper:
- Test explicit swc config returns true
- Test explicit babel config returns false
- Test missing config defaults to SWC for 9.3.0+
- Test missing file defaults to SWC
- Test invalid YAML defaults to SWC

Closes #1956

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

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 26, 2025

Walkthrough

Introduces SWC configuration detection in the generator helper with automatic Shakapacker version checking and shakapacker.yml parsing. Adds conditional SWC dependency installation in the JS dependency manager. Includes comprehensive tests for the new SWC detection logic.

Changes

Cohort / File(s) Change Summary
SWC Detection & Configuration
react_on_rails/lib/generators/react_on_rails/generator_helper.rb
Adds using_swc? public method that detects SWC via shakapacker.yml config or Shakapacker 9.3.0+ version check; includes detect_swc_configuration, parse_shakapacker_yml, and shakapacker_version_9_3_or_higher? helpers with resilient YAML parsing and version detection.
SWC Dependency Installation
react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
Adds SWC_DEPENDENCIES constant and add_swc_dependencies private method; conditionally installs SWC dependencies via add_js_dependencies when using_swc? is true, with error handling and manual install fallback.
Test Suite
react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb, react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb, react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
Comprehensive tests for using_swc? detection across config scenarios (swc, babel, missing, parse errors); integration test verifying SWC dependencies installed by default; test helper methods for configurable SWC flag.
Development Dependencies
react_on_rails/spec/dummy/package.json
Adds @swc/core@^1.7.0 and swc-loader@^0.2.6 as development dependencies.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • generator_helper.rb: Multiple fallback paths in YAML parsing and version detection require careful attention to error handling and precedence logic.
  • js_dependency_manager.rb: Verify SWC dependency installation mirrors existing patterns and error handling is consistent.
  • Test coverage: Comprehensive test suite validates detection logic across edge cases; verify mocking and setup/teardown are correct.

Possibly related issues

Possibly related PRs

Suggested labels

review-needed, full-ci

Suggested reviewers

  • alexeyr-ci
  • AbanoubGhadban
  • Judahmeek

Poem

🐰 ✨ A transpiler so swift, now bundled with care,
SWC detection in springtime air!
Version checks, configs parsed just right,
Dependencies installed, shining bright! 🚀

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Linked Issues check ❓ Inconclusive The PR addresses core SWC detection and dependency installation but does not fully cover all stated objectives from issue #1956, particularly generated shakapacker.yml configuration and documentation. Verify whether generated shakapacker.yml configuration updates, documentation, and migration notes are planned as follow-up work or out of scope for this PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Improve SWC compiler detection and default dependencies' directly and clearly summarizes the main changes: enhanced SWC detection logic and automatic SWC dependency installation.
Out of Scope Changes check ✅ Passed All changes in the PR are directly related to SWC detection and dependency management, with no unrelated modifications outside the stated objectives.
✨ 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 jg/swc-detection-fix

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16b3908 and c7f23d7.

📒 Files selected for processing (6)
  • react_on_rails/lib/generators/react_on_rails/generator_helper.rb (1 hunks)
  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb (3 hunks)
  • react_on_rails/spec/dummy/package.json (2 hunks)
  • react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb (1 hunks)
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb (1 hunks)
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rb,rake}

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS run bundle exec rubocop and fix ALL violations before every commit/push

Files:

  • react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
  • react_on_rails/lib/generators/react_on_rails/generator_helper.rb
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS ensure files end with a newline character before committing/pushing

Files:

  • react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
  • react_on_rails/lib/generators/react_on_rails/generator_helper.rb
🧠 Learnings (14)
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to spec/dummy/e2e/playwright/**/*.spec.js : Use Rails helpers (`appFactories`, `appEval`) in Playwright tests instead of UI-based setup to leverage factory_bot and arbitrary Ruby code execution

Applied to files:

  • react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.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:

  • react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb
  • react_on_rails/lib/generators/react_on_rails/generator_helper.rb
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package

Applied to files:

  • react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb
  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
  • react_on_rails/lib/generators/react_on_rails/generator_helper.rb
📚 Learning: 2025-02-13T14:29:49.267Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: spec/react_on_rails/utils_spec.rb:218-218
Timestamp: 2025-02-13T14:29:49.267Z
Learning: In RSpec tests, prefer using local variables over constants within test blocks to avoid constant redefinition warnings and maintain better test isolation.

Applied to files:

  • react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.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:

  • react_on_rails/spec/react_on_rails/generators/generator_helper_spec.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:

  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
  • react_on_rails/lib/generators/react_on_rails/generator_helper.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:

  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
  • react_on_rails/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/lib/generators/react_on_rails/js_dependency_manager.rb
  • react_on_rails/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/spec/dummy/package.json
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
📚 Learning: 2024-07-27T10:08:35.868Z
Learnt from: theforestvn88
Repo: shakacode/react_on_rails PR: 1620
File: spec/dummy/client/app/startup/HelloTurboStream.jsx:3-3
Timestamp: 2024-07-27T10:08:35.868Z
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/spec/dummy/package.json
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to sig/react_on_rails/**/*.rbs : In RBS type signature files, define type signatures that correspond to Ruby files in `lib/react_on_rails/`

Applied to files:

  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.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:

  • react_on_rails/lib/generators/react_on_rails/generator_helper.rb
🧬 Code graph analysis (3)
react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb (2)
react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb (1)
  • destination_root (25-27)
react_on_rails/lib/generators/react_on_rails/generator_helper.rb (1)
  • using_swc? (143-147)
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb (1)
react_on_rails/lib/generators/react_on_rails/generator_helper.rb (1)
  • package_json (7-20)
react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb (1)
react_on_rails/lib/generators/react_on_rails/generator_helper.rb (1)
  • using_swc? (143-147)
⏰ 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). (5)
  • GitHub Check: dummy-app-integration-tests (3.4, 22, latest)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: build
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: claude-review
🔇 Additional comments (14)
react_on_rails/spec/dummy/package.json (1)

39-39: LGTM! SWC dependencies correctly added to devDependencies.

The added @swc/core and swc-loader packages align with the javascript_transpiler: swc setting in shakapacker.yml and match the SWC_DEPENDENCIES constant defined in the generator.

Also applies to: 59-59

react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb (1)

15-23: LGTM! Good test coverage for default SWC installation.

The test correctly verifies that SWC dependencies are installed by default for the "without args" scenario, aligning with the Shakapacker 9.3.0+ default behavior.

react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb (2)

29-35: LGTM! Well-designed test helper for SWC behavior.

The using_swc? mock method with a sensible default (true) and an attr_writer for overriding enables flexible test scenarios for SWC dependency installation logic.


119-123: LGTM! Consistent with other dependency constant tests.

The test follows the same pattern as other *_DEPENDENCIES constant tests in this file, ensuring SWC_DEPENDENCIES contains the expected packages.

react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb (3)

112-125: LGTM! Proper test setup with memoization reset.

The setup correctly clears the memoized @using_swc value before each test and manages the temporary config directory lifecycle. This ensures test isolation.


126-184: LGTM! Comprehensive coverage of configuration scenarios.

The tests cover the key scenarios well:

  • Explicit swc and babel configurations
  • Missing javascript_transpiler setting (falls back to version check)
  • Non-existent shakapacker.yml (fresh installation)
  • YAML parse errors (graceful fallback)

186-236: LGTM! Version boundary tests are well-structured.

The tests correctly verify the behavior when Shakapacker version is 9.3.0+ (SWC default), below 9.3.0 (Babel default), and when version detection fails (defaults to latest/SWC).

react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb (3)

102-107: LGTM! SWC dependencies correctly defined.

The constant follows the established pattern with .freeze and includes the essential SWC packages. The comment documenting the 9.3.0+ default and performance benefit is helpful.


128-129: LGTM! Clean conditional for SWC installation.

The pattern mirrors the Rspack conditional above and correctly gates SWC dependency installation on the using_swc? helper from GeneratorHelper.


244-262: LGTM! Consistent implementation with other dependency methods.

The add_swc_dependencies method follows the established pattern:

  • Informative status message (with performance note)
  • dev: true for build-time tools
  • Graceful failure with warning and manual install instructions
  • Rescue block for unexpected errors
react_on_rails/lib/generators/react_on_rails/generator_helper.rb (4)

127-147: LGTM! Well-documented public API with proper memoization.

The using_swc? method follows the established memoization pattern from shakapacker_version_9_or_higher? and includes thorough documentation explaining the detection logic and caching behavior.


149-167: LGTM! Clear detection logic with correct precedence.

The implementation correctly prioritizes:

  1. Explicit javascript_transpiler setting from config
  2. Version-based default (SWC for 9.3.0+)
  3. Fresh installation fallback

Using dig for safe nested access is a good defensive choice.


169-186: LGTM! Robust YAML parsing with backward compatibility.

The cascading fallback strategy handles different Psych versions gracefully:

  1. Modern Psych with all options
  2. Psych without aliases: parameter
  3. Legacy fallback with safe_load + File.read
  4. Empty hash on any parse failure

This ensures the generator works across different Ruby versions.


188-197: LGTM! Consistent with existing version check pattern.

The shakapacker_version_9_3_or_higher? helper mirrors the structure of shakapacker_version_9_or_higher? and correctly defaults to true (latest version assumption) when version detection fails.


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 26, 2025

Code Review: PR #2135 - Improve SWC compiler detection and default dependencies

Summary

This PR adds intelligent SWC (Speedy Web Compiler) detection and automatic dependency installation for the React on Rails generator. Overall, the implementation is well-designed and production-ready with excellent test coverage and error handling.


✅ Strengths

1. Excellent Error Handling & Graceful Degradation

The code follows a defensive programming approach that aligns well with the project's error handling philosophy:

def parse_shakapacker_yml(path)
  require "yaml"
  YAML.load_file(path, aliases: true)
rescue ArgumentError
  # Older Psych versions don't support the aliases parameter
  YAML.load_file(path)
rescue StandardError
  # If we can't parse the file, return empty config
  {}
end
  • ✅ Handles both old and new Psych versions
  • ✅ Returns empty config instead of raising exceptions
  • ✅ Prevents generator crashes from malformed YAML files

2. Smart Default Behavior

The detection logic makes sensible assumptions:

  • Explicitly configured transpilers take precedence (babel vs swc)
  • Defaults to SWC for Shakapacker 9.3.0+ (matches upstream default)
  • Assumes latest version for fresh installs (optimistic but safe)
  • Falls back gracefully when version detection fails

3. Comprehensive Test Coverage

The specs cover all edge cases:

 Explicit SWC configuration
 Explicit Babel configuration  
 No transpiler specified (version-based default)
 Missing shakapacker.yml
 Malformed YAML parsing errors

4. Proper Memoization

def using_swc?
  return @using_swc if defined?(@using_swc)
  @using_swc = detect_swc_configuration
end

Uses defined?(@using_swc) instead of just checking truthiness, which correctly handles false values.

5. Clear Documentation

Excellent inline documentation explaining:

  • What the method does
  • Detection logic flow
  • Why certain defaults are chosen
  • Performance benefits ("20x faster than Babel")

🔍 Potential Issues & Suggestions

1. Missing Version Check Implementation ⚠️

The code calls shakapacker_version_9_3_or_higher? but I notice it's a new method. Let me verify the implementation:

def shakapacker_version_9_3_or_higher?
  return true unless defined?(ReactOnRails::PackerUtils)
  
  ReactOnRails::PackerUtils.shakapacker_version_requirement_met?("9.3.0")
rescue StandardError
  # If we can't determine version, assume latest (which uses SWC)
  true
end

Good: This follows the same pattern as the existing shakapacker_version_9_or_higher? method.

Concern: The method returns true when ReactOnRails::PackerUtils is not defined. During generator runtime, this might not be defined yet.

Recommendation: Verify this works correctly during fresh installations where Shakapacker hasn't been installed yet. The optimistic default is probably correct, but worth confirming.

2. Dependency Installation Ordering 💡

In js_dependency_manager.rb:

def add_js_dependencies
  add_react_on_rails_package
  add_react_dependencies
  add_css_dependencies
  add_rspack_dependencies if respond_to?(:options) && options&.rspack?
  add_swc_dependencies if using_swc?  # ← Called here
  add_dev_dependencies
end

Question: Should SWC dependencies be added earlier in the sequence, perhaps before CSS dependencies? Build tools typically need to be installed before other dependencies that might use them.

Recommendation: Consider moving add_swc_dependencies right after add_react_on_rails_package or at least before add_css_dependencies.

3. YAML.load_file Security 🔒

YAML.load_file(path, aliases: true)

Current: Uses YAML.load_file which can execute arbitrary Ruby code in older YAML versions.

Recommendation: Consider using YAML.safe_load_file for better security:

def parse_shakapacker_yml(path)
  require "yaml"
  YAML.safe_load_file(path, aliases: true, permitted_classes: [Symbol])
rescue ArgumentError
  YAML.safe_load_file(path, permitted_classes: [Symbol])
rescue StandardError
  {}
end

However: Since this is reading the user's own shakapacker.yml config file (not external input), the security risk is minimal. But it's worth considering for defense-in-depth.

4. Missing Test: Version Boundary 📝

The tests cover the logic well, but there's no test for the version boundary:

Suggestion: Add a test that mocks ReactOnRails::PackerUtils.shakapacker_version_requirement_met? to return both true and false for version 9.3.0.

Example:

context "when Shakapacker version is 9.2.0 (before SWC default)" do
  before do
    allow(ReactOnRails::PackerUtils).to receive(:shakapacker_version_requirement_met?)
      .with("9.3.0").and_return(false)
  end

  it "returns false when no transpiler is specified" do
    File.write(shakapacker_yml_path, "default: {}\n")
    expect(using_swc?).to be false
  end
end

5. Potential Race Condition with Memoization 🧵

The memoization uses instance variables:

def using_swc?
  return @using_swc if defined?(@using_swc)
  @using_swc = detect_swc_configuration
end

Concern: If shakapacker.yml changes during generator execution, the memoized value won't update.

Reality Check: This is probably fine since generators run quickly and config files shouldn't change mid-execution.

Optional Enhancement: Add a comment explaining this caching behavior.


🎯 Code Quality Assessment

Category Rating Notes
Error Handling ⭐⭐⭐⭐⭐ Excellent graceful degradation
Test Coverage ⭐⭐⭐⭐½ Comprehensive, missing version boundary test
Documentation ⭐⭐⭐⭐⭐ Clear comments and inline docs
Code Style ⭐⭐⭐⭐⭐ Follows project conventions
Security ⭐⭐⭐⭐☆ Minor YAML.load concern (low risk)
Performance ⭐⭐⭐⭐⭐ Proper memoization

🚀 Testing Recommendations

Before merging, please verify:

  1. Fresh Installation Test:

    # In a new Rails app without Shakapacker
    rails new test_app
    cd test_app
    bundle add react_on_rails --git=<your-branch>
    rails generate react_on_rails:install
    # Verify SWC dependencies are installed
    grep -E '@swc/core|swc-loader' package.json
  2. Babel Override Test:

    # Edit config/shakapacker.yml BEFORE running generator
    # Set javascript_transpiler: babel
    rails generate react_on_rails:install
    # Verify SWC dependencies are NOT installed
    grep -E '@swc/core|swc-loader' package.json  # Should be empty
  3. Existing Installation Test:

    # In an app with existing Shakapacker 9.3.0+
    rails generate react_on_rails:install
    # Verify SWC deps are added

📋 Checklist for Author

  • Manual testing completed per recommendations above
  • CI passes (RuboCop, RSpec)
  • Tested with both fresh and existing installations
  • Verified SWC deps are correctly installed/skipped based on config
  • Consider adding version boundary test (optional)
  • Consider YAML.safe_load_file (optional security hardening)

✅ Final Recommendation

APPROVE with minor suggestions.

This is a well-implemented feature that:

  • Solves a real problem (manual SWC dependency installation)
  • Has excellent error handling
  • Includes comprehensive tests
  • Follows project conventions
  • Makes sensible default assumptions

The suggestions above are minor improvements, not blocking issues. The code is production-ready as-is.

Great work! 🎉


Reviewed by: Claude Code
Date: 2025-11-26

The JsDependencyManager tests create a mock test class that includes
the module. After adding the using_swc? call to add_js_dependencies,
the test class needs to provide this method (which comes from
GeneratorHelper in actual generator classes).

Changes:
- Add using_swc? method stub to test class (defaults to true)
- Add using_swc setter for test control
- Add test for SWC_DEPENDENCIES constant

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

Co-Authored-By: Claude <noreply@anthropic.com>
@justin808 justin808 added the AI_ON label Dec 5, 2025
Changes based on code review feedback:

1. Security: Use YAML.safe_load_file instead of YAML.load_file
   - Defense-in-depth even though it's the user's own config
   - Added fallback chain for older Psych versions

2. Documentation: Add caching behavior note to using_swc?
   - Explains memoization is per-generator-instance
   - Notes config changes during execution won't be reflected

3. Tests: Add version boundary tests for Shakapacker 9.3.0
   - Test SWC default when version is 9.3.0+
   - Test Babel default when version is below 9.3.0
   - Test graceful fallback when version check fails

4. Tests: Add generator test verifying SWC dependency installation
   - Confirms @swc/core and swc-loader in devDependencies
   - Mirrors existing rspack dependency test pattern

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

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve SWC compiler detection and configuration for Shakapacker 9.3.0+

2 participants