-
-
Notifications
You must be signed in to change notification settings - Fork 638
Add Shakapacker 9.0+ private_output_path integration for server bundles #2028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Shakapacker 9.0+ private_output_path integration for server bundles #2028
Conversation
WalkthroughAdds Shakapacker 9+-aware server-bundle configuration and docs: generator/template changes to prefer and surface Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Gen as Generator
participant PUtil as PackerUtils
participant Conf as ReactOnRails::Configuration
participant Utils as Utils
participant Doctor as Doctor
Gen->>PUtil: shakapacker_version_9_or_higher?
PUtil-->>Gen: boolean
alt Shakapacker ≥ 9
Gen->>Gen: render templates using private_output_path
else
Gen->>Gen: render legacy templates (hardcoded server path)
end
Conf->>PUtil: request Shakapacker config
PUtil-->>Conf: config (may include private_output_path)
Conf->>Conf: auto_detect_server_bundle_path_from_shakapacker
Conf->>Utils: normalize_to_relative_path(detected_path)
Utils-->>Conf: relative_path or nil
alt relative_path present
Conf->>Conf: set server_bundle_output_path or warn if explicit mismatch
else
Conf->>Conf: keep default, log guidance
end
Doctor->>PUtil: shakapacker_version_requirement_met?("9.0.0")
PUtil-->>Doctor: boolean
Doctor->>Doctor: check_shakapacker_private_output_path(rails_bundle_path)
Doctor->>Doctor: emit info/warning/suggestions
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
Code Review - PR #2028: Shakapacker 9.0+ private_output_path IntegrationSummaryThis PR adds automatic detection and integration of Shakapacker 9.0+'s ✅ Strengths1. Excellent Backward Compatibility
2. Comprehensive Test Coverage
3. Strong Documentation
4. Developer Experience
🔍 Potential Issues & Suggestions1. Critical: Auto-Detection Timing Risk
|
Code Review - PR #2028: Shakapacker 9.0+ private_output_path IntegrationOverall AssessmentStatus: ✅ Excellent Quality - This is a well-designed, thoroughly tested feature that follows best practices throughout. 🎯 Strengths1. Excellent Backward Compatibility DesignThe auto-detection logic in
2. Comprehensive Test CoverageThe test suite is thorough:
3. Version-Aware Generator TemplatesThe generator helper (
4. Excellent Documentation
🔍 Code Quality ObservationsSecurity✅ Good: The PR includes Performance✅ No concerns:
Error Handling✅ Robust:
💡 Minor Suggestions1. Path Normalization Edge CaseIn # Current code
path_str.sub(%r{^#{Regexp.escape(rails_root_str)}/?}, "")
# Edge case: Rails.root = "/", path = "/app"
# Would incorrectly match and return "app" instead of "/app"Recommendation: Add a boundary check or document this assumption. Though extremely rare, you could add: return path_str if rails_root_str == "/"2. Generator Default AssumptionIn return true unless defined?(ReactOnRails::PackerUtils)This is pragmatic, but could generate incorrect config if someone installs an older Shakapacker version. Consider whether the comment should emphasize this assumption more strongly. Current risk: Low - the code works correctly, but users might not realize they got v9+ config with older Shakapacker. 3. Doctor Method ComplexityThe
Not blocking: The current implementation is readable and well-tested. 🔒 Security Review✅ No security concerns identified
🐛 Potential IssuesNone IdentifiedThe code is solid. The only theoretical concern is: Edge Case: If a user has Shakapacker 9.0+ but ✅ Best Practices CompliancePer the project's
📋 Pre-Merge ChecklistBefore merging, verify:
🎉 ConclusionRecommendation: APPROVE ✅ This is exemplary code that:
The implementation demonstrates careful consideration of edge cases and provides a smooth migration path for users. Great work! 📝 Nit: Documentation TypoIn Note: This review was conducted according to the repository's CLAUDE.md guidelines, focusing on code quality, security, performance, and best practices. |
Code Review - PR #2028OverviewThis PR adds excellent Shakapacker 9.0+ integration for automatic server bundle path detection. The implementation is well-thought-out with strong backward compatibility and comprehensive testing. ✅ Strengths1. Excellent Test Coverage
2. Strong Backward Compatibility
3. Security Best Practices
4. Developer Experience
5. Code Quality
🔍 Potential Issues & Suggestions1. Missing Test Coverage for Auto-Detection Logic
|
CI Failure - Not Related to This PRThe failing CI job is due to a pre-existing bug in master's CI configuration ( lines 73-75). The issue: Matrix entries with conditional expressions that evaluate to are passed as literal values, causing "Unknown engine false" error. This is not caused by the Shakapacker integration changes in this PR. The actual Shakapacker integration code:
I'll monitor master for a fix or add a workaround commit if needed. |
Code Review - PR #2028: Shakapacker 9.0+ private_output_path Integration🎯 Overall AssessmentThis is an excellent PR that delivers a significant DX improvement by eliminating configuration duplication between Shakapacker and React on Rails. The implementation is well-designed, thoroughly tested, and backward compatible. ✅ Strengths1. Excellent Architecture & Design
2. Outstanding Test Coverage
3. Code Quality
4. Documentation
5. Developer Experience
💡 Suggestions for Consideration1. Path Normalization Edge Case (Minor)Location: The path normalization logic should handle these edge cases:
Example test case to add: # In spec/react_on_rails/utils_spec.rb
it "handles multiple consecutive slashes" do
expect(normalize_to_relative_path("//ssr-generated//")).to eq("ssr-generated")
end2. Configuration Priority Documentation (Minor)Location: The template comments are excellent, but could benefit from explicitly stating the priority order: # Configuration Priority (highest to lowest):
# 1. Explicit config.server_bundle_output_path setting
# 2. Auto-detected from shakapacker.yml private_output_path (Shakapacker 9.0+)
# 3. Default: "ssr-generated"This makes the behavior crystal clear for users. 3. Doctor Check Performance (Very Minor)Location: The
4. Generator Helper Error Context (Minor)Location: The rescue StandardError
# If we can't determine version, assume latest
true
endConsider logging the error in development mode to help debug version detection failures: rescue StandardError => e
Rails.logger&.debug("Could not determine Shakapacker version: #{e.message}") if defined?(Rails)
true
end5. Test Coverage Gap (Minor)The tests for
Based on the diff, these might already be covered in the path normalization tests. 🔒 SecurityNo security concerns. The feature actually improves security by:
⚡ PerformanceNo performance concerns:
🧪 Testing RecommendationsBefore merge, verify:
Based on the commit messages, it looks like these have been tested extensively. 📝 Minor Nitpicks
🎉 ConclusionThis PR is production-ready and represents a thoughtful, well-executed enhancement to React on Rails. The implementation demonstrates:
Recommendation: ✅ APPROVE with minor suggestions above for future consideration. The Shakapacker 9.0+ integration will significantly improve the developer experience by eliminating a common source of configuration errors. Great work! This is exactly the kind of thoughtful, incremental improvement that makes frameworks better over time. 🤖 Generated with Claude Code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR integrates Shakapacker 9.0+ private_output_path configuration with React on Rails for server bundles, providing automatic synchronization between webpack and Rails configurations. The implementation gracefully handles version detection and provides clear diagnostic feedback through the doctor command.
Key Changes:
- Automatic detection of
private_output_pathfromshakapacker.ymlwhen using Shakapacker 9.0+ - Version-aware generator templates that configure appropriately based on Shakapacker version
- Enhanced doctor diagnostics with recommendations for optimal configuration
Reviewed Changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
spec/react_on_rails/utils_spec.rb |
Comprehensive tests for path normalization covering edge cases including Rails.root handling, special characters, and nil values |
spec/lib/react_on_rails/doctor_spec.rb |
Tests for Shakapacker integration diagnostics across version scenarios including success, mismatch, and error cases |
lib/react_on_rails/utils.rb |
Adds normalize_to_relative_path utility to convert absolute paths to Rails.root-relative paths with proper documentation |
lib/react_on_rails/doctor.rb |
Implements check_shakapacker_private_output_path to validate configuration and provide version-specific recommendations |
lib/react_on_rails/configuration.rb |
Adds auto-detection logic for server_bundle_output_path from Shakapacker's private_output_path with graceful error handling |
lib/generators/react_on_rails/generator_helper.rb |
Adds version detection helper for Shakapacker 9.0+ with proper fallback logic |
lib/generators/react_on_rails/base_generator.rb |
Updates config generation to use templates for version-aware configuration |
lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt |
Template uses config.privateOutputPath for Shakapacker 9.0+, hardcoded path for older versions |
lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.tt |
Conditionally enables private_output_path configuration based on Shakapacker version |
lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt |
Adds comprehensive documentation about Shakapacker 9.0+ integration with clear migration guidance |
docs/core-concepts/webpack-configuration.md |
Documents the Shakapacker 9.0+ integration with configuration examples and benefits |
docs/api-reference/configuration.md |
Extensive documentation updates covering server bundle security, organization, and Shakapacker 9.0+ integration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
34e4785 to
acdc849
Compare
There was a problem hiding this 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 (3)
lib/generators/react_on_rails/generator_helper.rb (1)
99-114: Consider the implications of defaulting totrueon version check failures.The method defaults to
truein two scenarios:
- When Shakapacker is not yet installed (line 107)
- When version detection fails (line 112)
While optimistic defaults work for fresh installs, silently defaulting to
trueon errors could generate incorrect configuration if version detection genuinely fails in an existing project.Consider logging a warning when the rescue block is triggered:
def shakapacker_version_9_or_higher? return @shakapacker_version_9_or_higher if defined?(@shakapacker_version_9_or_higher) @shakapacker_version_9_or_higher = begin # If Shakapacker is not available yet (fresh install), default to true # since we're likely installing the latest version return true unless defined?(ReactOnRails::PackerUtils) ReactOnRails::PackerUtils.shakapacker_version_requirement_met?("9.0.0") rescue StandardError - # If we can't determine version, assume latest + puts "Warning: Could not determine Shakapacker version, assuming 9.0+" true end endlib/react_on_rails/configuration.rb (1)
261-290: Consider validating empty string from private_output_path.The auto-detection logic checks for
nilat line 276 but doesn't handle the case whereprivate_output_pathreturns an empty string. If Shakapacker's config returns"", the code would proceed to normalize and set an empty path.Apply this diff to handle empty strings:
begin private_path = ::Shakapacker.config.private_output_path - return unless private_path + return if private_path.nil? || private_path.to_s.empty? # Convert from Pathname to relative string pathlib/react_on_rails/doctor.rb (1)
1408-1470: Consider normalizing both paths before comparison.At line 1439, the method compares
relative_path(normalized from Shakapacker) withrails_bundle_path(extracted directly from the config file at line 684). Ifrails_bundle_pathcontains an absolute path or inconsistent formatting, the comparison might fail even when the paths logically match.Apply this diff to normalize both paths for comparison:
# Shakapacker 9.0+ is available begin private_path = ::Shakapacker.config.private_output_path if private_path relative_path = ReactOnRails::Utils.normalize_to_relative_path(private_path) + normalized_rails_path = ReactOnRails::Utils.normalize_to_relative_path(rails_bundle_path) - if relative_path == rails_bundle_path + if relative_path == normalized_rails_path checker.add_success("\n ✅ Using Shakapacker 9.0+ private_output_path: '#{relative_path}'") checker.add_info(" Auto-detected from shakapacker.yml - no manual config needed") else checker.add_warning(<<~MSG.strip) \n ⚠️ Configuration mismatch detected! Shakapacker private_output_path: '#{relative_path}' - React on Rails server_bundle_output_path: '#{rails_bundle_path}' + React on Rails server_bundle_output_path: '#{normalized_rails_path}'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
docs/api-reference/configuration.md(1 hunks)docs/core-concepts/webpack-configuration.md(1 hunks)lib/generators/react_on_rails/base_generator.rb(1 hunks)lib/generators/react_on_rails/generator_helper.rb(1 hunks)lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt(1 hunks)lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.tt(1 hunks)lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt(2 hunks)lib/react_on_rails/configuration.rb(2 hunks)lib/react_on_rails/doctor.rb(4 hunks)lib/react_on_rails/utils.rb(1 hunks)spec/lib/react_on_rails/doctor_spec.rb(1 hunks)spec/react_on_rails/utils_spec.rb(1 hunks)
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
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.
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.
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.
📚 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:
docs/core-concepts/webpack-configuration.mdlib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.ttlib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.mdlib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.ttlib/react_on_rails/configuration.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:
docs/core-concepts/webpack-configuration.mdlib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.ttlib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.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:
docs/core-concepts/webpack-configuration.mdlib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.mdlib/react_on_rails/configuration.rblib/react_on_rails/utils.rbspec/react_on_rails/utils_spec.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/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.ttlib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.mdlib/react_on_rails/configuration.rbspec/lib/react_on_rails/doctor_spec.rbspec/react_on_rails/utils_spec.rblib/react_on_rails/doctor.rb
📚 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:
lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.ttlib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt
📚 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/initializers/react_on_rails.rb.ttlib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.md
📚 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/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.ttdocs/api-reference/configuration.mdlib/generators/react_on_rails/generator_helper.rbspec/react_on_rails/utils_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:
lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.ttdocs/api-reference/configuration.mdlib/generators/react_on_rails/generator_helper.rbspec/react_on_rails/utils_spec.rblib/react_on_rails/doctor.rb
📚 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:
lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt
📚 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:
docs/api-reference/configuration.md
📚 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/generator_helper.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:
spec/lib/react_on_rails/doctor_spec.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:
spec/react_on_rails/utils_spec.rb
📚 Learning: 2024-10-08T20:53:47.076Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1622
File: spec/dummy/spec/rake/assets_precompile_rake_spec.rb:12-12
Timestamp: 2024-10-08T20:53:47.076Z
Learning: When stubbing environment variables in RSpec tests, use `before` and `after` hooks to ensure that the original values are restored after the tests, preventing any side effects on other tests. Example provided by justin808:
```ruby
describe "My test" do
before do
original_value = ENV["VARIABLE_NAME"]
allow(ENV).to receive(:[]).with("VARIABLE_NAME").and_return("stubbed_value")
end
after do
allow(ENV).to receive(:[]).with("VARIABLE_NAME").and_call_original
ENV["VARIABLE_NAME"] = original_value
end
it "tests something" do
# Your test code here
end
end
```
This practice ensures test isolation and reliability.
Applied to files:
spec/react_on_rails/utils_spec.rb
🧬 Code graph analysis (4)
lib/generators/react_on_rails/generator_helper.rb (1)
lib/react_on_rails/packer_utils.rb (1)
shakapacker_version_requirement_met?(30-33)
lib/react_on_rails/configuration.rb (1)
lib/react_on_rails/utils.rb (1)
normalize_to_relative_path(455-469)
spec/react_on_rails/utils_spec.rb (1)
lib/react_on_rails/utils.rb (1)
normalize_to_relative_path(455-469)
lib/react_on_rails/doctor.rb (2)
lib/react_on_rails/system_checker.rb (3)
add_info(28-30)add_success(24-26)add_warning(20-22)lib/react_on_rails/utils.rb (1)
normalize_to_relative_path(455-469)
⏰ 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). (3)
- GitHub Check: build
- GitHub Check: claude-review
- GitHub Check: markdown-link-check
🔇 Additional comments (11)
lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.tt (1)
32-37: LGTM! Version-aware configuration template is well-designed.The conditional generation based on Shakapacker version is clean and maintainable. The commented fallback for older versions provides good documentation without breaking existing setups.
lib/generators/react_on_rails/base_generator.rb (1)
102-103: LGTM! Template-driven generation enables version-aware configuration.The switch from
copy_filetotemplateis necessary to process the ERB conditionals inshakapacker.yml.tt. This change is minimal and focused.lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt (1)
47-71: LGTM! Version-aware server output path configuration is well-implemented.The conditional logic correctly uses
config.privateOutputPathfor Shakapacker 9.0+ and falls back to a hardcoded path for older versions. The comments provide clear migration guidance.lib/react_on_rails/utils.rb (1)
446-469: LGTM! Path normalization utility is robust and well-documented.The implementation correctly handles nil, Pathname, and String inputs. The use of
Regexp.escapefor the Rails.root prefix prevents regex injection issues. Documentation and examples are clear.docs/core-concepts/webpack-configuration.md (1)
81-111: LGTM! Documentation clearly explains the Shakapacker 9.0+ integration.The new section provides clear examples and explains the benefits of using
private_output_path. The fallback guidance for older versions is helpful for users who haven't upgraded yet.docs/api-reference/configuration.md (1)
111-163: LGTM! Comprehensive documentation of server bundle security and organization.The documentation clearly explains the Shakapacker 9.0+ integration, the benefits of
private_output_path, and the security implications ofenforce_private_server_bundles. The directory structure example is particularly helpful for understanding the separation between client and server bundles.lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt (1)
29-32: No breaking change concerns identified after verification.The asymmetry between the template default (
enforce_private_server_bundles = true) and the library default (line 50 inlib/react_on_rails/configuration.rb:false) is intentional. The default isfalsefor backward compatibility, while the generated initializer is secure-by-default for new projects.The implementation includes appropriate safeguards:
- Validation logic (
lib/react_on_rails/configuration.rblines 237-259) raises errors ifenforce_private_server_bundles=truewithout properserver_bundle_output_pathconfiguration- Template guidance directs users to use Shakapacker 9.0+ auto-detection or manually configure the path
- Doctor task (
rails react_on_rails:doctor) helps verify configurationExisting projects are unaffected unless they explicitly regenerate their initializer, and any misconfiguration triggers clear error messages guiding users to proper setup.
lib/react_on_rails/configuration.rb (1)
187-187: LGTM! Auto-detection positioned correctly in the configuration flow.The auto-detection method is appropriately invoked at the end of
setup_config_values, ensuring all other configuration validations complete first before attempting auto-detection.spec/react_on_rails/utils_spec.rb (1)
902-999: Excellent test coverage for path normalization utility.The test suite comprehensively covers the
normalize_to_relative_pathmethod, including:
- Standard absolute → relative conversions
- Pathname object handling
- Edge cases (nil, already relative, Rails.root as substring)
- Complex path scenarios (special characters, spaces, dots)
The test structure is clear and follows RSpec best practices.
spec/lib/react_on_rails/doctor_spec.rb (1)
526-636: Well-structured tests for Shakapacker integration diagnostics.The test suite thoroughly validates the
check_shakapacker_private_output_pathhelper across multiple scenarios:
- Absent Shakapacker gem
- Pre-9.0 versions without
private_output_pathsupport- 9.0+ scenarios (matching paths, mismatches, unset config, error handling)
The tests use proper test doubles and verify specific diagnostic messages, ensuring the doctor feature provides accurate guidance to users.
lib/react_on_rails/doctor.rb (1)
670-718: LGTM! Enhanced server rendering configuration analysis.The updated
analyze_server_rendering_configmethod now includes:
- Display of
server_bundle_output_pathandenforce_private_server_bundlesconfiguration- Integration with the new Shakapacker diagnostics helper
The additions are well-integrated and provide users with comprehensive server bundle configuration information.
CI Fix AppliedAdded the The Problem: The workflow's conditional matrix include logic evaluates to - ruby-version: ${{ (condition) && '3.2'}} # Evaluates to false when condition is falseThe Fix: The This ensures the full test matrix runs (both latest and minimum dependency versions) and avoids the "Unknown engine false" error. CI should now pass! ✅ |
Review Feedback Addressed ✅Added validation and error messaging for hardcoded server bundle paths (addressing review comment on serverWebpackConfig.js.tt:61). Changes in commit 42da62c: 1. Runtime Validation for Older ShakapackerFor Shakapacker < 9.0 using hardcoded paths, added validation that displays helpful warnings: ⚠️ Server bundle output directory does not exist: /path/to/ssr-generated
It will be created during build, but ensure React on Rails is configured:
config.server_bundle_output_path = "ssr-generated" in config/initializers/react_on_rails.rb
Run: rails react_on_rails:doctor to validate your configuration2. Code Quality Improvements
Benefits
|
42da62c to
ee74d03
Compare
|
✅ Rebased onto latest master (276507d) Picked up important CI fixes from master:
Removed the All RuboCop checks passing ✅ |
CI Failure Fixed ✅Root Cause: The webpack config template was using without a fallback, causing it to be when wasn't set in . Fix Applied (commit 78a2ff7): // Before (broken):
path: config.privateOutputPath
// After (fixed):
path: config.privateOutputPath || require('path').resolve(__dirname, '../../ssr-generated')This ensures the server bundle is always built to a valid location, even when:
The fallback maintains full backward compatibility while still supporting the new auto-detection feature when properly configured. CI should now pass! 🚀 |
78a2ff7 to
adb0aa9
Compare
|
✅ Rebased onto latest master (ad73088) Picked up important fixes:
The Knip fix should resolve the build failures. CI running now! 🚀 |
adb0aa9 to
4fd1204
Compare
Knip Warnings - Pre-existing Issue ℹ️The build job shows Knip warnings for spec/dummy dependencies:
These are false positives - both dependencies ARE used but in ways Knip can't detect:
This is a pre-existing issue in master, not introduced by this PR. These same dependencies exist in Options:
The Shakapacker integration feature itself is complete and working. All other CI checks should pass. ✅ |
|
@claude review this PR |
|
Claude finished @justin808's task —— View job Code Review for PR #2028Task: Review Shakapacker 9.0+ private_output_path integration Executive SummaryThis is an excellent PR that delivers a high-quality feature with thoughtful design, comprehensive testing, and clear documentation. The implementation provides automatic detection of Shakapacker 9.0+ Recommendation: ✅ APPROVE - Ready to merge with minor observations noted below. 🎯 Strengths1. Outstanding Architecture & DesignThe auto-detection logic is exemplary:
lib/react_on_rails/configuration.rb:265-290 def auto_detect_server_bundle_path_from_shakapacker
return if server_bundle_output_path != ReactOnRails::DEFAULT_SERVER_BUNDLE_OUTPUT_PATH
return unless defined?(::Shakapacker)
return unless ::Shakapacker.config.respond_to?(:private_output_path)
# ... graceful error handling
endThis pattern is excellent - each 2. Comprehensive Test Coveragespec/react_on_rails/utils_spec.rb:902-999 - Path normalization tests are thorough:
spec/lib/react_on_rails/doctor_spec.rb:536-636 - Doctor diagnostics fully tested:
3. Excellent Developer ExperienceThe doctor command provides actionable guidance:
lib/react_on_rails/doctor.rb:1411-1470 - All scenarios handled with appropriate messaging. 4. Security Best Practiceslib/react_on_rails/utils.rb:446-473: path_str.sub(%r{^#{Regexp.escape(rails_root_str)}/?}, "")✅ Uses 5. Code Quality
6. Documentation Excellencedocs/api-reference/configuration.md:
Generator templates:
🔍 Observations & Minor Suggestions1. Webpack Config Fallback ✅ Already Fixedlib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt:61 The latest commit (4fd1204) properly adds a fallback: path: config.privateOutputPath || require('path').resolve(__dirname, '../../ssr-generated')This is excellent - ensures the server bundle always has a valid output path even when 2. Auto-Detection Logging Level ✅ Well-Chosenlib/react_on_rails/configuration.rb:283-284 Using
3. Generator Version Detectionlib/generators/react_on_rails/generator_helper.rb:104-112 The optimistic default ( return true unless defined?(ReactOnRails::PackerUtils)Reasoning: This assumes fresh installs will use latest Shakapacker, which is reasonable. The fallback in the webpack config ensures it still works even if this assumption is wrong. Minor concern: If someone generates with Shakapacker not installed, then installs an older version, they'd get the wrong template. However:
Verdict: Current approach is acceptable. 4. Path Normalization Edge Caselib/react_on_rails/utils.rb:459-473 Consider what happens if # Rails.root = "/", path = "/app"
# Would incorrectly match and return "app" instead of "/app"Mitigation: The Optional enhancement: Add a guard clause: return path_str if rails_root_str == "/"But this is not blocking - just a theoretical edge case. 5. Error Handling Specificitylib/react_on_rails/configuration.rb:285-289 rescue StandardError => e
Rails.logger&.debug("ReactOnRails: Could not auto-detect...")
endCatching
Could be improved: Catch more specific exceptions ( 🧪 TestingTest Coverage Assessment: Excellent
Tests NOT present (and why that's OK):
📋 Pre-Merge ChecklistBased on CLAUDE.md requirements, verify:
Note: The author has already addressed CI failures through multiple commits and rebases. The latest commit (4fd1204) adds the critical fallback for webpack config. 🔒 Security Review✅ No security concerns identified
⚡ Performance✅ Minimal performance impact
📝 Code Quality Issues Found: NoneAll code follows project standards:
💡 Notable Implementation Details1. Constant ExtractionThe addition of
2. Webpack ValidationserverWebpackConfig.js.tt:67-79 - For Shakapacker < 9.0, adds helpful validation warnings when the output directory doesn't exist. This guides users to proper configuration. 3. Doctor Integrationlib/react_on_rails/doctor.rb:670-718 - The doctor command now displays:
This provides a complete diagnostic picture. 🎉 ConclusionThis PR demonstrates excellent software engineering:
The implementation shows careful consideration of:
Minor Observations SummaryThe observations noted above are not blocking issues - they're minor points for future consideration:
Final Recommendation✅ APPROVE AND MERGE This is production-quality code that significantly improves the React on Rails developer experience. Great work, @justin808! Reviewed commit: 4fd1204 (Fix webpack config to fallback when privateOutputPath is undefined) |
There was a problem hiding this 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 (4)
docs/api-reference/configuration.md (1)
115-128: Consider strengthening the guidance on Shakapacker version requirements.The documentation states "
⚠️ RECOMMENDED: Use Shakapacker 9.0+" but then shows manual configuration options for older versions. While this flexibility is good, consider adding a note about which versions are actively tested/supported to help users make informed upgrade decisions.Additionally, the comment at line 123 says "For older Shakapacker versions or custom setups, manually configure" but doesn't specify what counts as "older." Consider being explicit: "For Shakapacker < 9.0, manually configure:"
lib/generators/react_on_rails/generator_helper.rb (1)
99-114: Consider more specific error handling.The method rescues all
StandardErrorand defaults totrue(line 110-113). While this provides a safe fallback during fresh installations, it might mask legitimate errors (e.g., permissions issues, load path problems, or version parsing failures).Consider:
- Rescuing more specific exceptions (e.g.,
LoadError,Gem::LoadError)- Logging the rescued error at debug level to aid troubleshooting
- Adding a comment explaining that the true default optimizes for the fresh-install case
The current implementation is acceptable but could be more defensive.
def shakapacker_version_9_or_higher? return @shakapacker_version_9_or_higher if defined?(@shakapacker_version_9_or_higher) @shakapacker_version_9_or_higher = begin # If Shakapacker is not available yet (fresh install), default to true # since we're likely installing the latest version return true unless defined?(ReactOnRails::PackerUtils) ReactOnRails::PackerUtils.shakapacker_version_requirement_met?("9.0.0") - rescue StandardError + rescue LoadError, Gem::LoadError, NoMethodError => e + # Log for debugging but don't fail generation + puts "Warning: Could not determine Shakapacker version: #{e.message}" if ENV['DEBUG'] # If we can't determine version, assume latest true end endlib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt (1)
79-86: Consider asynchronous or lazy validation.The validation block uses
fs.existsSync()(line 81) which is synchronous and may block webpack configuration loading, especially on slower file systems or network drives. While this is during config initialization (not during builds), it could impact developer experience.Consider:
- Moving this check to a webpack plugin that runs at the start of compilation
- Making the check conditional on a debug flag
- Keeping as-is but adding a timeout to prevent hangs
Given this is a generator template for initial setup and the check is quick, the current approach is acceptable but could be optimized in a future enhancement.
spec/lib/react_on_rails/doctor_spec.rb (1)
525-636: Excellent test coverage for Shakapacker integration!The test suite comprehensively covers:
- Shakapacker undefined scenario
- Pre-9.0 version handling with upgrade guidance
- 9.0+ scenarios: matching paths, mismatches, and missing configuration
- Error handling with graceful degradation
The test structure is clear, uses proper mocking, and validates both success and warning messages. The use of
instance_doubleand proper constant stubbing demonstrates good testing practices.One minor enhancement to consider: add a test for the edge case where
private_output_pathreturns an empty string, which might occur with misconfigured shakapacker.yml files.Optional enhancement for edge case coverage:
it "handles empty string private_output_path" do private_path = instance_double(Pathname, to_s: "/app/") allow(shakapacker_config).to receive(:private_output_path).and_return(private_path) expect(checker).to receive(:add_warning).with(/Configuration mismatch detected/) doctor.send(:check_shakapacker_private_output_path, "ssr-generated") end
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
docs/api-reference/configuration.md(1 hunks)docs/core-concepts/webpack-configuration.md(1 hunks)lib/generators/react_on_rails/base_generator.rb(1 hunks)lib/generators/react_on_rails/generator_helper.rb(1 hunks)lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt(1 hunks)lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.tt(1 hunks)lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt(1 hunks)lib/react_on_rails/configuration.rb(4 hunks)lib/react_on_rails/doctor.rb(4 hunks)lib/react_on_rails/utils.rb(1 hunks)spec/lib/react_on_rails/doctor_spec.rb(1 hunks)spec/react_on_rails/utils_spec.rb(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- lib/generators/react_on_rails/base_generator.rb
- spec/react_on_rails/utils_spec.rb
- lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt
- lib/react_on_rails/configuration.rb
- lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.tt
- lib/react_on_rails/utils.rb
- docs/core-concepts/webpack-configuration.md
🧰 Additional context used
🧠 Learnings (11)
📚 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:
spec/lib/react_on_rails/doctor_spec.rblib/react_on_rails/doctor.rblib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.md
📚 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:
spec/lib/react_on_rails/doctor_spec.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/doctor.rblib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.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/react_on_rails/doctor.rblib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.ttlib/generators/react_on_rails/generator_helper.rbdocs/api-reference/configuration.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/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.md
📚 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/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.md
📚 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:
lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt
📚 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/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.md
📚 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/generator_helper.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/generators/react_on_rails/generator_helper.rbdocs/api-reference/configuration.md
📚 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:
docs/api-reference/configuration.md
🧬 Code graph analysis (2)
lib/react_on_rails/doctor.rb (2)
lib/react_on_rails/system_checker.rb (3)
add_info(28-30)add_success(24-26)add_warning(20-22)lib/react_on_rails/utils.rb (1)
normalize_to_relative_path(470-484)
lib/generators/react_on_rails/generator_helper.rb (1)
lib/react_on_rails/packer_utils.rb (1)
shakapacker_version_requirement_met?(30-33)
⏰ 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). (6)
- GitHub Check: examples (3.4, latest)
- GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
- GitHub Check: rspec-package-tests (3.4, latest)
- GitHub Check: build
- GitHub Check: claude-review
- GitHub Check: markdown-link-check
🔇 Additional comments (4)
lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt (1)
61-61: Verify null vs undefined handling in JavaScript.The ternary on line 61 checks
config.privateOutputPath != nullwhich handles bothnullandundefinedin JavaScript (loose equality). This is correct, but the fallback path should be wrapped to ensure it always resolves correctly.The current implementation is sound, but consider documenting this behavior in the comments above (lines 49-54) to clarify that the fallback handles both missing and null privateOutputPath values.
lib/react_on_rails/doctor.rb (2)
1408-1485: Well-structured Shakapacker integration helpers.The helper methods are well-organized with clear separation of concerns:
check_shakapacker_private_output_pathacts as a dispatcher- Individual
report_*methods handle specific scenarios with clear, actionable messages- Path normalization using
ReactOnRails::Utils.normalize_to_relative_pathensures consistent comparisons- Error handling with rescue clause (line 1415-1416) provides graceful degradation
The user-facing messages are clear, include actionable recommendations, and explain the benefits of upgrading to Shakapacker 9.0+. The implementation correctly handles all documented scenarios from the tests.
1449-1451: Good defensive path normalization.The code normalizes both paths by removing trailing slashes (lines 1450-1451) before comparison, which prevents false negatives due to path formatting differences. This is a good defensive programming practice.
docs/api-reference/configuration.md (1)
130-132: Documentation verified as accurate.The default value for
enforce_private_server_bundlesis correctly implemented asfalsein the configuration class (lib/react_on_rails/configuration.rbline 51) and properly documented in the configuration guide. The documentation statement "Default is false for backward compatibility" is accurate and synchronized with the actual code.
| end | ||
| end | ||
|
|
||
| # rubocop:disable Metrics/CyclomaticComplexity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix inconsistent RuboCop directive.
Line 670 disables Metrics/CyclomaticComplexity, but line 719 (the matching enable) mentions both Metrics/AbcSize, Metrics/CyclomaticComplexity. This inconsistency should be resolved.
Looking at the method analyze_server_rendering_config, it's likely that both metrics are being violated. Update line 670 to match line 719:
- # rubocop:disable Metrics/CyclomaticComplexity
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
def analyze_server_rendering_config(content)📝 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.
| # rubocop:disable Metrics/CyclomaticComplexity | |
| # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity | |
| def analyze_server_rendering_config(content) |
🤖 Prompt for AI Agents
In lib/react_on_rails/doctor.rb around line 670, the RuboCop disable directive
currently only disables Metrics/CyclomaticComplexity while the matching enable
at line 719 re-enables both Metrics/AbcSize and Metrics/CyclomaticComplexity;
update the disable directive on line 670 to disable both Metrics/AbcSize and
Metrics/CyclomaticComplexity so the pair is consistent (i.e., change the comment
to disable Metrics/AbcSize, Metrics/CyclomaticComplexity) and ensure the enable
at line 719 remains intact.
There was a problem hiding this 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 (2)
lib/generators/react_on_rails/generator_helper.rb (1)
99-126: shakapacker_version_9_or_higher? behavior is sound; memoization/control flow could be simplifiedThe helper does the right thing functionally and matches its documentation (optimistically assuming 9+ when version detection fails). The only minor nit is that the
return trueinside thebeginblock means@shakapacker_version_9_or_higheris never memoized on that path, so the detection runs on each call (albeit cheaply in this context).If you want tighter memoization and slightly clearer control flow, you could refactor to compute into a local and assign once:
- def shakapacker_version_9_or_higher? - return @shakapacker_version_9_or_higher if defined?(@shakapacker_version_9_or_higher) - - @shakapacker_version_9_or_higher = begin - # If Shakapacker is not available yet (fresh install), default to true - # since we're likely installing the latest version - return true unless defined?(ReactOnRails::PackerUtils) - - ReactOnRails::PackerUtils.shakapacker_version_requirement_met?("9.0.0") - rescue StandardError - # If we can't determine version, assume latest - true - end - end + def shakapacker_version_9_or_higher? + return @shakapacker_version_9_or_higher if defined?(@shakapacker_version_9_or_higher) + + result = + if !defined?(ReactOnRails::PackerUtils) + true + else + ReactOnRails::PackerUtils.shakapacker_version_requirement_met?("9.0.0") + end + + @shakapacker_version_9_or_higher = result + rescue StandardError + @shakapacker_version_9_or_higher = true + endspec/react_on_rails/configuration_spec.rb (1)
554-628: Auto-detection configuration specs look solid; consider narrowing the negative logger expectationThe new
auto_detect_server_bundle_path_from_shakapackerexamples cover the important behaviors: mismatch warnings, normalized matches, auto-detection, debug logging, and nilprivate_output_path.One small robustness tweak: in
it "does not warn when paths match after normalization" do ... expect(Rails.logger).not_to receive(:warn) ReactOnRails.configure do |config| config.server_bundle_output_path = "ssr-generated" end endthe blanket
not_to receive(:warn)will fail if any other configuration step logs a warning in future (unrelated to server bundle paths). Scoping this to the specific message pattern you care about will make the spec less brittle, e.g.:expect(Rails.logger).not_to receive(:warn).with(/server_bundle_output_path is explicitly set/)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
docs/api-reference/configuration.md(1 hunks)lib/generators/react_on_rails/generator_helper.rb(1 hunks)lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt(1 hunks)lib/react_on_rails/configuration.rb(4 hunks)lib/react_on_rails/utils.rb(1 hunks)spec/react_on_rails/configuration_spec.rb(1 hunks)spec/react_on_rails/utils_spec.rb(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- spec/react_on_rails/utils_spec.rb
🧰 Additional context used
🧠 Learnings (11)
📚 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/utils.rblib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.mdlib/react_on_rails/configuration.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/templates/base/base/config/webpack/serverWebpackConfig.js.ttspec/react_on_rails/configuration_spec.rbdocs/api-reference/configuration.mdlib/react_on_rails/configuration.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/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.mdlib/react_on_rails/configuration.rb
📚 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:
lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt
📚 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:
spec/react_on_rails/configuration_spec.rbdocs/api-reference/configuration.mdlib/react_on_rails/configuration.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:
spec/react_on_rails/configuration_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:
spec/react_on_rails/configuration_spec.rblib/generators/react_on_rails/generator_helper.rbdocs/api-reference/configuration.md
📚 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/generators/react_on_rails/generator_helper.rbdocs/api-reference/configuration.md
📚 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/generator_helper.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:
docs/api-reference/configuration.md
📚 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:
docs/api-reference/configuration.md
🧬 Code graph analysis (3)
spec/react_on_rails/configuration_spec.rb (1)
lib/react_on_rails/configuration.rb (1)
configure(6-9)
lib/generators/react_on_rails/generator_helper.rb (1)
lib/react_on_rails/packer_utils.rb (1)
shakapacker_version_requirement_met?(30-33)
lib/react_on_rails/configuration.rb (1)
lib/react_on_rails/utils.rb (1)
normalize_to_relative_path(470-492)
⏰ 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). (6)
- GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
- GitHub Check: rspec-package-tests (3.4, latest)
- GitHub Check: examples (3.4, latest)
- GitHub Check: build
- GitHub Check: markdown-link-check
- GitHub Check: claude-review
🔇 Additional comments (6)
docs/api-reference/configuration.md (5)
97-109: Clear, well-placed Pro features callout. The section appropriately introduces Pro capabilities and directs users to dedicated documentation, avoiding documentation bloat in the core config guide.
111-139: Excellent security-focused documentation with clear upgrade path. The section clearly distinguishes auto-detection (Shakapacker 9.0+) from manual configuration, includes appropriate security recommendations, and maintains backward compatibility messaging.
140-169: Well-designed visual guide for bundle organization. The directory structure example with accompanying comments and API references helps users understand the recommended separation and provides clear mental model for client/server bundle locations.
442-480: Security configuration well-documented with clear rationale. Theenforce_private_server_bundlessection clearly articulates the default (false for backward compatibility), production recommendation, and security benefits, including explicit mention of React Server Components protection.
444-461: Conservative and appropriate documentation for critical setting. The strong caution against changingserver_bundle_output_pathis justified, and the explanation of behavior at different values is clear. Properly emphasizes the default is correct for virtually all use cases.lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt (1)
47-59: Version-aware serverBundleOutputPath and validations are well-aligned with the Shakapacker 9+ integrationThe template cleanly:
- Derives
serverBundleOutputPathfromconfig.privateOutputPathfor Shakapacker 9+, with a fallback topath.resolve(__dirname, '../../ssr-generated'), matching the Ruby default.- Keeps a hardcoded
../../ssr-generatedpath for pre‑9.0 installs, preserving backward compatibility.- Wires
output.pathto this single source of truth and adds targeted runtime warnings for:
- missing
private_output_pathin 9.0+, and- missing output directory / initializer config in <9.0.
This matches the documented migration path and should behave predictably across versions.
Also applies to: 71-91
Adds clear documentation and automated validation to prevent configuration mismatches between webpack and React on Rails configurations. **Documentation Improvements:** - Add prominent warnings in both webpack config and Rails initializer templates - Clarify that both server_bundle_output_path settings must match - Explain the security rationale (private directories prevent code exposure) - Update generator templates with cross-reference comments **Doctor Validation:** - Add automated check that compares webpack serverWebpackConfig.js output.path with React on Rails server_bundle_output_path configuration - Display success message when configs are in sync - Provide detailed warning with fix instructions when mismatch detected - Gracefully handles missing config files or parsing errors **Why This Matters:** Webpack (build-time) and React on Rails (runtime) need to agree on where server bundles are located. Misconfiguration causes SSR failures that can be hard to debug. This change makes the requirement explicit and adds automated validation via the doctor command. **Technical Notes:** - Validation runs as part of `rails react_on_rails:doctor` analysis - Parses webpack config to extract output.path value - Compares paths relative to Rails.root - No breaking changes - pure documentation and tooling improvement Related to closed PR #1808 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…sive tests
Addresses critical issues identified in code review:
**Issue 1: Regex Pattern Too Restrictive**
- Original regex only matched hardcoded path.resolve() pattern
- Real dummy app uses config.outputPath, which wasn't matched at all
- Validation would silently skip without detecting actual configs
**Fix:**
- Support hardcoded path: require('path').resolve(__dirname, '../../path')
- Detect config.outputPath usage (can't validate, inform user)
- Detect variable usage (can't validate, inform user)
- Clear messaging for each pattern type
**Issue 2: Missing Path Normalization**
- String equality comparison failed on equivalent paths
- ./ssr-generated vs ssr-generated would be false mismatch
- Trailing slashes caused false positives
**Fix:**
- normalize_path() method strips leading ./ and /
- Removes trailing slashes
- Handles whitespace
- Graceful handling of nil/non-string values
**Issue 3: No Test Coverage**
- New validation methods had zero tests
- High risk of regressions
**Fix:**
- Added 20+ comprehensive test cases covering:
- File not found scenarios
- Hardcoded paths (matching and mismatched)
- config.outputPath detection
- Variable detection
- Error handling
- Path normalization edge cases
- All return nil vs success vs warning paths
**Testing Results:**
- All 20 new tests passing
- 30/31 total specs passing (1 pre-existing failure unrelated)
- Covers real-world patterns including dummy app config
**Technical Details:**
- extract_webpack_output_path() now pattern-aware
- Better user messaging for unvalidatable configs
- Maintains backward compatibility
- No breaking changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
…improve docs
Addresses feedback from detailed code review:
**1. Critical: Fix Asymmetric RuboCop Directives**
- Issue: Line 667 only disabled Metrics/CyclomaticComplexity
- But line 702 enabled BOTH Metrics/AbcSize and Metrics/CyclomaticComplexity
- This asymmetry could cause violations
- Fix: Changed line 667 to disable both cops symmetrically
- Result: RuboCop reports method doesn't actually need AbcSize disabled, auto-fixed
**2. Simplify Regex Pattern for Clarity**
- Issue: Pattern `['"]\.\.[\/\.\.]+` was hard to read
- Fix: Changed to explicit `['"]\.\.\/\.\.\/` to clearly match ../../path
- Makes intent obvious: we match exactly two parent directory traversals
- RuboCop auto-removed redundant escapes inside %r{}
**3. Improve Documentation Discoverability**
- Issue: Users might not know about the validation feature
- Fix: Added "Run 'rails react_on_rails:doctor' to verify these configs are in sync"
- Placement: In generator template right next to server_bundle_output_path config
- Helps users discover the validation tool when they need it most
**Testing:**
- ✅ All 20 validation tests still passing
- ✅ RuboCop passes with zero offenses
- ✅ Regex pattern matches test cases correctly
- ✅ 30/31 total specs passing (1 pre-existing failure unrelated)
**Other Suggestions Considered:**
- Reordering validation (decided current flow is good - validates immediately after config display)
- Magic string constant (not needed - single use in method, clear context)
- Trailing newline check (git hooks already enforce this automatically)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Addresses code review feedback about fragile regex matching by implementing a proper integration with Shakapacker 9.0+ private_output_path. **Key Changes:** **1. Auto-Detection from Shakapacker (configuration.rb)** - New `auto_detect_server_bundle_path_from_shakapacker` method - Automatically reads `private_output_path` from Shakapacker 9.0+ config - Only applies if user hasn't explicitly set `server_bundle_output_path` - Gracefully falls back to default if detection fails - Logs info message when auto-detection succeeds **2. Removed Fragile Regex Validation (doctor.rb)** - Removed `validate_server_bundle_path_sync` method (regex matching) - Removed `extract_webpack_output_path` method (pattern detection) - Removed `normalize_path` method (no longer needed) - Replaced with `check_shakapacker_private_output_path` method **3. Recommendation-Based Doctor Checks (doctor.rb)** - Detects Shakapacker version and capabilities - Pre-9.0: Recommends upgrading for better DX - 9.0+ without config: Shows how to configure private_output_path - 9.0+ with config matching: Success message - 9.0+ with config mismatch: Warning with fix instructions - No Shakapacker: Informs about manual configuration **4. Updated Generator Templates** - **React on Rails initializer**: Documents Shakapacker 9.0+ approach first - **Webpack config**: Shows config.privateOutputPath pattern - Both templates emphasize single source of truth in shakapacker.yml - Clear migration path for older Shakapacker versions **5. Comprehensive Test Coverage (8 new tests)** - Shakapacker not defined scenario - Pre-9.0 Shakapacker (no private_output_path support) - 9.0+ with matching config - 9.0+ with mismatched config - 9.0+ without config - Error handling - All tests passing **Benefits:** - No fragile regex parsing of webpack configs - Single source of truth in shakapacker.yml - Automatic configuration for Shakapacker 9.0+ users - Backward compatible with older Shakapacker versions - Clear upgrade path and recommendations - Robust error handling **Breaking Changes:** None - Existing configurations continue to work - Auto-detection only applies to default values - Explicit user configuration always takes precedence Addresses: @justin's feedback on PR #1967 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…tion Documents the recommended approach of using Shakapacker 9.0+ private_output_path for server bundle configuration, providing a single source of truth. **Documentation Updates:** **1. Configuration API Reference (docs/api-reference/configuration.md)** - Added prominent recommendation for Shakapacker 9.0+ approach - Documents shakapacker.yml private_output_path configuration - Explains auto-detection behavior - Preserves documentation for older versions **2. Webpack Configuration Guide (docs/core-concepts/webpack-configuration.md)** - New section: "Server Bundle Configuration (Shakapacker 9.0+)" - Complete example with shakapacker.yml and webpack config - Lists benefits of the new approach: - Single source of truth - Automatic synchronization - No configuration duplication - Better maintainability - Notes compatibility with older versions **Key Points:** - Shakapacker 9.0+ users get automatic configuration - Backward compatible with manual configuration - Generator templates already show both approaches - Doctor command guides users to upgrade **Related Changes:** - Generator templates already updated in previous commit - Auto-detection implemented in configuration.rb - Doctor provides version-aware recommendations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Adds commented-out private_output_path configuration to the generated shakapacker.yml, making it easy for users to enable the Shakapacker 9.0+ integration feature. **Changes:** - Added private_output_path: ssr-generated (commented out) - Clear documentation that it's a Shakapacker 9.0+ feature - Notes that React on Rails automatically detects it - Positioned logically after public_output_path configuration **User Experience:** Users can now simply uncomment one line in shakapacker.yml to enable automatic configuration instead of needing to manually add it. **Complete Integration:** - ✅ Auto-detection in configuration.rb - ✅ Doctor recommendations - ✅ Generator templates (webpack + initializer) - ✅ Shakapacker.yml template (NEW) - ✅ Documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…ration
This commit addresses code review feedback and enhances the Shakapacker 9.0+
integration with several key improvements:
1. **Extract path normalization to shared helper**
- Added Utils.normalize_to_relative_path method
- Eliminates code duplication between configuration.rb and doctor.rb
- Handles edge cases: Pathname objects, special characters, trailing slashes
- Uses proper regex escaping with Regexp.escape
2. **Add comprehensive test coverage**
- Added 17 new test cases for path normalization
- Covers absolute/relative paths, nil handling, special characters
- Tests paths with spaces, dots, hyphens, and substring matching
- All 81 utils tests passing
3. **Make generator version-aware**
- Added shakapacker_version_9_or_higher? helper method
- serverWebpackConfig.js.tt now generates optimal code based on version:
* Shakapacker 9.0+: Uses config.privateOutputPath
* Shakapacker < 9.0: Uses hardcoded path with upgrade notes
- shakapacker.yml.tt automatically enables private_output_path for 9.0+
- Provides clear upgrade path for older versions
4. **Improve error handling**
- Added safe navigation operator for Rails.logger calls
- Graceful fallbacks throughout auto-detection code
- Proper exception handling in generator helper
5. **Code quality improvements**
- All RuboCop violations fixed (0 offenses)
- Added complexity disable directive for well-structured method
- Clear documentation and comments throughout
- New installations get optimal configuration automatically
- No manual config needed for Shakapacker 9.0+ users
- Single source of truth in shakapacker.yml
- Better maintainability through DRY principles
- Comprehensive test coverage ensures reliability
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Addresses review feedback to provide clear error messages when using hardcoded paths with older Shakapacker versions. Changes: - Add runtime validation in serverWebpackConfig.js template for Shakapacker < 9.0 - Display helpful warning with configuration instructions if path doesn't exist - Extract hardcoded "ssr-generated" to DEFAULT_SERVER_BUNDLE_OUTPUT_PATH constant - Improve logging: use debug level for auto-detection (not user-initiated) - Add documentation about absolute paths in normalize_to_relative_path The validation helps users quickly identify configuration mismatches and provides actionable guidance to fix them using rails react_on_rails:doctor. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
The generated serverWebpackConfig.js was failing when Shakapacker 9+ was detected but private_output_path wasn't configured in shakapacker.yml. This caused config.privateOutputPath to be undefined, resulting in webpack building to an incorrect location. Changes: - Add fallback to hardcoded path when config.privateOutputPath is undefined - Ensures server bundle is always built to a valid location - Maintains backward compatibility with all Shakapacker versions This fixes the "server-bundle.js cannot be read" error in generator examples. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Key improvements from code review: - Fix YAML template to generate valid configuration files - Use explicit null checking instead of || for better robustness - Add validation for Shakapacker 9.0+ users to catch misconfigurations - Refactor methods to reduce complexity and improve maintainability - Add path normalization to prevent false mismatch warnings - Improve logging level from debug to info for visibility - Enhance documentation for normalize_to_relative_path utility Technical changes: - shakapacker.yml.tt: Fix ERB syntax for proper comment placement - serverWebpackConfig.js.tt: Use != null check, add Shakapacker 9.0+ validation - configuration.rb: Extract apply_shakapacker_private_output_path method - doctor.rb: Break down large method into focused helper methods - utils.rb: Add comprehensive documentation with examples All changes maintain backward compatibility while improving code quality. RuboCop: 149 files inspected, 0 offenses Tests: 130/131 passing (1 pre-existing failure) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review Improvements: - Enhanced auto-detection to warn when user explicitly configures server_bundle_output_path differently from Shakapacker's private_output_path - Improved webpack config template readability by extracting path logic to named constant instead of inline ternary - Added warning for edge case of absolute paths outside Rails.root - Enhanced documentation for shakapacker_version_9_or_higher? method explaining optimistic default behavior and fallback logic - Fixed long line in configuration.md documentation (187 chars -> multi-line) Test Coverage: - Added 5 tests for auto-detection warning functionality - Added 2 tests for absolute path warning in normalize_to_relative_path - All tests pass, zero RuboCop offenses Changes maintain backward compatibility while providing better user guidance through actionable warning messages. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
58a717b to
2c08975
Compare
- Fix doctor.rb RuboCop directive consistency: disable and enable now match - Improve normalize_to_relative_path to prevent false matches with substring paths - Normalize Rails.root by removing trailing slash for consistent comparisons - Add Metrics/CyclomaticComplexity disable for normalize_to_relative_path 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review - PR #2028: Shakapacker 9.0+ private_output_path IntegrationThank you for this well-structured PR! This is a solid integration that significantly improves the developer experience. Below is a comprehensive review covering code quality, best practices, and potential issues. ✅ Strengths1. Excellent Architecture & Design
2. Comprehensive Testing
3. Strong Documentation
4. Code Quality
🔍 Code Quality Issues1. Missing Utility Method (Minor - Critical for functionality)Location: relative_path = ReactOnRails::Utils.normalize_to_relative_path(private_path)Issue: This method Impact: This will cause a Evidence: # Searched for the method definition - NOT FOUND
grep -r "def normalize_to_relative_path" lib/
# Returns: No matchesRecommendation:
2. Incomplete Test Coverage for New MethodLocation: Issue: The missing Recommendation: Add comprehensive tests: describe ".normalize_to_relative_path" do
it "converts absolute path to relative" do
absolute = "\#{Rails.root}/ssr-generated"
expect(described_class.normalize_to_relative_path(absolute)).to eq("ssr-generated")
end
it "handles Pathname objects" do
pathname = Pathname.new("\#{Rails.root}/ssr-generated")
expect(described_class.normalize_to_relative_path(pathname)).to eq("ssr-generated")
end
it "returns unchanged if already relative" do
expect(described_class.normalize_to_relative_path("ssr-generated")).to eq("ssr-generated")
end
it "handles paths outside Rails.root" do
expect(described_class.normalize_to_relative_path("/tmp/bundles")).to eq("/tmp/bundles")
end
end3. Path Normalization Inconsistency (Minor)Location: def warn_about_explicit_configuration(shakapacker_path)
normalized_config = server_bundle_output_path.to_s.chomp("/")
normalized_shakapacker = shakapacker_path.to_s.chomp("/")Issue: Path normalization here only removes trailing slashes, but doesn't handle:
Recommendation: Use a consistent normalization approach: def normalize_path_for_comparison(path)
path.to_s.strip.sub(/^\.\//, "").gsub(/\/+/, "/").chomp("/")
end4. Error Handling Could Be More Specific (Minor)Location: rescue StandardError => e
Rails.logger&.debug("ReactOnRails: Could not auto-detect server bundle path from " \
"Shakapacker: \#{e.message}")
endIssue: Catches all errors silently. While graceful degradation is good, some errors (like Recommendation: rescue StandardError => e
error_msg = "ReactOnRails: Could not auto-detect server bundle path from " \
"Shakapacker: \#{e.message}"
if Rails.env.development?
Rails.logger&.warn(error_msg)
else
Rails.logger&.debug(error_msg)
end
end5. Doctor Method Naming (Minor - Style)Location: def check_shakapacker_private_output_path(rails_bundle_path)
return report_no_shakapacker unless defined?(::Shakapacker)
return report_upgrade_shakapacker unless ::Shakapacker.config.respond_to?(:private_output_path)
check_shakapacker_9_private_output_path(rails_bundle_path)Issue: Method calls Recommendation: Use more descriptive names:
🔒 Security Considerations✅ Good Security Practices
|
There was a problem hiding this 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
♻️ Duplicate comments (1)
lib/react_on_rails/configuration.rb (1)
175-189: Enforcement still runs before Shakapacker auto‑detection, weakeningenforce_private_server_bundlesguarantees
setup_config_valuescurrently does:check_component_registry_timeout validate_generated_component_packs_loading_strategy validate_enforce_private_server_bundles auto_detect_server_bundle_path_from_shakapackerwhile
auto_detect_server_bundle_path_from_shakapackercan changeserver_bundle_output_pathbased on Shakapacker 9+private_output_path. Combined with the default:DEFAULT_SERVER_BUNDLE_OUTPUT_PATH = "ssr-generated" ... server_bundle_output_path: DEFAULT_SERVER_BUNDLE_OUTPUT_PATH,and the enforcement:
def validate_enforce_private_server_bundles return unless enforce_private_server_bundles ... server_output_path = File.expand_path(server_bundle_output_path, Rails.root.to_s) return unless server_output_path.start_with?(public_path) raise ReactOnRails::Error, ... endyou still get the problematic scenario:
enforce_private_server_bundlesistrue,server_bundle_output_pathis left at its default ("ssr-generated"), and- Shakapacker 9+ is configured with a
private_output_pathunderpublic/.In that case, enforcement runs against
"ssr-generated"(seen as private), then auto‑detection updatesserver_bundle_output_pathto the public path, so the effective server‑bundle directory can be public without triggering the enforcement error.To ensure
enforce_private_server_bundlesvalidates the actual effective path, auto‑detection should happen before enforcement:def setup_config_values check_autobundling_requirements if auto_load_bundle ensure_webpack_generated_files_exists configure_generated_assets_dirs_deprecation configure_skip_display_none_deprecation check_server_render_method_is_only_execjs error_if_using_packer_and_generated_assets_dir_not_match_public_output_path # check_deprecated_settings adjust_precompile_task check_component_registry_timeout validate_generated_component_packs_loading_strategy - validate_enforce_private_server_bundles - auto_detect_server_bundle_path_from_shakapacker + auto_detect_server_bundle_path_from_shakapacker + validate_enforce_private_server_bundles endThat way,
validate_enforce_private_server_bundlesruns against the sameserver_bundle_output_paththat will be used at runtime and reported by the doctor.Also applies to: 262-312
🧹 Nitpick comments (1)
lib/generators/react_on_rails/generator_helper.rb (1)
99-126: Consider avoiding earlyreturninside the memoization block for clarityThe behavior of
shakapacker_version_9_or_higher?is fine (optimistic default totrueand rescue totrue), but the earlyreturn truemeans the@shakapacker_version_9_or_highercache is never set in the “no PackerUtils yet” case. That’s harmless, just slightly non‑idiomatic.If you want cleaner memoization, you could avoid early returns and always assign the result:
- def shakapacker_version_9_or_higher? - return @shakapacker_version_9_or_higher if defined?(@shakapacker_version_9_or_higher) - - @shakapacker_version_9_or_higher = begin - # If Shakapacker is not available yet (fresh install), default to true - # since we're likely installing the latest version - return true unless defined?(ReactOnRails::PackerUtils) - - ReactOnRails::PackerUtils.shakapacker_version_requirement_met?("9.0.0") - rescue StandardError - # If we can't determine version, assume latest - true - end - end + def shakapacker_version_9_or_higher? + return @shakapacker_version_9_or_higher if defined?(@shakapacker_version_9_or_higher) + + @shakapacker_version_9_or_higher = + if !defined?(ReactOnRails::PackerUtils) + true + else + ReactOnRails::PackerUtils.shakapacker_version_requirement_met?("9.0.0") + end + rescue StandardError + @shakapacker_version_9_or_higher = true + endPurely a style/clarity tweak; behavior is already acceptable.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
docs/api-reference/configuration.md(1 hunks)docs/core-concepts/webpack-configuration.md(1 hunks)lib/generators/react_on_rails/base_generator.rb(1 hunks)lib/generators/react_on_rails/generator_helper.rb(1 hunks)lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt(1 hunks)lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.tt(1 hunks)lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt(1 hunks)lib/react_on_rails/configuration.rb(4 hunks)lib/react_on_rails/doctor.rb(4 hunks)lib/react_on_rails/utils.rb(1 hunks)spec/lib/react_on_rails/doctor_spec.rb(1 hunks)spec/react_on_rails/configuration_spec.rb(1 hunks)spec/react_on_rails/utils_spec.rb(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- spec/react_on_rails/utils_spec.rb
🚧 Files skipped from review as they are similar to previous changes (5)
- docs/core-concepts/webpack-configuration.md
- spec/lib/react_on_rails/doctor_spec.rb
- lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt
- lib/generators/react_on_rails/base_generator.rb
- spec/react_on_rails/configuration_spec.rb
🧰 Additional context used
🧠 Learnings (10)
📚 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/webpack/serverWebpackConfig.js.ttlib/react_on_rails/configuration.rblib/react_on_rails/utils.rbdocs/api-reference/configuration.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/webpack/serverWebpackConfig.js.ttlib/react_on_rails/configuration.rbdocs/api-reference/configuration.mdlib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.tt
📚 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/webpack/serverWebpackConfig.js.ttdocs/api-reference/configuration.mdlib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.tt
📚 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:
lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt
📚 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/configuration.rblib/react_on_rails/utils.rbdocs/api-reference/configuration.mdlib/react_on_rails/doctor.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:
docs/api-reference/configuration.mdlib/generators/react_on_rails/generator_helper.rblib/react_on_rails/doctor.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:
docs/api-reference/configuration.mdlib/generators/react_on_rails/generator_helper.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:
docs/api-reference/configuration.md
📚 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:
docs/api-reference/configuration.md
📚 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/generator_helper.rb
🧬 Code graph analysis (3)
lib/react_on_rails/configuration.rb (1)
lib/react_on_rails/utils.rb (1)
normalize_to_relative_path(471-497)
lib/generators/react_on_rails/generator_helper.rb (1)
lib/react_on_rails/packer_utils.rb (1)
shakapacker_version_requirement_met?(30-33)
lib/react_on_rails/doctor.rb (2)
lib/react_on_rails/system_checker.rb (3)
add_info(28-30)add_success(24-26)add_warning(20-22)lib/react_on_rails/utils.rb (1)
normalize_to_relative_path(471-497)
⏰ 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: examples (3.4, latest)
- GitHub Check: rspec-package-tests (3.4, latest)
- GitHub Check: build
- GitHub Check: claude-review
- GitHub Check: markdown-link-check
🔇 Additional comments (4)
lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml.tt (1)
32-39: Version‑gatedprivate_output_pathtemplate looks correctThe ERB gating, default
ssr-generatedvalue, and explanatory comments all line up with the new Shakapacker 9.0+ integration and React on Rails auto‑detection behavior. No changes needed.lib/react_on_rails/utils.rb (1)
446-499: Path normalization now correctly respects Rails.root boundaries
normalize_to_relative_pathnow uses a boundary‑awareinside_rails_rootcheck and only stripsRails.rootfor exact match or subdirectories, while warning on absolute paths outsideRails.root. This aligns well with the documented examples and closes the earlier prefix‑matching edge case.lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt (1)
47-59: Server bundle output path handling and diagnostics look solidThe
serverBundleOutputPathlogic correctly prefersconfig.privateOutputPathfor Shakapacker 9.0+ with a safe fallback, and the <9.0 path keeps existing behavior. The added runtime warnings for missingprivate_output_pathand for non‑existent output directories are clear and actionable, and they align with the doctor/configuration behavior.Also applies to: 61-61, 71-91
lib/react_on_rails/doctor.rb (1)
670-720: Shakapackerprivate_output_pathdiagnostics are well integrated and consistentThe updated
analyze_server_rendering_configplus the newcheck_shakapacker_private_output_pathhelpers give clear, version‑aware feedback:
- They derive the effective
server_bundle_output_path(defaulting toDEFAULT_SERVER_BUNDLE_OUTPUT_PATH) from the initializer.- For Shakapacker 9.0+, they normalize
private_output_pathviaReactOnRails::Utils.normalize_to_relative_pathand compare it to the Rails setting, emitting either a success or a detailed mismatch warning with remediation.- For older or missing Shakapacker, they provide upgrade/configuration guidance without raising.
This aligns nicely with the runtime auto‑detection logic and should make path issues much easier to diagnose.
Also applies to: 1409-1485
- Add clear deprecation notice with 🚫 DEPRECATED marker - Explain that the option now logs warnings but has no effect - Note that immediate hydration is automatically enabled for Pro users - Provide action required: remove the config line - Include historical context about what the setting used to do - Reference CHANGELOG.md for migration instructions Fixes documentation to match the deprecation shim in configuration.rb (lib/react_on_rails/configuration.rb:79-113) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Shakapacker 9.0+ private_output_path IntegrationI've completed a comprehensive review of this PR. Overall, this is excellent work with strong design, thorough testing, and good backward compatibility. ✅ Strengths1. Excellent Architecture & Design
2. Comprehensive Test Coverage
3. Version-Aware Generator TemplatesThe serverWebpackConfig.js.tt intelligently generates code based on Shakapacker version, ensuring new projects get optimal configuration automatically. 4. Excellent Developer Experience
5. Code Quality
🔍 Minor Issues & SuggestionsLogger Safe Navigation InconsistencySome places use Rails.logger&.debug (configuration.rb:286, 309) while others check defined?(Rails.logger) && Rails.logger (doctor.rb:1404). Recommend using safe navigation operator throughout for consistency. Enhancement Suggestions
🔒 Security Review: ✅ No Security Concerns Found
🎯 Performance: ✅ Efficient Implementation
📝 Documentation Quality: ✅ ExcellentAPI Reference and Webpack Guide provide clear explanations with migration paths. Generator templates have inline comments to guide developers. Well-documented edge cases throughout. Minor suggestion: Consider adding a troubleshooting section for common migration pitfalls. 📊 Summary
✅ Recommendation: APPROVEThis PR is ready to merge. The implementation is solid, well-tested, and provides significant value to users while maintaining full backward compatibility. Key Wins:
Optional Follow-ups (not blocking):
Great work on this feature! This is exactly the kind of DX improvement that makes the gem easier to use. 🎉 Reviewed by Claude Code 🤖 |
|
/run-skipped-tests |
|
/run-skipped-ci |
|
🚀 Full CI Mode Enabled Failed to trigger:
Note: Added the To disable full CI mode, use the View progress in the Actions tab. |
- Simplify log_debug method in doctor.rb to use safe navigation operator (&.) - Remove redundant check for defined?(Rails.logger) && Rails.logger - Consistent with logger usage elsewhere in configuration.rb - No behavioral change, just cleaner code 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this 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
♻️ Duplicate comments (2)
lib/react_on_rails/doctor.rb (2)
670-670: RuboCop directive inconsistency already flagged.The disable directive on line 670 only mentions
Metrics/CyclomaticComplexity, but the enable directive on line 719 mentionsMetrics/CyclomaticComplexitywithoutMetrics/AbcSize. This inconsistency was already noted in a previous review.
721-721: Fix inconsistent RuboCop directive.Line 721 disables only
Metrics/CyclomaticComplexity, but line 766 (the matching enable) mentions bothMetrics/AbcSize, Metrics/CyclomaticComplexity. Update line 721 to disable both metrics for consistency:Apply this diff:
- # rubocop:disable Metrics/CyclomaticComplexity + # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity def analyze_performance_config(content)
🧹 Nitpick comments (2)
docs/api-reference/configuration.md (2)
115-128: Clarify Shakapacker 9.0+ auto-detection behavior in the detailed reference section.The quick-start guidance here (lines 115-128) explains that for Shakapacker 9.0+, users should add
private_output_pathtoconfig/shakapacker.ymland React on Rails will auto-detect it. However, the detailed reference section forserver_bundle_output_pathat lines 456-468 doesn't mention this auto-detection behavior. This could confuse users who skip directly to the reference section into thinking they always need to setconfig.server_bundle_output_pathmanually.Consider updating lines 456-468 to clarify:
- For Shakapacker 9.0+: value is auto-detected from
config/shakapacker.yml- For older versions: manually configure as shown
- The default fallback behavior
This ensures consistency between the quick-start and reference sections.
97-109: Consider a more specific reference to Shakapacker 9.0+ in the Pro features intro.The RSC/Pro features section appropriately points users to external documentation. However, it might be helpful to briefly mention here (or cross-link to lines 115-128) that Pro configuration interacts with Shakapacker 9.0+ private_output_path settings, so users don't assume Pro setup is entirely separate from the server bundle security section below.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
docs/api-reference/configuration.md(1 hunks)lib/react_on_rails/doctor.rb(4 hunks)
🧰 Additional context used
🧠 Learnings (8)
📚 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:
docs/api-reference/configuration.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:
docs/api-reference/configuration.mdlib/react_on_rails/doctor.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:
docs/api-reference/configuration.md
📚 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:
docs/api-reference/configuration.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:
docs/api-reference/configuration.mdlib/react_on_rails/doctor.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:
docs/api-reference/configuration.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:
docs/api-reference/configuration.md
📚 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:
docs/api-reference/configuration.md
🧬 Code graph analysis (1)
lib/react_on_rails/doctor.rb (2)
lib/react_on_rails/system_checker.rb (3)
add_info(28-30)add_success(24-26)add_warning(20-22)lib/react_on_rails/utils.rb (1)
normalize_to_relative_path(471-497)
⏰ 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). (9)
- GitHub Check: dummy-app-integration-tests (3.2, 20, minimum)
- GitHub Check: dummy-app-integration-tests (3.4, 22, latest)
- GitHub Check: rspec-package-tests (3.2, minimum)
- GitHub Check: rspec-package-tests (3.4, latest)
- GitHub Check: examples (3.2, minimum)
- GitHub Check: examples (3.4, latest)
- GitHub Check: build
- GitHub Check: claude-review
- GitHub Check: markdown-link-check
🔇 Additional comments (5)
docs/api-reference/configuration.md (2)
283-300: ✅ Past review comment addressed:immediate_hydrationdeprecation is now clear.The earlier review requested clarity on the
immediate_hydrationdeprecation. This section now properly marks it as deprecated, explains the warning logging behavior, provides migration context, and advises users to remove the setting. This effectively resolves the previous feedback.
140-170: Excellent documentation of bundle organization with clear visual examples.The bundle organization examples and directory structure clearly illustrate the separation between private server bundles and public client bundles. This visual documentation effectively supports the security-focused guidance above it.
lib/react_on_rails/doctor.rb (3)
682-693: LGTM: Well-structured Shakapacker integration check.The new logic correctly extracts the server bundle output path, reports relevant configuration settings, and invokes the Shakapacker integration check. The fallback to
DEFAULT_SERVER_BUNDLE_OUTPUT_PATHensures the code handles unconfigured scenarios gracefully.
1403-1405: LGTM: Safe navigation prevents potential nil errors.The change from
Rails.logger.debugtoRails.logger&.debugis a defensive improvement that gracefully handles scenarios whereRails.loggermight be nil.
1407-1483: LGTM: Well-designed Shakapacker integration diagnostics.The new helper methods provide comprehensive Shakapacker 9.0+ integration checks with clear, actionable guidance:
check_shakapacker_private_output_path: Robust entry point with proper version detection and error handling usingdefined?andrespond_to?.- Path comparison logic correctly normalizes paths and removes trailing slashes to prevent false mismatches.
- User-facing messages are clear, informative, and provide specific recommendations with examples.
- Error handling with
StandardErrorrescue ensures graceful degradation.The implementation aligns well with the PR objectives for auto-detection and migration guidance.
…se-otp-timing * origin/master: (27 commits) Fix doctor command false version mismatch for beta/prerelease versions (#2064) Fix beta/RC version handling in generator (#2066) Document Rails Engine development nuances and add tests for automatic rake task loading (#2067) Add /run-skipped-tests as alias for /run-skipped-ci (#XXXX) (#2068) Fix: Add Rails 5.2-6.0 compatibility for compact_blank (#2058) Break CI circular dependency with non-docs change (#2065) Fix CI safety check to evaluate latest workflow attempt (#2062) Fix yalc publish (#2054) Add Shakapacker 9.0+ private_output_path integration for server bundles (#2028) Consolidate all beta versions into v16.2.0.beta.10 (#2057) Improve reliability of CI debugging scripts (#2056) Clarify monorepo changelog structure in documentation (#2055) Bump version to 16.2.0.beta.10 Bump version to 16.2.0.beta.9 Fix duplicate rake task execution by removing explicit task loading (#2052) Simplify precompile hook and restore Pro dummy app to async loading (#2053) Add Shakapacker precompile hook with ReScript support to Pro dummy app (#1977) Guard master docs-only pushes and ensure full CI runs (#2042) Refactor: Extract JS dependency management into shared module (#2051) Add workflow to detect invalid CI command attempts (#2037) ... # Conflicts: # rakelib/release.rake
Summary
This PR integrates Shakapacker 9.0+
private_output_pathconfiguration with React on Rails, eliminating the need for manualserver_bundle_output_pathconfiguration and providing automatic synchronization between webpack and Rails configs.Key Changes
Auto-Detection
private_output_pathfromshakapacker.yml(Shakapacker 9.0+)"ssr-generated"if not configuredGenerator Updates
private_output_pathfor Shakapacker 9.0+Doctor Enhancements
private_output_pathsupportDocumentation
Benefits
shakapacker.ymlTesting
Migration Path
For users on Shakapacker 9.0+:
private_output_path: ssr-generatedtoconfig/shakapacker.ymlconfig.server_bundle_output_pathfrom React on Rails initializer (optional - auto-detected)rails react_on_rails:doctorto verifyFor users on older Shakapacker:
Related
Supersedes #1967 (rebased for cleaner history)
🤖 Generated with Claude Code
This change is
Summary by CodeRabbit
New Features
Documentation
Tools & Diagnostics
Tests