Skip to content

Conversation

justin808
Copy link
Member

@justin808 justin808 commented Oct 3, 2025

Fixes ReScript deprecation warnings:

  • Change module type from 'es6' to 'esmodule' in bsconfig.json
  • Mark unused event parameter with underscore in error boundary

These changes resolve deprecation warnings shown during ReScript compilation.


This change is Reviewable

Summary by CodeRabbit

  • Chores
    • Updated build configuration to output ES modules while retaining in-source compilation. No user-facing changes.
  • Refactor
    • Cleaned up the Comment form’s button click handler by renaming an unused parameter for clarity. No behavioral changes; form actions and dispatch remain the same.

Copy link

coderabbitai bot commented Oct 3, 2025

Walkthrough

Updates build configuration by switching module type in bsconfig.json to esmodule. Minor UI code tweak in CommentForm: renames an onClick handler parameter to a discarded variable without altering dispatch logic.

Changes

Cohort / File(s) Change Summary
Build config
bsconfig.json
Changed package-specs module from "es6" to "esmodule"; kept in-source compilation enabled.
Comment form handler
client/app/bundles/comments/rescript/CommentForm/CommentForm.res
Renamed onClick parameter from event to _event for a form-type button; no behavioral changes to dispatch or control flow.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I nudge my nose at modules bright,
From es6 to esmodule—clean and light.
A tiny click, an underscore friend,
Events ignored, the actions send.
I thump my paws: builds still hum—
Swift as a hare, the changes come. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The changes only adjust the ReScript configuration and a handler parameter without removing any Babel dependencies, updating Shakapacker settings, adding a .swcrc, or modifying testing and documentation as required by issue #666, so the PR does not meet the linked issue’s core migration requirements. Implement the full migration steps from issue #666 by removing Babel packages, updating shakapacker.yml, adding and configuring .swcrc, adjusting ESLint and Jest for SWC, and updating documentation.
Out of Scope Changes Check ⚠️ Warning The updates to bsconfig.json and CommentForm.res address ReScript warnings and are unrelated to the Babel-to-SWC migration objectives, indicating out-of-scope modifications within this PR. Move the ReScript deprecation fixes into a separate PR or issue and focus this PR exclusively on the SWC migration tasks defined in issue #666.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “Fix ReScript deprecation warnings” accurately describes the changes to the ReScript configuration and code but omits the primary migration from Babel to SWC outlined in the PR objectives, making it only partially related to the main intent.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch justin808/migrate-to-swc

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 543f1a6 and 4332a54.

📒 Files selected for processing (2)
  • bsconfig.json (1 hunks)
  • client/app/bundles/comments/rescript/CommentForm/CommentForm.res (1 hunks)
⏰ 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). (2)
  • GitHub Check: test (22.x, 3.4.6)
  • GitHub Check: deploy
🔇 Additional comments (2)
bsconfig.json (1)

11-11: LGTM! Deprecation warning addressed.

The update from "es6" to "esmodule" correctly addresses the ReScript deprecation warning while maintaining the same module output behavior.

client/app/bundles/comments/rescript/CommentForm/CommentForm.res (1)

107-107: LGTM! Unused variable warning fixed.

The underscore prefix on _event is the idiomatic ReScript convention for intentionally unused parameters, correctly silencing the compiler warning while maintaining type compatibility with the onClick handler signature.


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

❤️ Share

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

Copy link

github-actions bot commented Oct 3, 2025

🚀 Quick Review App Commands

Welcome! Here are the commands you can use in this PR:

/deploy-review-app

Deploy your PR branch for testing

/delete-review-app

Remove the review app when done

/help

Show detailed instructions, environment setup, and configuration options.


@justin808
Copy link
Member Author

/deploy-review-app

Copy link

claude bot commented Oct 3, 2025

Pull Request Review: Migrate from Babel to SWC transpiler

Summary

This PR successfully migrates the project from Babel to SWC, modernizing the build toolchain and aligning with Shakapacker 9.0 defaults. The migration is well-executed with comprehensive configuration updates and dependency management.


Strengths

1. Comprehensive Migration

  • Complete removal of Babel dependencies while retaining @babel/runtime for necessary polyfills
  • Proper SWC configuration in both .swcrc and config/swc.config.js
  • Jest configuration updated to use @swc/jest
  • ESLint properly configured to use espree parser instead of @babel/eslint-parser

2. Configuration Quality

  • Browser targets are consistent across configs (.swcrc, config/swc.config.js, package.json browserslist)
  • Environment-aware settings in config/swc.config.js (development mode, refresh mode)
  • Source maps enabled in webpack config

3. Documentation


Issues and Recommendations

Critical: Configuration Inconsistency

Issue: .swcrc and config/swc.config.js have conflicting React refresh settings:

  • .swcrc:12 has development: false, refresh: true (hardcoded)
  • config/swc.config.js:13-14 has environment-aware logic using process.env

Impact: This creates ambiguity about which config is used when. If both are present, SWC may prioritize one over the other unpredictably.

Recommendation:

  1. Option A (Recommended): Remove .swcrc entirely and rely solely on config/swc.config.js for webpack builds, as it has environment-aware logic
  2. Option B: If .swcrc is needed for non-webpack tooling, clearly document its purpose and ensure settings don't conflict

Performance: Missing jsc.loose

Location: .swcrc

Issue: config/swc.config.js:17 has loose: true but .swcrc doesn't.

Impact: Loose mode generates more performant code. The inconsistency may cause different transpilation behavior.

Recommendation: Add loose: true to .swcrc if it's being used, or remove .swcrc entirely.

Code Quality: ReScript Generated File

Location: client/app/bundles/comments/rescript/RescriptShow/ror_components/RescriptShow.jsx

Issue: This appears to be a ReScript-generated file (line 1: Generated by ReScript, PLEASE EDIT WITH CARE). The 201-line change shows reformatting (quote style changes) but no logical changes.

Questions:

  1. Why was this generated file reformatted? Was it manually edited?
  2. Should generated files be committed at all, or added to .gitignore?
  3. The warning says PLEASE EDIT WITH CARE but the file is generated - this seems contradictory

Minor: Code Style Inconsistencies

Observation: The PR removes trailing newlines from several webpack config files and changes quote styles in server-bundle.js. These are unrelated to the Babel to SWC migration and appear to be incidental formatting changes.


Security Considerations

No security concerns identified:

  • Dependency changes are appropriate (removing Babel, adding SWC)
  • No credential exposure
  • No unsafe code patterns introduced
  • @swc/core is a well-maintained, widely-used tool by Vercel

Test Coverage

Positive:

  • PR description confirms all tests pass (build:test, build:dev, lint, RuboCop)
  • Jest configuration properly updated to use @swc/jest

Concerns:

  1. Missing test coverage for SWC config itself - Consider adding tests that verify JSX transformation, React refresh, and modern JS transpilation work correctly
  2. No explicit migration guide - If other developers need to apply this to their own React-on-Rails projects, documentation would help

Performance Considerations

Positive:

  • PR description claims 10-20x faster build times (excellent!)
  • Lower memory footprint
  • SWC's Rust implementation is significantly faster than Babel's JS

Questions:

  1. Were build times actually measured before/after to confirm the 10-20x improvement?
  2. What about the production bundle size - any changes?

Recommendation: Add before/after metrics to PR description if available.


Best Practices Assessment

Category Rating Notes
Code Quality Good (with concerns) Config duplication needs resolution
Documentation Excellent Clear PR description, test plan included
Testing Good Existing tests pass, but SWC-specific tests would help
Security Excellent No concerns
Performance Excellent Significant improvement expected
Breaking Changes Excellent None - transparent migration

Recommendation

Status: Approve with Changes Requested

This is a solid migration that modernizes the build toolchain. The main blocker is the configuration inconsistency between .swcrc and config/swc.config.js. Once resolved, this should be safe to merge.

Required Changes:

  1. Resolve .swcrc vs config/swc.config.js conflict (pick one or clearly document both)
  2. Add loose: true to .swcrc if keeping it, or remove .swcrc

Suggested Improvements:

  1. Document/explain the ReScript generated file changes
  2. Consider adding a note about actual measured performance improvements
  3. Consider adding SWC-specific integration tests

Great work on this migration! SWC is a significant improvement over Babel for build performance.

@justin808 justin808 force-pushed the justin808/migrate-to-swc branch from 64b0ff4 to 91acf43 Compare October 3, 2025 07:49
Copy link

github-actions bot commented Oct 3, 2025

✅ Deployment complete for PR #669, commit 91acf43

🚀 Review App for PR #669
🎮 Control Plane Console

📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 3, 2025

PR Review: Migrate from Babel to SWC transpiler

Summary

This PR successfully migrates the project from Babel to SWC for JavaScript transpilation. The migration is well-executed with comprehensive configuration updates and proper dependency management.

✅ Strengths

1. Configuration Quality

  • Well-structured SWC configuration: Both .swcrc and config/swc.config.js are properly configured
  • Environment-aware settings: config/swc.config.js correctly uses environment variables for development and refresh settings
  • Browser targets consistency: Browser targets are consistent across .swcrc, config/swc.config.js, and package.json browserslist

2. Dependency Management

  • Clean removal: All Babel-related dependencies properly removed
  • Retained @babel/runtime: Correctly kept @babel/runtime for polyfills (good practice)
  • Appropriate versions: SWC dependencies use appropriate version ranges

3. Testing Setup

  • Jest configuration updated: Properly configured to use @swc/jest instead of babel-jest
  • Test regex maintained: Test patterns remain unchanged, ensuring existing tests will run

4. ESLint Migration

  • Parser switch: Changed from @babel/eslint-parser to espree (standard ESLint parser)
  • Explicit configuration: Added proper parserOptions for ECMAScript 2022 and JSX support

⚠️ Issues & Concerns

1. Configuration Inconsistency (HIGH PRIORITY)

There's a critical inconsistency between .swcrc and config/swc.config.js:

In .swcrc (line 12):

"development": false,

In config/swc.config.js (line 13):

development: process.env.NODE_ENV === 'development',

Issue: .swcrc has development: false hardcoded, which will disable React development mode features even in development builds.

Recommendation:

  • Remove .swcrc entirely and rely solely on config/swc.config.js for dynamic environment handling, OR
  • Update .swcrc to be environment-aware (though this is harder since JSON is static)

The config/swc.config.js approach is superior because it:

  • Dynamically sets development based on NODE_ENV
  • Dynamically sets refresh based on WEBPACK_SERVE
  • Includes loose: true mode for better compatibility
  • Includes sourceMaps: true for debugging

2. Duplicate Configuration Files

Having both .swcrc and config/swc.config.js can lead to confusion about which takes precedence.

Recommendation: Remove .swcrc and use only config/swc.config.js since Shakapacker will load the config from that location.

3. Missing Fast Refresh Configuration in .swcrc

The .swcrc has "refresh": true (line 13) but this should be conditional on the environment. In production, Fast Refresh should be disabled.

4. Security Consideration: axios version

Current: "axios": "^0.21.1" (package.json:44)

Issue: This version has known security vulnerabilities (CVE-2021-3749). While not directly related to this PR, it's worth addressing.

Recommendation: Upgrade axios to ^1.6.0 or later in a follow-up PR.

5. Minor: ESLint Root Configuration

The addition of root: true in .eslintrc is good practice but wasn't mentioned in the PR description.

🔍 Code Quality & Best Practices

Positive Points:

  1. No code logic changes: Pure build tool migration
  2. Comprehensive test plan: PR description shows thorough testing
  3. Proper git attribution: Includes co-author for Claude Code
  4. Browser target alignment: Targets are reasonable and consistent
  5. Shakapacker integration: Correctly updates shakapacker.yml

Suggestions:

  1. Documentation: Consider adding migration notes to README or CHANGELOG for future reference
  2. Performance benchmarks: While the PR mentions "10-20x faster build times", it would be valuable to include actual before/after measurements for this specific project
  3. CI/CD verification: Ensure CI passes with the new transpiler

🧪 Test Coverage

Status: ✅ Test configuration properly updated

  • Jest transform correctly points to @swc/jest
  • Test regex unchanged (maintains existing coverage)
  • Test helper files remain intact

Recommendation: Run the full test suite to ensure no SWC-specific compatibility issues with existing tests.

🚀 Performance Considerations

Expected Benefits:

  • ✅ Faster build times (SWC is Rust-based)
  • ✅ Lower memory usage
  • ✅ Better alignment with Shakapacker 9.0 defaults

No Performance Concerns Identified

🔐 Security Assessment

  1. Low Risk: This migration primarily affects build-time tooling, not runtime code
  2. Dependency Security:
    • New SWC dependencies (@swc/core, @swc/jest, swc-loader) are from the official SWC organization
    • No suspicious dependencies added
  3. Existing Vulnerability: Unrelated axios version issue mentioned above

📋 Recommendations

Required Before Merge:

  1. Fix configuration inconsistency: Resolve the .swcrc vs config/swc.config.js conflict by choosing one configuration file
  2. Test in development mode: Verify React Fast Refresh works correctly
  3. Test in production mode: Ensure production builds work without development features

Recommended Follow-ups:

  1. Document the migration in project docs
  2. Update axios to address security vulnerability
  3. Consider adding a performance benchmark to the PR description
  4. Verify all CI/CD pipelines pass

✅ Verdict

Approval Status: ⚠️ Approve with required changes

This is a high-quality migration PR with excellent structure and testing. However, the configuration file inconsistency must be resolved before merging to ensure proper React development mode behavior.

Recommended Action:

  • Remove .swcrc
  • Rely exclusively on config/swc.config.js for environment-aware configuration
  • Verify Fast Refresh works in development
  • Verify production builds work correctly

Great work on this migration! The move to SWC is a solid choice for improving build performance. 🎉

Copy link

github-actions bot commented Oct 3, 2025

✅ Deployment complete for PR #669, commit 91acf43

🚀 Review App for PR #669
🎮 Control Plane Console

📋 View Completed Action Build and Deploy Logs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (1)
package.json (1)

1-155: Remove remaining Babel-related package

@babel/runtime is still listed in dependencies. Remove it (or provide a justification for its inclusion) to complete the cleanup outlined in issue #666.

🧹 Nitpick comments (1)
package.json (1)

34-34: No direct imports of @babel/runtime detected
All matches are confined to yarn.lock. If your SWC configuration provides the necessary runtime helpers, you can remove @babel/runtime from dependencies. Verify that builds and helper functions remain correct without it.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 79a7efc and 91acf43.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (6)
  • .eslintrc (1 hunks)
  • .swcrc (1 hunks)
  • babel.config.js (0 hunks)
  • config/shakapacker.yml (1 hunks)
  • config/swc.config.js (1 hunks)
  • package.json (2 hunks)
💤 Files with no reviewable changes (1)
  • babel.config.js
🔇 Additional comments (6)
config/swc.config.js (1)

1-32: Good environment-aware configuration.

The use of environment variables for development (line 13) and refresh (line 14) settings is the correct approach, as it allows the configuration to adapt to different build contexts. This is superior to the hardcoded values in .swcrc.

Additional features like loose: true (line 17) and sourceMaps: true (line 22) are appropriate for the build pipeline.

config/shakapacker.yml (1)

11-11: LGTM!

The transpiler configuration correctly switches from Babel to SWC, aligning with the PR objectives.

.eslintrc (1)

10-16: LGTM!

Switching to espree parser with ES2022 support is the correct approach after removing @babel/eslint-parser. The parser options correctly enable JSX and module syntax.

package.json (2)

102-105: LGTM!

The SWC dependencies (@swc/core, @swc/jest, swc-loader) are added with appropriate versions for the migration.


151-151: LGTM!

Jest transform correctly updated to use @swc/jest instead of babel-jest.

.swcrc (1)

1-33: Confirm SWC config usage

Neither .swcrc nor config/swc.config.js are referenced by swc-loader in webpack configs or package.json – verify which file is actually loaded during your build to avoid divergent settings.

@justin808 justin808 force-pushed the justin808/migrate-to-swc branch from 91acf43 to e62c1ea Compare October 3, 2025 08:02
Copy link

github-actions bot commented Oct 3, 2025

✅ Deployment complete for PR #669, commit e62c1ea

🚀 Review App for PR #669
🎮 Control Plane Console

📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 3, 2025

PR Review: Migrate from Babel to SWC transpiler

Summary

This PR successfully migrates the project from Babel to SWC for JavaScript transpilation, aligning with Shakapacker 9.0 defaults. The changes are well-structured and the PR description is comprehensive. Overall, this is a solid migration with minimal issues found.

✅ Strengths

  1. Excellent Documentation: The PR description is thorough, clearly outlining the motivation, changes, and test plan
  2. Clean Dependency Management: Properly removed all Babel-related dependencies while retaining @babel/runtime for polyfills
  3. Configuration Parity: The SWC config appears to replicate the previous Babel functionality appropriately
  4. Comprehensive Testing: Multiple test scenarios were validated (build:test, build:dev, linting, RuboCop)

🔍 Code Quality Findings

config/swc.config.js

Issue 1: Hardcoded String Comparison (Minor)

development: process.env.NODE_ENV === 'development',
refresh: process.env.WEBPACK_SERVE === 'true',

Recommendation: The string comparison for WEBPACK_SERVE is fine, but consider adding a comment explaining that it's a string because environment variables are always strings.

Issue 2: Browser Targets Duplication (Low Priority)

targets: {
  browsers: ['>1%', 'last 5 versions', 'safari >= 7', 'Firefox ESR', 'not IE 11'],
}

Observation: These targets are duplicated in package.json (lines 135-141). While both are valid locations, this creates a maintenance burden. Consider documenting which takes precedence or consolidating to a single source of truth.

Issue 3: CoreJS Mode Configuration (Review Needed)

env: {
  coreJs: 3,
  mode: 'entry',
}

Concern: Using mode: 'entry' requires importing core-js at the entry point of your application. This can result in larger bundle sizes compared to mode: 'usage' which only includes polyfills for features you actually use.

  • Question: Is there a specific core-js import in your entry files?
  • Suggestion: Consider switching to mode: 'usage' for better tree-shaking unless there's a specific reason for entry mode.

.eslintrc

Issue 4: Parser Configuration (Positive Change)

parser: espree
parserOptions:
  ecmaVersion: 2022

Observation: Switching from @babel/eslint-parser to espree is appropriate for this migration. However, ensure that all JavaScript features used in your codebase are supported by ECMAScript 2022. The switch looks good.

Issue 5: Missing Root Setting Explanation

root: true

Observation: Adding root: true is a best practice to prevent ESLint from searching parent directories. Good addition.

🐛 Potential Bugs

1. React Fast Refresh Configuration

In config/swc.config.js:14:

refresh: process.env.WEBPACK_SERVE === 'true',

Potential Issue: This enables React Fast Refresh only when WEBPACK_SERVE === 'true'. Verify that:

  • This environment variable is consistently set during development server runs
  • The @pmmmwh/react-refresh-webpack-plugin in webpack config is also properly configured to work with SWC
  • Fast refresh works as expected in development

2. Loose Mode Implications

In config/swc.config.js:17:

loose: true,

Security/Correctness Concern: Loose mode trades spec compliance for performance/size. This can lead to subtle bugs where code behaves differently from standard JavaScript. Unless you're migrating from Babel with loose mode enabled (which should be verified), consider:

  • Testing thoroughly to ensure no behavioral changes
  • Documenting why loose mode is necessary
  • Consider setting to false for better spec compliance

🚀 Performance Considerations

Positive: The migration to SWC should provide significant performance improvements (10-20x faster builds as noted).

Suggestion: Consider adding build time metrics to your CI/CD to track and validate the performance improvements over time.

🔒 Security Concerns

No Critical Issues Found

Minor observations:

  1. Ensure @swc/core and related packages are kept up to date as SWC is rapidly evolving
  2. The axios version ^0.21.1 in dependencies is outdated and has known security vulnerabilities. Consider upgrading to ^1.6.0 or later (separate issue from this PR, but worth addressing)

📊 Test Coverage

Positive: The PR includes a comprehensive test plan covering:

  • Build processes (test and dev)
  • Linting
  • RuboCop
  • Manual functionality verification

Recommendation: Consider adding:

  1. A simple integration test that specifically validates transpiled output
  2. Bundle size comparison before/after to quantify improvements
  3. Jest test run confirmation (the Jest config was updated but no mention of running tests)

📝 Additional Recommendations

1. Documentation Updates

Consider updating the README or adding migration notes for other developers:

  • Document the SWC migration in CHANGELOG.md
  • Add any SWC-specific troubleshooting tips
  • Document any behavioral changes (if any)

2. Missing .swcrc File

The PR description mentions "Created .swcrc" but I only see config/swc.config.js in the changed files. Clarify:

  • Is .swcrc being used? If so, which takes precedence?
  • Or was this a typo in the PR description?

3. Dependency Version Specifications

"@swc/core": "^1.3.100",
"@swc/jest": "^0.2.29",
"swc-loader": "^0.2.3",

These versions are relatively old. Consider:

  • Using more recent versions (latest @swc/core is 1.7.x as of late 2024)
  • Be mindful of breaking changes in SWC updates

✅ Approval Recommendation

Recommendation: Approve with Minor Changes

This is a well-executed migration. The issues identified are minor and mostly around optimization and documentation. The core functionality appears sound.

Before merging, please address:

  1. Critical: Verify React Fast Refresh works in development
  2. Important: Clarify the coreJs mode choice (entry vs usage)
  3. Nice to have: Run full test suite including Jest tests and report results

Post-merge follow-ups:

  1. Monitor bundle sizes
  2. Update SWC dependencies to latest stable versions
  3. Address axios security vulnerability (separate PR)

Questions for Author

  1. Have you verified React Fast Refresh works correctly with the new setup?
  2. Was the previous Babel config using loose mode? (This would explain the SWC loose mode setting)
  3. Do you have core-js imported in your entry files for the mode: 'entry' setting?
  4. Have you run the full Jest test suite with @swc/jest?

Great work on this migration! 🎉


Review generated with assistance from Claude Code

@justin808 justin808 force-pushed the justin808/migrate-to-swc branch from e62c1ea to 683b1e9 Compare October 3, 2025 21:35
Copy link

github-actions bot commented Oct 3, 2025

✅ Deployment complete for PR #669, commit 683b1e9

🚀 Review App for PR #669
🎮 Control Plane Console

📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 3, 2025

Pull Request Review: Migrate from Babel to SWC transpiler

Overall Assessment

This is a well-executed migration that modernizes the build toolchain. The changes are thorough, well-documented, and the test plan demonstrates due diligence. ✅


Code Quality & Best Practices

✅ Strengths

  1. Clean migration path: Properly removed all Babel dependencies and replaced with SWC equivalents
  2. Configuration parity: The config/swc.config.js maintains equivalent settings to the previous babel.config.js
  3. Comprehensive test plan: All critical build steps were verified
  4. Good documentation: Clear PR description with rationale and breaking changes section

⚠️ Areas for Improvement

1. SWC Configuration - Browser Targets (config/swc.config.js:26)

The env.mode: 'entry' configuration is typically a Babel-specific setting for polyfills. With SWC, you should verify this is having the intended effect:

env: {
  targets: {
    browsers: ['>1%', 'last 5 versions', 'safari >= 7', 'Firefox ESR', 'not IE 11'],
  },
  coreJs: 3,
  mode: 'entry',  // ⚠️ Verify this works as intended with SWC
}

Recommendation: SWC's env.mode may not behave identically to Babel's. Consider:

  • Testing that polyfills are being correctly included
  • Potentially switching to mode: 'usage' for better tree-shaking
  • Or explicitly configure polyfill strategy in webpack config

2. ESLint Parser Change (.eslintrc:10)

Switching from @babel/eslint-parser to espree is a regression in capability:

parser: espree  # ⚠️ Less capable than babel parser

Potential issues:

  • espree doesn't support modern JavaScript features as well as Babel parser
  • You're using ecmaVersion: 2022, but your code may use newer features
  • React automatic JSX runtime may cause issues with older parsers

Recommendation: Consider using @typescript-eslint/parser (even for JS) or keeping a parser that understands modern syntax better. If sticking with espree, explicitly test that it lints all your modern syntax correctly.

3. Missing .swcrc File

The PR mentions creating .swcrc in the description, but I don't see this file in the changes. The configuration is in config/swc.config.js instead.

Recommendation:

  • Update PR description to match actual implementation
  • Verify Shakapacker correctly reads from config/swc.config.js
  • Consider if a root .swcrc would be more standard

Potential Bugs & Issues

🔴 Critical: Generated i18n Files Committed

The biggest concern is committing previously generated files:

Files: client/app/libs/i18n/translations.js and client/app/libs/i18n/default.js

# .gitignore
-client/app/libs/i18n/translations.js
-client/app/libs/i18n/default.js
+# Note: These files are now required for the build, so we commit them

Issues:

  1. Why are these now required? - This suggests a build process change that's not explained
  2. ⚠️ Workflow change - Developers must remember to regenerate and commit these files when translations change
  3. 🐛 Potential for stale data - If the generation process is manual, files can become outdated
  4. 📝 Missing documentation - No documentation on when/how to regenerate these files

Recommendations:

  • Explain in PR why SWC requires these to be committed (unlike Babel)
  • Document the regeneration workflow in README or contributing docs
  • Consider adding a pre-commit hook to regenerate these files
  • Or better: find a way to generate these at build time so they don't need to be committed

⚠️ Loose Mode Enabled (config/swc.config.js:17)

loose: true,  // ⚠️ Non-spec-compliant transformations

While this improves performance, it can cause subtle bugs if code relies on spec-compliant behavior. This was likely carried over from Babel config, but verify it's intentional.


Performance Considerations

Excellent Performance Gains

The migration to SWC should deliver the promised 10-20x build performance improvement. Good choice for build optimization.

💡 Consider:

  1. Benchmark before/after: Document actual build time improvements for this specific project
  2. Watch mode performance: Test HMR/fast refresh still works smoothly with SWC
  3. CI build times: Monitor if CI builds are actually faster

Security Concerns

No major security issues

The migration removes dependencies, which reduces attack surface. Good security hygiene.

💡 Minor notes:

  1. axios: "^0.21.1" (package.json:44) is quite old and has known vulnerabilities. Consider updating to latest (separate issue, not introduced by this PR)
  2. SWC is a Rust-based tool with generally good security track record

Test Coverage

⚠️ Testing Gaps

The PR description shows manual testing, but:

  1. No automated test changes visible: Verify that existing Jest tests all pass with @swc/jest
  2. Missing integration test results: Show test suite output before/after
  3. React Fast Refresh: Explicitly test HMR in development mode
  4. Production build: Verify production bundle size and behavior

Recommendation:

  • Add test results to PR description
  • Consider adding a test that verifies transpilation is working correctly

Additional Recommendations

📋 Documentation

  1. Update project README with new build toolchain info
  2. Document any developer workflow changes
  3. Add troubleshooting section for SWC-specific issues

🔧 Follow-up Tasks

Consider these improvements in future PRs:

  1. Enable SWC's experimental decorators if you start using them
  2. Explore SWC's jsc.minify for additional optimization
  3. Monitor SWC releases for bug fixes and performance improvements

Summary

Category Rating Notes
Code Quality ⭐⭐⭐⭐ Well-structured migration
Potential Bugs ⚠️ i18n files concern needs clarification
Performance ⭐⭐⭐⭐⭐ Excellent performance gains expected
Security No new security concerns
Test Coverage ⚠️ Need to verify automated tests
Documentation ⭐⭐⭐ Good PR docs, could improve project docs

Overall: Approve with minor concerns addressed. The migration is solid, but please clarify the i18n files situation and verify the ESLint parser works correctly with all your modern JavaScript syntax.


Review generated with 🤖 attention to detail and developer empathy

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
config/swc.config.js (1)

1-32: SWC configuration suggestions

  • react.runtime: 'automatic' — correct for React 19.
  • loose: true — improves speed but may deviate from spec; test for subtle differences.
  • decorators: false — no decorators detected in the codebase.
  • env.mode: 'entry' — pulls in all core-js polyfills; consider mode: 'usage' to trim bundle size.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 91acf43 and 683b1e9.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (9)
  • .eslintignore (0 hunks)
  • .eslintrc (1 hunks)
  • .gitignore (1 hunks)
  • babel.config.js (0 hunks)
  • client/app/libs/i18n/default.js (1 hunks)
  • client/app/libs/i18n/translations.js (1 hunks)
  • config/shakapacker.yml (1 hunks)
  • config/swc.config.js (1 hunks)
  • package.json (2 hunks)
💤 Files with no reviewable changes (2)
  • .eslintignore
  • babel.config.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • .eslintrc
🧰 Additional context used
🪛 GitHub Actions: JS CI
client/app/libs/i18n/translations.js

[error] 1-1: ESLint: 'import/prefer-default-export' - Prefer default export on a file with a single export.

🪛 GitHub Actions: Lint CI
client/app/libs/i18n/translations.js

[error] 1-1: import/prefer-default-export: Prefer default export on a file with single export

🪛 GitHub Check: test (22.x, 3.3.4)
client/app/libs/i18n/translations.js

[failure] 1-1:
Prefer default export on a file with single export

⏰ 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). (2)
  • GitHub Check: deploy
  • GitHub Check: test (22.x, 3.3.4)
🔇 Additional comments (6)
.gitignore (1)

44-46: LGTM! Clear documentation of the change.

The comment effectively explains why these i18n files are now committed to the repository instead of being ignored, aligning with the new i18n files added in this PR.

client/app/libs/i18n/default.js (1)

1-26: LGTM! Well-structured i18n defaults.

The implementation follows react-intl best practices:

  • Consistent message ID naming convention (app.*)
  • Clear separation of default locale and messages
  • Proper use of defineMessages for message descriptors
config/shakapacker.yml (1)

11-11: LGTM! Core migration change.

This change switches the JavaScript transpiler from Babel to SWC, which is the primary objective of this PR. The configuration aligns with the new SWC config file at config/swc.config.js.

package.json (3)

34-34: LGTM! Correct retention of @babel/runtime.

The @babel/runtime package is correctly retained despite migrating to SWC. This package provides runtime helpers and polyfills that are still needed regardless of the transpiler used.


102-103: LGTM! SWC dependencies added.

The SWC packages are correctly added to devDependencies:

  • @swc/core - the core SWC compiler
  • @swc/jest - Jest transformer using SWC
  • swc-loader - webpack loader for SWC

Also applies to: 105-105


150-151: LGTM – Jest transform updated to @swc/jest; Babel deps removed
All Babel dependencies from issue #666 are removed and @babel/runtime remains.

@justin808 justin808 force-pushed the justin808/migrate-to-swc branch from 683b1e9 to 4f3af19 Compare October 3, 2025 21:52
Copy link

github-actions bot commented Oct 3, 2025

✅ Deployment complete for PR #669, commit 4f3af19

🚀 Review App for PR #669
🎮 Control Plane Console

📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 3, 2025

PR Review: Migrate from Babel to SWC transpiler

Overall Assessment

Excellent migration! This PR successfully modernizes the build toolchain with significant performance benefits and no breaking changes. The implementation is clean, well-documented, and thorough.


Code Quality & Best Practices

✅ Strengths

  1. Clean dependency migration - Properly removed all Babel-specific packages while retaining @babel/runtime for polyfills
  2. Comprehensive configuration - SWC config properly mirrors the previous Babel setup
  3. Test infrastructure updated - Jest correctly configured with @swc/jest
  4. Documentation - Excellent PR description with clear motivation and test plan

⚠️ Minor Concerns

1. SWC Config Structure (config/swc.config.js:1-32)

The current config wraps everything in an options object. Verify this structure matches your Shakapacker configuration. Some SWC loaders expect the top-level to be the configuration directly.

Check Shakapacker 9.0 docs to confirm the expected format.

2. ESLint Parser Configuration (.eslintrc:10)

The explicit parser: espree is good for clarity, but ensure it is compatible with all your syntax features. Espree does not always handle cutting-edge ECMAScript features as well as dedicated parsers.

Consider: Testing against any newer syntax (optional chaining, nullish coalescing, etc.) to ensure ESLint still works correctly.


Potential Bugs & Issues

⚠️ Translation Files Strategy

Issue: The i18n files (client/app/libs/i18n/default.js and translations.js) were previously gitignored and are now committed.

Analysis:

  • Pro: Simplifies build process by not requiring generation
  • Con: If these files were auto-generated from a source (e.g., i18n-js gem), you may have issues with stale translations or merge conflicts

Questions:

  1. Are these files still auto-generated by the i18n-js gem?
  2. If yes, how will you handle updates without conflicts?
  3. If no, do you have a process for maintaining translations across locales?

Recommendation: If these are generated files, consider:

  • Adding a comment header indicating they are generated
  • Creating a script/task to regenerate them
  • Documenting the generation process in the README

⚠️ SWC Browser Targets (config/swc.config.js:25-26)

These targets are quite broad (Safari 7 is from 2013). This may bloat your bundle with unnecessary polyfills.

Recommendation: Review and modernize browser targets based on your actual user analytics.


Performance Considerations

✅ Excellent

  1. Build performance - SWC should deliver the promised 10-20x speedup
  2. Memory footprint - Reduced memory usage during builds
  3. Bundle size - Should remain unchanged (same transformations)

💡 Optimization Opportunity

Source maps configuration (config/swc.config.js:22): Consider using inline source maps in development for faster builds, and true (separate files) only in production.


Security Concerns

✅ No Major Issues

  1. Dependency updates - All new dependencies are from reputable sources (@swc is well-maintained)
  2. No sensitive data - Translation files contain only public-facing strings
  3. No new attack vectors - Build-time only dependencies

💡 Recommendation

Run yarn audit to check for any vulnerabilities in the new dependency tree.


Test Coverage

✅ Excellent

  • Test build passes
  • Development build passes
  • ESLint passes
  • RuboCop passes
  • Functionality tested

Recommendation: Consider adding a regression test to verify:

  1. Hot reload still works in development
  2. CSS Modules compilation still works
  3. React refresh functionality works

Additional Recommendations

1. Add SWC Jest Configuration

Currently Jest is configured in package.json. Consider creating a .swcrc for Jest or adding SWC-specific jest config for better control.

2. Document the Migration

Consider adding a section to your README or a dedicated MIGRATION.md documenting:

  • Why you migrated to SWC
  • Performance improvements observed
  • Any gotchas for contributors
  • How to troubleshoot SWC-specific issues

3. Cleanup Verification

Double-check that no Babel-related files remain.


Summary

Verdict:Approve with minor recommendations

This is a well-executed migration that modernizes your build toolchain. The concerns raised are minor and mostly focused on ensuring long-term maintainability.

Key Action Items:

  1. ✓ Verify SWC config structure with Shakapacker docs
  2. ✓ Clarify i18n file generation strategy
  3. ✓ Consider modernizing browser targets
  4. ✓ Run security audit on new dependencies

Merge Confidence: High - This change is well-tested and thoroughly documented.


Great work on this migration! The performance improvements will significantly enhance the developer experience. 🚀

Copy link

github-actions bot commented Oct 3, 2025

✅ Deployment complete for PR #669, commit 24481d3

🚀 Review App for PR #669
🎮 Control Plane Console

📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 3, 2025

Pull Request Review: Migrate from Babel to SWC transpiler

Overall Assessment

This is a well-executed migration that modernizes the build toolchain. The PR demonstrates thorough testing and clear documentation. However, there are a few issues that should be addressed.


🔴 Critical Issues

1. Missing .swcrc Configuration File

Location: Root directory
Issue: The PR description mentions "Created .swcrc with equivalent Babel settings" but this file is not included in the changes. Only config/swc.config.js exists.

Impact: This could cause inconsistent transpilation behavior or build failures depending on how Shakapacker loads SWC configuration.

Recommendation:

  • Either add the missing .swcrc file, or
  • Update the PR description to remove the reference to .swcrc, or
  • Clarify that config/swc.config.js is being used instead of .swcrc

⚠️ Moderate Issues

2. SWC Configuration: env.mode Setting

Location: config/swc.config.js:29
Issue: The env.mode: 'entry' configuration may not work as expected with SWC.

Explanation: In Babel, useBuiltIns: 'entry' requires explicit polyfill imports. However, SWC's env.mode works differently and may not provide the same behavior. The mode option typically controls how polyfills are injected, but SWC's implementation differs from Babel's.

Recommendation:

  • Review SWC documentation for the correct way to handle polyfills
  • Consider using env.mode: 'usage' for automatic polyfill injection
  • Test polyfill behavior across target browsers
  • May want to remove this setting if relying on @babel/runtime for polyfills

3. Browser Targets Configuration

Location: config/swc.config.js:26
Issue: The browser targets list is quite broad: ['>1%', 'last 5 versions', 'safari >= 7', 'Firefox ESR', 'not IE 11']

Concerns:

  • Including 'last 5 versions' can be overly broad and increase bundle size
  • Safari 7 is from 2013 - likely unnecessary for most modern apps
  • The combination of >1% and last 5 versions may be redundant

Recommendation:

browsers: ['>0.5%', 'not dead', 'not IE 11', 'not op_mini all']

4. New Translation Files Without Context

Location: client/app/libs/i18n/translations.js, client/app/libs/i18n/default.js
Issue: These files were previously gitignored and auto-generated, but are now committed to the repository.

Concerns:

  • The PR description doesn't explain why these files need to be committed now
  • Comment in .gitignore:44 says "These files are now required for the build" but doesn't explain why the migration necessitates this change
  • Risk of merge conflicts if these files are modified both manually and by automated processes

Questions:

  • Are these still auto-generated, or are they now manually maintained?
  • If auto-generated, should they remain gitignored with a build step to generate them?
  • Does SWC not support the same dynamic loading that Babel did?

Recommendation: Add clarification in the PR description or in code comments explaining this architectural change.


💡 Minor Issues & Suggestions

5. ESLint Disable Directive

Location: client/app/libs/i18n/translations.js:1
Issue: The /* eslint-disable import/prefer-default-export */ comment seems unnecessary.

Explanation: The file has both named and default exports (export { translations }; export default translations), so the prefer-default-export rule shouldn't trigger. The second commit message mentions this was needed for CI, but it may indicate a configuration issue.

Recommendation:

  • Verify that both export styles are actually needed
  • If only one export style is used in the codebase, standardize on that
  • Consider fixing the root cause rather than disabling the lint rule

6. ESLint Parser Configuration

Location: .eslintrc:10-16
Issue: Switching from @babel/eslint-parser to espree with ecmaVersion: 2022 is appropriate, but may not support all modern syntax.

Recommendation:

  • Verify that all JavaScript syntax in the codebase is supported by ES2022
  • Consider updating to ecmaVersion: 'latest' or a specific newer version if using newer features
  • Test linting across all files to ensure no syntax errors

7. Jest Transform Configuration

Location: package.json:151
Recommendation: Consider adding SWC configuration for Jest to ensure test transpilation matches production. You may want to create a .swcrc for Jest or configure it in package.json:

"transform": {
  "^.+\\.jsx?$": ["@swc/jest", {
    "jsc": {
      "parser": {
        "syntax": "ecmascript",
        "jsx": true
      }
    }
  }]
}

✅ Strengths

  1. Comprehensive Testing: All critical build and test commands verified
  2. Clean Dependency Management: Properly removed Babel dependencies while retaining @babel/runtime for polyfills
  3. Documentation: Clear PR description with benefits and migration rationale
  4. Backwards Compatibility: No breaking changes for consumers
  5. Configuration: React Fast Refresh properly configured for development

🔒 Security Considerations

No security concerns identified. The migration removes dependencies which reduces the attack surface.


🧪 Test Coverage

Status: ✅ Adequate

The PR author has tested:

  • Production build (yarn build:test)
  • Development build (yarn build:dev)
  • Linting (yarn lint)
  • Ruby linting (bundle exec rubocop)

Recommendation:

  • Run the full Jest test suite to ensure @swc/jest works correctly
  • Verify that test coverage metrics remain consistent
  • Test in a production-like environment before deploying

📝 Recommendations Summary

Before merging:

  1. ✅ Clarify or add the missing .swcrc file
  2. ✅ Review the env.mode: 'entry' configuration
  3. ✅ Add explanation for why translation files are now committed
  4. ⚠️ Consider optimizing browser targets

After merging:

  1. Monitor build times and bundle sizes to verify expected performance improvements
  2. Watch for any runtime issues related to polyfills or transpilation differences

Final Verdict

Approve with minor changes recommended. This is a solid migration that will improve build performance significantly. The issues identified are mostly clarifications and optimizations rather than blockers.

Great work on this modernization effort! 🚀


Review generated with Claude Code

@justin808 justin808 force-pushed the justin808/migrate-to-swc branch from 24481d3 to 3676023 Compare October 3, 2025 23:16
Copy link

claude bot commented Oct 4, 2025

Pull Request Review: Migrate from Babel to SWC transpiler

Overall Assessment ✅

This is a well-executed migration that follows Shakapacker's official migration process. The changes are clean, comprehensive, and appropriately scoped. The PR demonstrates good engineering practices with thorough testing and clear documentation.


✅ Strengths

  1. Proper Migration Approach

    • Using the official rails shakapacker:migrate_to_swc task ensures best practices
    • All configuration changes align with Shakapacker 9.0 defaults
    • Performance improvements (10-20x build times) justify the migration
  2. Clean Dependency Management

    • Correctly removed all Babel-specific packages except @babel/runtime (needed for polyfills)
    • Added appropriate SWC equivalents: @swc/core, @swc/jest, swc-loader
    • Package lock file generated properly
  3. Thoughtful Edge Cases

    • Fixed ReScript deprecation (es6esmodule) - good proactive maintenance
    • Fixed unused variable warning in CommentForm.res (event → _event)
    • Jest configuration properly updated to use @swc/jest
  4. Comprehensive Testing

    • Test plan covers all critical areas (build, dev, ESLint, RuboCop)
    • No breaking changes claimed and verified

⚠️ Issues & Concerns

CRITICAL: Mixed Transpiler Configuration

Issue in commonWebpackConfig.js:76-109:
The code adds Babel back for Stimulus controllers while migrating everything else to SWC. This creates a hybrid setup:

// Excludes Stimulus controllers from SWC
config.module.rules[swcRuleIndex].exclude = [
  originalExclude,
  controllersPath
].filter(Boolean);

// Then adds Babel loader ONLY for Stimulus controllers
config.module.rules.push({
  test: /\.js$/,
  include: controllersPath,
  use: {
    loader: 'babel-loader',
    options: {
      presets: [
        ['@babel/preset-env', {
          useBuiltIns: 'entry',
          corejs: 3,
          // ...
        }]
      ]
    }
  }
});

Concerns:

  1. Dependency Conflict: Babel dependencies are in devDependencies but this requires babel-loader + @babel/preset-env at runtime
  2. Performance Impact: Defeats the purpose of the SWC migration for a portion of the codebase
  3. Maintenance Burden: Now maintaining TWO transpiler configurations
  4. Missing Context: The PR description doesn't explain WHY this dual setup is needed

Questions:

  • Why can't Stimulus controllers be transpiled with SWC?
  • Is there a specific SWC limitation with Stimulus controllers?
  • The swc.config.js has keepClassNames: true - was this intended for Stimulus? Does it work?

Recommendation:

  • If SWC can handle Stimulus (with keepClassNames: true), remove the Babel loader entirely
  • If Babel is truly needed, document the reason in code comments and PR description
  • Consider testing if SWC works with Stimulus before keeping this complexity

MODERATE: ESLint Configuration Issue

Issue in .eslintrc:8-12:

parserOptions:
  requireConfigFile: false
  babelOptions:
    presets:
      - "@babel/preset-react"

Concerns:

  1. Still references Babel in ESLint config despite migrating to SWC
  2. Dependency on deleted config: requireConfigFile: false suggests ESLint expects babel.config.js (now deleted)
  3. Inline Babel preset: This hardcodes @babel/preset-react, which should be in a shared config

Why this works (but is problematic):

  • ESLint uses @babel/eslint-parser which needs Babel config for parsing
  • The inline config compensates for the deleted babel.config.js
  • However, this creates inconsistency: ESLint parses with Babel, but builds with SWC

Recommendation:

  • Consider switching to @typescript/eslint-parser or another non-Babel parser
  • If Babel parser is required, document why in comments
  • Ensure @babel/preset-react in ESLint config matches SWC's React transform settings

MINOR: Missing corejs Dependency

Issue in commonWebpackConfig.js:100:

corejs: 3,

Concern:

  • The Babel loader config references corejs: 3 but core-js is not in package.json
  • This will fail if Babel actually tries to use it

Recommendation:

  • Add core-js@3 to dependencies if needed
  • Or remove corejs: 3 / useBuiltIns: 'entry' if not required for Stimulus controllers

MINOR: Incomplete SWC Configuration

Issue in config/swc.config.js:

module.exports = {
  jsc: {
    transform: {
      react: {
        runtime: "automatic"
      }
    },
    keepClassNames: true
  }
};

Observations:

  1. Missing target configuration: No env.targets specified (browser support)
  2. No minification settings: Production builds might need minify options
  3. Minimal transform options: Consider externalHelpers, parser settings

Comparison to deleted Babel config:
The old babel.config.js had:

  • React preset with development flag
  • react-refresh/babel for HMR
  • transform-react-remove-prop-types for production

Recommendation:

  • Add equivalent SWC settings for production optimization
  • Consider SWC's removeConsole, optimizer options
  • Add target browsers from package.json browserslist

🔒 Security Considerations

✅ No security concerns identified:

  • No new external dependencies with known vulnerabilities
  • No credential exposure
  • No insecure code patterns introduced
  • Dependency updates are within safe ranges

Note: The existing axios@^0.21.1 (line 44 in package.json) is outdated and has known vulnerabilities, but that's pre-existing and outside this PR's scope.


📊 Performance Considerations

✅ Positive:

  • SWC is 10-20x faster than Babel for transpilation
  • Lower memory footprint during builds
  • Actively maintained and optimized

⚠️ Concerns:

  • The dual Babel/SWC setup negates some performance benefits
  • If Stimulus controllers are in the hot path during development, you'll still hit Babel's slower transpilation

🧪 Test Coverage

✅ Adequate testing:

  • Build tests passing
  • Linting verified
  • Functionality confirmed

Recommendation:

  • Consider adding a specific test for Stimulus controllers to ensure the Babel loader works correctly
  • Verify HMR (Hot Module Replacement) still works with the new setup

📝 Suggestions for Improvement

  1. Clarify the Babel/SWC dual setup - Add comments explaining why Stimulus needs Babel
  2. Verify Stimulus + SWC compatibility - Test if keepClassNames: true in SWC is sufficient
  3. Enhance SWC configuration - Add production optimizations and target browsers
  4. Update ESLint parser strategy - Consider alternatives to Babel parser or document the decision
  5. Add core-js if needed - Or remove the corejs references from Babel config
  6. Consider a follow-up PR - To remove the Babel loader if SWC testing succeeds

🎯 Verdict

Conditional Approval ✅ with Requested Changes

The migration is fundamentally sound, but the hybrid Babel/SWC setup needs clarification:

Action Items:

  1. Merge as-is if Stimulus truly requires Babel (but document why)
  2. 🔧 Better: Test SWC with Stimulus and remove Babel loader if possible
  3. 📝 Add comments explaining the dual transpiler setup in commonWebpackConfig.js

Great work on the migration! The thoroughness of testing and use of official tools is commendable. Just needs clarity on the architectural decision to maintain two transpilers.


Reviewed by Claude Code

Copy link

github-actions bot commented Oct 4, 2025

🎉 ✨ Deploy Complete! 🚀

🌐 ➡️ Open Review App

Deployment successful for PR #669, commit 0be82af

🎮 Control Plane Console
📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 4, 2025

Pull Request Review: Migrate from Babel to SWC transpiler

Summary

This PR migrates the project from Babel to SWC for JavaScript transpilation. Overall, this is a well-executed migration with good documentation. However, there are some significant concerns that should be addressed before merging.


🔴 Critical Issues

1. Hybrid Babel/SWC Configuration Creates Inconsistency

Location: config/webpack/commonWebpackConfig.js:76-110

The PR claims to migrate to SWC, but actually implements a hybrid approach where:

  • TypeScript files use SWC
  • JavaScript files still use Babel (with inline config)

Issues:

  • Defeats the purpose: The main benefits cited (10-20x faster builds, lower memory) won't be realized if JS files still use Babel
  • Configuration duplication: Babel config is now in two places (.eslintrc and webpack config), violating DRY
  • Maintenance burden: Team must maintain both transpilers
  • Inconsistent behavior: TS and JS files transpiled differently could lead to subtle bugs

Recommendation:

  • Either fully migrate to SWC for all files, or
  • Document clearly why this hybrid approach is necessary (the comment mentions "SWC has compatibility issues with Stimulus" but no evidence is provided)
  • If Stimulus compatibility is truly an issue, create an issue to track full migration

2. ESLint Still Depends on Babel

Location: .eslintrc:8-12

parserOptions:
  requireConfigFile: false
  babelOptions:
    presets:
      - "@babel/preset-react"

Issues:

  • ESLint still requires @babel/preset-react even though it's no longer in the Babel config
  • This creates a hidden dependency that could break if Babel packages are removed
  • Inconsistent with the claim that Babel has been removed

Recommendation:

  • If using @babel/eslint-parser, consider switching to @typescript-eslint/parser for consistency
  • Or clearly document why Babel is still needed for linting

3. Missing core-js Dependency

Location: config/webpack/commonWebpackConfig.js:96

The Babel config specifies:

useBuiltIns: 'entry',
corejs: 3,

But I don't see core-js in the package.json dependencies. This could cause runtime errors.

Recommendation: Add core-js@3 to dependencies if using useBuiltIns: 'entry'


⚠️ High Priority Issues

4. Babel Loader Added Back as Dev Dependency

Location: package.json:110

The PR adds babel-loader to devDependencies, which contradicts the migration goal. While this might be intentional for the hybrid approach, it should be:

  • Moved to regular dependencies (since it's used in production builds)
  • OR removed entirely if fully migrating to SWC

5. Incomplete SWC Configuration

Location: config/swc.config.js

The SWC config is minimal compared to what Babel was doing:

Missing from SWC config:

  • Polyfill handling (Babel had useBuiltIns)
  • Browser targets (Babel had browserslist integration)
  • Production optimizations (Babel had react-remove-prop-types)
  • Development features (Babel had react-refresh)

Recommendation:

  • Add target environment configuration to SWC
  • Consider using swc's env option to match browserslist targets
  • Document what optimizations were intentionally dropped

6. Test Coverage

The PR description mentions tests pass, but:

  • No new tests for the SWC configuration
  • No tests verifying the hybrid loader behavior
  • No performance benchmarks to validate the "10-20x faster" claim

Recommendation: Add integration tests that verify both TS (SWC) and JS (Babel) files transpile correctly


💡 Medium Priority Issues

7. Potential Race Condition in Rule Modification

Location: config/webpack/commonWebpackConfig.js:78-84

The code modifies webpack rules based on regex matching the test property:

const swcRuleIndex = config.module.rules.findIndex(rule =>
  rule.test && /\.(ts|tsx|js|jsx|mjs|coffee)/.test(rule.test.toString())
);

Issues:

  • Fragile: Depends on Shakapacker's internal rule structure
  • Could break with Shakapacker updates
  • The regex in the finder doesn't match exactly what Shakapacker creates

Recommendation: Add defensive checks and error logging if rule not found

8. Missing Documentation in Code

Location: config/webpack/commonWebpackConfig.js:76-110

The added code has only one comment. Should document:

  • Why the hybrid approach was chosen
  • What "compatibility issues with Stimulus" means specifically
  • When full SWC migration is planned

9. ReScript Changes Unrelated to Migration

Location: bsconfig.json, client/app/bundles/comments/rescript/CommentForm/CommentForm.res

While good fixes, these should arguably be in a separate PR since they're unrelated to the Babel→SWC migration.


✅ What's Done Well

  1. Good PR description: Clear summary with test plan and migration method
  2. Used official migration tool: Leveraged rails shakapacker:migrate_to_swc
  3. Dependency cleanup: Properly removed unused Babel plugins
  4. ReScript fixes: Fixed deprecations proactively
  5. Breaking changes: Correctly noted no breaking changes
  6. Jest configuration: Updated test transformer correctly

🔒 Security Considerations

  • axios@0.21.1: This version has known security vulnerabilities (CVE-2021-3749). Should be updated to >=0.21.2 (separate issue, but worth noting)
  • loader-utils@1.1.0: Very outdated, has known vulnerabilities. Should update to >=2.0.4
  • No new security concerns introduced by this PR specifically

🎯 Performance Considerations

  • Claim of 10-20x faster builds: Needs validation since JS files still use Babel
  • Two transpilers running: May actually slow down builds vs. single transpiler
  • Recommendation: Run benchmarks comparing build times before/after this change

📝 Recommendations Summary

Before merging:

  1. ✅ Decide: Full SWC migration vs. documented hybrid approach
  2. ✅ Add core-js dependency if needed
  3. ✅ Fix ESLint Babel dependency or document why needed
  4. ✅ Add comprehensive SWC configuration matching Babel's functionality
  5. ✅ Add integration tests for transpilation
  6. ✅ Document the hybrid approach in code comments
  7. ✅ Run and document actual performance benchmarks

After merging:
8. Create issue to track full SWC migration (if hybrid approach chosen)
9. Create issue to update vulnerable dependencies
10. Consider splitting ReScript changes to separate PR


Overall Assessment

Code Quality: ⚠️ Good structure but significant architectural concerns
Best Practices: ⚠️ Hybrid approach needs justification
Potential Bugs: 🔴 Missing core-js could cause runtime errors
Security: ✅ No new issues introduced
Test Coverage: ⚠️ Needs more comprehensive tests

Recommendation: Request Changes - The hybrid approach needs to be either fully justified with documentation, or the PR should be updated to complete the full SWC migration as the title suggests.


Great work on tackling this migration! The execution is clean and the PR description is excellent. The main concern is ensuring the implementation matches the stated goals and that all edge cases are covered.

🤖 Review generated with Claude Code

Copy link

github-actions bot commented Oct 4, 2025

🎉 ✨ Deploy Complete! 🚀

🌐 ➡️ Open Review App

Deployment successful for PR #669, commit 21e9a2c

🎮 Control Plane Console
📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 4, 2025

Pull Request Review: Migrate from Babel to SWC Transpiler

Summary

This PR migrates the project from Babel to SWC for JavaScript transpilation. The migration is well-documented and follows Shakapacker's official migration process. Overall, this is a solid implementation with good attention to compatibility concerns.


✅ Strengths

  1. Well-Documented Migration: Using the official Shakapacker rake task (shakapacker:migrate_to_swc) ensures best practices
  2. Comprehensive Testing: The PR description indicates all tests pass (build, dev, ESLint, RuboCop)
  3. Bonus Fixes: Addresses ReScript deprecation warnings proactively
  4. Performance Benefits: 10-20x faster build times and reduced memory footprint are significant wins

🔍 Code Quality & Best Practices

config/webpack/commonWebpackConfig.js (Lines 73-116)

Issue: Hybrid SWC/Babel Approach

The implementation adds Babel back for JavaScript files while using SWC only for TypeScript. This is contrary to the PR's stated goal of migrating to SWC.

// Lines 76-86: SWC restricted to only TypeScript
swcRule.test = /\.(ts|tsx)(\.erb)?$/;

// Lines 89-112: Babel re-introduced for all JavaScript files
config.module.rules.push({
  test: /\.(js|jsx|mjs)(\.erb)?$/,
  // ... full Babel configuration
});

Concerns:

  1. Contradicts PR Description: The PR claims to migrate to SWC, but actually creates a hybrid setup
  2. Defeats Performance Goals: JavaScript files will still use Babel, negating much of the performance benefit
  3. Increased Complexity: Maintaining two transpilers increases maintenance burden
  4. Stimulus Compatibility: The comment mentions "SWC has compatibility issues with Stimulus" but:
    • This needs documentation/evidence
    • Should be tracked as a separate issue
    • Consider reporting to SWC/Stimulus projects

Recommendations:

  1. If Stimulus incompatibility is real, document it with specifics (error messages, issue links)
  2. Consider using SWC's keepClassNames: true option (already in swc.config.js) which may resolve Stimulus issues
  3. Test whether the Stimulus issue exists with current SWC settings
  4. If hybrid is necessary, update PR description to reflect this accurately
  5. Add inline comments explaining why each file type uses different transpilers

.eslintrc (Lines 8-12)

Issue: ESLint Still Configured for Babel

parserOptions:
  requireConfigFile: false
  babelOptions:
    presets:
      - "@babel/preset-react"

Concerns:

  1. ESLint is configured to parse with Babel's React preset, but code may be transpiled with SWC
  2. Parser/transpiler mismatch could cause linting issues that don't reflect actual build problems

Recommendations:

  1. Since Babel is still in use for JS files (per webpack config), this is actually correct
  2. However, if the goal is full SWC migration, consider using @typescript-eslint/parser instead
  3. Document the parser choice in comments

package.json (Lines 100-110, 133)

Dependencies Review:

Good:

  • SWC dependencies properly added: @swc/core, @swc/jest, swc-loader
  • Babel retained in devDependencies for ESLint compatibility
  • @babel/runtime kept for polyfills (correct decision)

⚠️ Concern:

  • babel-loader is in devDependencies (line 110) even though it's used in production webpack config
  • Should be moved to dependencies since it's used at runtime in commonWebpackConfig.js

🐛 Potential Bugs

1. Missing corejs Dependency

Location: config/webpack/commonWebpackConfig.js:99

useBuiltIns: 'entry',
corejs: 3,

Issue: corejs version 3 is specified but I don't see it in package.json dependencies

Recommendation: Add core-js: "^3.x" to dependencies or change to useBuiltIns: false

2. Babel Loader Configuration Hardcoding

Location: config/webpack/commonWebpackConfig.js:96-109

The Babel configuration is hardcoded in webpack config, duplicating what was previously in babel.config.js. This:

  • Makes updates harder (must edit webpack config instead of standard Babel config)
  • Loses the ability to use api.env() for environment-specific settings
  • Could cause inconsistencies with ESLint's babel parser

Recommendation: Extract to a shared babel.config.js or use environment variables


🔒 Security Concerns

No major security issues identified. The dependency changes appear safe:

  • Reputable packages (@swc/core is actively maintained by Vercel)
  • No known vulnerabilities in the new dependencies
  • Proper scoping of dev vs production dependencies (except babel-loader issue noted above)

Recommendation: Run npm audit or yarn audit to verify no vulnerabilities introduced


⚡ Performance Considerations

Positive:

  • SWC for TypeScript files will be significantly faster
  • Build times should improve for TS/TSX files

Concerns:

  1. Limited Performance Gain: Since JS files still use Babel, actual performance improvement may be much less than claimed 10-20x
  2. Two Transpiler Overhead: Running both SWC and Babel in the same build adds overhead
  3. No Benchmarks: PR description claims performance improvements but doesn't include before/after metrics

Recommendations:

  1. Add benchmark data showing actual build time improvements
  2. Profile builds to ensure both transpilers aren't creating bottlenecks
  3. Consider measuring:
    • Cold build time
    • Hot reload time
    • Production build time
    • Memory usage during builds

🧪 Test Coverage

Positive:

  • Jest properly updated to use @swc/jest
  • PR checklist indicates all tests pass

Concerns:

  1. No New Tests: No tests added to verify SWC transpilation works correctly
  2. Stimulus Not Tested: If Stimulus has compatibility issues, are there tests proving it works with Babel?

Recommendations:

  1. Add integration test verifying Stimulus controllers work correctly
  2. Consider adding a test that verifies SWC is actually being used for TS files
  3. Test both development and production builds

📋 Additional Recommendations

1. Documentation

Missing documentation about:

  • Why hybrid transpiler approach was chosen
  • Known Stimulus compatibility issues
  • Build performance benchmarks
  • Migration rollback procedure

Add to README.md or docs:

## Build Tooling
- TypeScript files: Transpiled with SWC
- JavaScript files: Transpiled with Babel (due to Stimulus compatibility)
- Tests: Use @swc/jest

2. Configuration File Location

config/swc.config.js appears to be created but may not be read by swc-loader. Verify the loader is picking up this config file or inline it in the webpack configuration.

3. Clean Up Old Babel Config

The deleted babel.config.js is good, but ensure no other files reference it:

grep -r "babel.config" . --exclude-dir=node_modules

🎯 Summary & Verdict

Overall Assessment: ⚠️ APPROVE WITH CHANGES

This PR makes good progress toward modernizing the build tooling, but the hybrid approach contradicts the stated migration goal and may reduce the performance benefits.

Required Changes:

  1. ✅ Move babel-loader to dependencies in package.json
  2. ✅ Add core-js to dependencies or remove corejs: 3 configuration
  3. ✅ Update PR description to accurately describe the hybrid SWC/Babel approach
  4. ✅ Document Stimulus compatibility issues with evidence

Recommended Changes:

  1. Test if SWC can handle Stimulus with current keepClassNames: true setting
  2. Add build performance benchmarks
  3. Extract Babel config from webpack to separate file
  4. Add integration tests for Stimulus functionality
  5. Update documentation about transpiler usage

Great work on tackling this migration! The attention to compatibility and the use of official migration tools shows good engineering judgment. With the recommended changes, this will be a solid improvement to the codebase.

🤖 Review generated with Claude Code

Copy link

github-actions bot commented Oct 4, 2025

🎉 ✨ Deploy Complete! 🚀

🌐 ➡️ Open Review App

Deployment successful for PR #669, commit 0444f60

🎮 Control Plane Console
📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 4, 2025

Pull Request Review: Migrate from Babel to SWC transpiler

Overall Assessment

This PR migrates JavaScript transpilation from Babel to SWC, which is a significant tooling change. While the migration approach using Shakapacker's official task is sound, there are critical architectural concerns that need to be addressed.


🚨 Critical Issues

1. Contradictory Configuration - Mixed Babel/SWC Setup

Location: config/webpack/commonWebpackConfig.js:86-109

The PR claims to migrate to SWC, but the webpack configuration adds Babel back for JavaScript files:

config.module.rules.splice(swcRuleIndex, 0, {
  test: /\.(js|jsx|mjs)(\.erb)?$/,
  include: swcRule.include,
  exclude: swcRule.exclude,
  use: {
    loader: 'babel-loader',
    options: {
      presets: [
        ['@babel/preset-env', {
          useBuiltIns: 'entry',
          corejs: 3,
          // ...
        }],
        ['@babel/preset-react', {
          runtime: 'automatic',
          // ...
        }]
      ]
    }
  }
});

Issues:

  • This defeats the entire purpose of the migration - you're still using Babel for all .js/.jsx files
  • SWC is only handling TypeScript files (.ts/.tsx)
  • The performance benefits mentioned (10-20x faster builds) will not be realized with this configuration
  • ESLint still requires @babel/preset-react (.eslintrc:12)
  • babel-loader is added as a dev dependency

Why was this done? The code comment says "This allows Babel to handle all JavaScript while SWC continues to match TypeScript" - but this contradicts the PR's stated goal.

Recommendation:

  • Either commit fully to SWC for both JS and TS, or clearly document why a hybrid approach is necessary
  • If ESLint compatibility is the issue, consider using @typescript-eslint/parser or other solutions
  • Update the PR description to accurately reflect that this is a hybrid Babel/SWC setup, not a full migration
  • Remove the misleading performance claims about 10-20x faster builds

2. Dependency Management Issues

Missing core-js dependency:

  • babel-loader config uses useBuiltIns: 'entry' with corejs: 3 (line 95-96)
  • core-js is not listed in package.json dependencies
  • This will cause runtime errors when the babel-loader tries to inject polyfills

Recommendation:

yarn add core-js@3

Babel dependencies kept as devDependencies:
Looking at package.json:100-104, these Babel packages are retained:

  • @babel/core
  • @babel/eslint-parser
  • @babel/preset-env
  • @babel/preset-react
  • babel-loader

This is actually correct given the hybrid setup, but contradicts the PR description claiming Babel was removed.


3. Test Configuration Mismatch

Location: package.json:155-156

Jest is configured to use @swc/jest:

"transform": {
  "^.+\\.jsx?$": "@swc/jest"
}

Issue: Tests will use SWC for transformation, but the actual application builds use Babel for JS files. This creates a testing/production parity problem:

  • Different transpilers may handle edge cases differently
  • Bugs could pass tests but fail in production (or vice versa)
  • Different optimization behaviors

Recommendation:

  • Use babel-jest if you're keeping Babel for the main build
  • Or ensure SWC handles everything consistently

⚠️ Major Concerns

4. Incomplete SWC Configuration

Location: config/swc.config.js

The SWC config is minimal:

module.exports = {
  jsc: {
    transform: {
      react: {
        runtime: "automatic"
      }
    },
    keepClassNames: true
  }
};

Missing critical settings:

  • No target specified (ES2015? ES2020? ESNext?)
  • No parser configuration (ecmaVersion, jsx, decorators, etc.)
  • No minify settings for production
  • No source map configuration
  • No loose mode options that might be needed for compatibility

Compare this to the Babel config that was removed - it had much more comprehensive configuration.

Recommendation:

  • Add explicit target environment configuration
  • Configure parser options to match your needs
  • Add production optimizations
  • Consider documenting why keepClassNames: true is needed (the comment mentions Stimulus compatibility)

5. Package Lock File Concerns

Issue: The PR adds package-lock.json with 17,995 new lines while also having yarn.lock.

Problems:

  • Having both package-lock.json and yarn.lock is an anti-pattern
  • The package.json specifies "packageManager": "yarn@1.22.22" and "engines": {"yarn": "1.22"}
  • This suggests the project uses Yarn, not npm
  • package-lock.json should not exist in a Yarn project

Recommendation:

rm package-lock.json
git add package-lock.json

💡 Code Quality Issues

6. ESLint Configuration Redundancy

Location: .eslintrc:8-12

parserOptions:
  requireConfigFile: false
  babelOptions:
    presets:
      - "@babel/preset-react"

Issues:

  • This hardcodes Babel presets in ESLint config
  • Creates tight coupling between linting and build configuration
  • If you truly migrated to SWC, you shouldn't need babelOptions in ESLint

Recommendation:

  • Consider switching to @typescript-eslint/parser which doesn't require Babel
  • Or use espree (default ESLint parser) which handles modern JS without Babel

7. ReScript Changes Unrelated to Migration

Location: client/app/bundles/comments/rescript/CommentForm/CommentForm.res:107

-onClick={event => SetFormType(form.formType)->dispatch}>
+onClick={_event => SetFormType(form.formType)->dispatch}>

Issue: This change (prefixing unused variable with _) is good practice but unrelated to Babel→SWC migration.

Recommendation:

  • Fine to include, but mention in PR description that this fixes a compiler warning
  • The PR does mention this in "Additional Fixes" ✅

8. Security: Dependency Versions

Concerns:

  • axios: "^0.21.1" - This is quite old (2020) and has known vulnerabilities. Latest is 1.x
  • loader-utils: "^1.1.0" - Has critical prototype pollution vulnerability (CVE-2022-37601)
  • jquery: "^3.2.1" - From 2017, multiple security updates since then

Recommendation:

  • Update these dependencies in a separate PR
  • Run yarn audit and address critical vulnerabilities

✅ Positive Aspects

  1. Used official migration tool - Good decision to use rails shakapacker:migrate_to_swc
  2. Comprehensive PR description - Well documented with test plan
  3. ReScript modernization - Fixed deprecation (es6esmodule)
  4. Test coverage verified - PR mentions all tests pass
  5. Clean commits - Appears to be a focused change

📊 Performance Concerns

Expected vs Actual Performance Improvement

The PR claims:

Performance: 10-20x faster build times for large codebases

Reality: With the current hybrid setup where Babel still handles all JS/JSX files:

  • Performance improvement will be minimal for this project
  • Only TypeScript files (if any) get SWC's speed benefits
  • Most of the codebase appears to be .js/.jsx based on the structure

Recommendation:

  • Benchmark actual build times before/after this change
  • Either fix the configuration to use SWC for everything, or adjust performance expectations

🔧 Recommendations Summary

Must Fix (Blocking):

  1. Resolve the architectural contradiction - Decide on full SWC migration vs hybrid approach
  2. Add missing core-js dependency or remove useBuiltIns: 'entry'
  3. Remove package-lock.json - This is a Yarn project
  4. Align test and build transpilers - Both should use the same tool

Should Fix (High Priority):

  1. ⚠️ Expand SWC configuration - Add target, parser options, minification settings
  2. ⚠️ Update PR description - Accurately describe the hybrid approach
  3. ⚠️ Document the rationale - Why is Babel still needed for JS files?

Nice to Have:

  1. 💡 Consider modernizing ESLint parser
  2. 💡 Plan security dependency updates
  3. 💡 Add actual build time benchmarks

Final Verdict

Status: ⚠️ Needs Major Revisions

This PR has good intentions and uses the official migration path, but the implementation has significant issues:

  • The hybrid Babel/SWC setup contradicts the migration goal
  • Missing dependencies will cause build failures
  • Test/production parity issues
  • Misleading performance claims

Recommendation: Request changes to clarify the architecture and fix the critical issues before merging.


Review generated with assistance from Claude Code

Copy link

github-actions bot commented Oct 5, 2025

🎉 ✨ Deploy Complete! 🚀

🌐 ➡️ Open Review App

Deployment successful for PR #669, commit 543f1a6

🎮 Control Plane Console
📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 5, 2025

Code Review: Migrate from Babel to SWC transpiler

Overview

This PR migrates the project from Babel to SWC for JavaScript transpilation, which is a significant tooling change. The migration appears well-executed and follows Shakapacker's official migration path. Overall, this is a solid migration with some notable concerns that should be addressed.


✅ Strengths

  1. Official Migration Approach: Using rails shakapacker:migrate_to_swc ensures alignment with Shakapacker best practices
  2. Clear Documentation: Excellent PR description with rationale, test plan, and clear documentation of changes
  3. Thorough Testing: All test suites verified (build, dev, ESLint, RuboCop)
  4. Clean Dependency Management: Properly removed Babel dependencies while retaining @babel/runtime for polyfills
  5. Additional Improvements: Fixed ReScript deprecation warnings proactively

⚠️ Major Concerns

1. Hybrid Babel/SWC Configuration (Critical)

Location: config/webpack/commonWebpackConfig.js:73-113

The most significant issue is the dual transpiler setup where Babel is re-introduced to handle .js files while SWC handles TypeScript:

// Insert Babel rule BEFORE SWC rule so it matches .js files first
config.module.rules.splice(swcRuleIndex, 0, {
  test: /\.(js|jsx|mjs)(\.erb)?$/,
  // ... babel-loader configuration
});

Issues:

  • Defeats the purpose of migrating to SWC - you lose the 10-20x performance gains for JavaScript files
  • Increases complexity - maintaining two transpilers is harder than one
  • Larger bundle - both babel-loader and swc-loader in production
  • No explanation - PR description claims migration to SWC but doesn't mention this hybrid approach
  • Duplicate configuration - Babel config in webpack + SWC config file

Recommendation:

  • If SWC can handle both JS and TS (which it can), use SWC exclusively
  • If there's a specific Babel transform needed, document why and consider SWC alternatives
  • Remove the hybrid approach or clearly document why it's necessary

2. Babel Still in devDependencies

Location: package.json:101-110

"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@babel/preset-react": "^7.18.6",
"babel-loader": "^10.0.0",

These Babel packages are now in devDependencies instead of dependencies, but:

  • ❌ They're actively used by the webpack config (see concern Need to add Capybara Feature tests #1)
  • ❌ Should be in dependencies if they're required for builds
  • ⚠️ ESLint still requires @babel/preset-react (.eslintrc:8-12)

Recommendation:

  • If keeping the hybrid approach, move Babel deps back to dependencies
  • If removing hybrid approach, keep only @babel/core and @babel/preset-react for ESLint

3. ESLint Babel Dependency

Location: .eslintrc:8-12

parserOptions:
  requireConfigFile: false
  babelOptions:
    presets:
      - "@babel/preset-react"
  • ⚠️ ESLint still depends on Babel for parsing
  • This is acceptable but means Babel isn't fully eliminated
  • Consider using @typescript-eslint/parser if TypeScript is widely used

🔍 Code Quality & Best Practices

Positive

  1. Clean SWC Config: Simple and appropriate (config/swc.config.js:1-11)

    • ✅ React automatic runtime
    • ✅ Preserves class names for Stimulus compatibility
  2. Jest Configuration: Properly updated to use @swc/jest (package.json:155-157)

  3. ReScript Fixes:

    • Fixed deprecation: es6esmodule (bsconfig.json:11)
    • Fixed unused variable warning (CommentForm.res:107)

Areas for Improvement

  1. Documentation Gap: No inline comment explaining why Babel is re-introduced in webpack config
  2. Testing: Consider adding performance benchmarks to verify speed improvements
  3. .swcrc vs swc.config.js: PR mentions .swcrc but implements swc.config.js (minor inconsistency)

🐛 Potential Bugs

No critical bugs identified, but:

  1. Rule Ordering Risk: Inserting Babel rule via splice is fragile - if Shakapacker changes rule order, this could break
  2. RegEx Match: /\.(ts|tsx|js|jsx|mjs|coffee)/.test(rule.test.toString()) assumes test is a RegExp - could fail if string

Recommendation: Add null checks and error handling:

if (swcRuleIndex !== -1 && config.module.rules[swcRuleIndex]) {
  // ... existing code
} else {
  console.warn('SWC rule not found - skipping Babel injection');
}

🔒 Security Considerations

No security concerns identified

  • Dependency versions are reasonable and recent
  • No introduction of vulnerable packages
  • Build process remains secure

⚡ Performance Considerations

  1. Mixed Performance Profile:

    • ✅ TypeScript files will build faster with SWC
    • ❌ JavaScript files still use Babel (slower)
    • ❓ What percentage of the codebase is JS vs TS?
  2. Bundle Size: Running both transpilers adds weight to node_modules

  3. Memory: Two transpilers = higher memory usage during builds

Recommendation: Measure actual build times before/after to validate performance claims


🧪 Test Coverage

Good test plan execution:

  • Build passes
  • Development build passes
  • Linters pass
  • Functionality verified

⚠️ Missing:

  • No automated tests for build configuration itself
  • No performance benchmarks included
  • Jest tests not shown running in PR (only mentioned in description)

Recommendation: Add output of yarn test:client to PR description


📋 Recommendations Summary

Must Fix (Before Merge)

  1. Clarify transpiler strategy: Either commit fully to SWC or document why hybrid is necessary
  2. Fix dependency placement: Move actively-used Babel deps to dependencies or remove them
  3. Add error handling: Protect against webpack config changes breaking the Babel injection

Should Fix

  1. Document performance gains: Add before/after build time metrics
  2. Add webpack config comments: Explain the hybrid transpiler setup
  3. Run full test suite: Include Jest output in PR

Nice to Have

  1. Consider TypeScript ESLint parser: Further reduce Babel dependency
  2. SWC plugin exploration: Check if any Babel plugins can be replaced with SWC equivalents
  3. Webpack config refactor: Extract transpiler setup to separate function for clarity

📊 Final Assessment

Approve with changes requested

The migration is well-intentioned and follows good practices, but the hybrid Babel/SWC approach undermines the stated goals of the PR. This needs clarification and likely revision before merge.

If the hybrid approach is intentional, it should be:

  • Clearly documented in the PR description
  • Explained with comments in the code
  • Measured for actual performance impact

If it's unintentional, remove the Babel reintroduction and use SWC for all transpilation.


Great work on the migration overall! The attention to detail (ReScript fixes, dependency cleanup) shows care. Just need to resolve the transpiler strategy. 🚀

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
config/webpack/commonWebpackConfig.js (1)

6-6: Unused import: path module.

The path module is imported but not used in this file. Consider removing it unless it's planned for future use.

Apply this diff to remove the unused import:

-const path = require('path');
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd5ff7e and 543f1a6.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • config/swc.config.js (1 hunks)
  • config/webpack/commonWebpackConfig.js (2 hunks)
  • package.json (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
config/webpack/commonWebpackConfig.js (2)
config/webpack/serverWebpackConfig.js (2)
  • require (5-5)
  • commonWebpackConfig (6-6)
config/webpack/clientWebpackConfig.js (1)
  • commonWebpackConfig (5-5)
⏰ 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: test (22.x, 3.4.6)
  • GitHub Check: deploy
  • GitHub Check: claude-review
🔇 Additional comments (4)
config/swc.config.js (1)

1-11: LGTM! Minimal SWC configuration is appropriate.

The configuration correctly sets React's automatic runtime and preserves class names for Stimulus compatibility. This minimal config is suitable since JavaScript transpilation is now handled by Babel (per commonWebpackConfig.js).

Note: The past review comment about env.mode: 'entry' is no longer relevant as that configuration has been removed from this file.

package.json (2)

101-110: Dependency structure supports hybrid Babel+SWC approach.

The Babel packages (@babel/core, presets, babel-loader) moved to devDependencies alongside SWC packages (@swc/core, swc-loader). This aligns with the webpack configuration that uses Babel for JavaScript and SWC for TypeScript.

However, note that the PR description indicates a migration "from Babel to SWC," but the implementation maintains Babel for JavaScript transpilation. Consider clarifying in the PR description that this is a hybrid approach rather than a complete Babel removal.


156-156: LGTM! Jest correctly configured to use SWC.

The Jest transformer updated to use @swc/jest for JavaScript/JSX files, which aligns with the migration goals for test transpilation.

config/webpack/commonWebpackConfig.js (1)

84-85: Clarify the hybrid Babel+SWC architecture.

The comment states "This allows Babel to handle all JavaScript while SWC continues to match TypeScript," but this hybrid approach wasn't clearly described in the PR objectives, which indicate a migration "from Babel to SWC."

Consider updating the PR description to clarify that:

  1. This is a hybrid approach, not a complete Babel removal
  2. Babel handles JavaScript (.js, .jsx, .mjs)
  3. SWC handles TypeScript (.ts, .tsx)
  4. The rationale for maintaining Babel for JavaScript

Comment on lines 73 to 113
const commonWebpackConfig = () => {
const config = merge({}, baseClientWebpackConfig, commonOptions, ignoreWarningsConfig);

// Find the SWC rule and get its include/exclude
const swcRuleIndex = config.module.rules.findIndex(rule =>
rule.test && /\.(ts|tsx|js|jsx|mjs|coffee)/.test(rule.test.toString())
);

if (swcRuleIndex !== -1) {
const swcRule = config.module.rules[swcRuleIndex];

// Insert Babel rule BEFORE SWC rule so it matches .js files first
// This allows Babel to handle all JavaScript while SWC continues to match TypeScript
config.module.rules.splice(swcRuleIndex, 0, {
test: /\.(js|jsx|mjs)(\.erb)?$/,
include: swcRule.include,
exclude: swcRule.exclude,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
useBuiltIns: 'entry',
corejs: 3,
modules: 'auto',
bugfixes: true,
exclude: ['transform-typeof-symbol']
}],
['@babel/preset-react', {
runtime: 'automatic',
development: process.env.NODE_ENV !== 'production',
useBuiltIns: true
}]
]
}
}
});
}

return config;
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Critical: Babel's useBuiltIns: 'entry' requires explicit core-js imports.

The Babel loader is configured with useBuiltIns: 'entry' (line 95), which requires explicit import 'core-js/stable' and import 'regenerator-runtime/runtime' in each entry file. Without these imports, polyfills won't be included, potentially causing runtime errors in older browsers.

Additionally, this implementation maintains Babel for JavaScript transpilation, creating a hybrid Babel+SWC setup (Babel for .js/.jsx, SWC for .ts/.tsx) rather than a complete migration to SWC as suggested by the PR description.

Option 1 (Recommended): Change to useBuiltIns: 'usage' to let Babel automatically inject only the required polyfills:

           ['@babel/preset-env', {
-            useBuiltIns: 'entry',
+            useBuiltIns: 'usage',
             corejs: 3,

Option 2: Keep useBuiltIns: 'entry' and add core-js imports to all entry files (e.g., files in client/app/packs/).

Run the following script to verify if core-js imports exist in entry files:


🏁 Script executed:

#!/bin/bash
# Description: Check for core-js imports in entry files

echo "=== Checking for core-js imports in entry files ==="
fd -e js -e jsx . client/app/packs/ --exec rg -l "import.*['\"]core-js" {} \; || echo "No core-js imports found"

echo ""
echo "=== Checking for regenerator-runtime imports ==="
fd -e js -e jsx . client/app/packs/ --exec rg -l "import.*['\"]regenerator-runtime" {} \; || echo "No regenerator-runtime imports found"

echo ""
echo "=== Entry files in packs directory ==="
fd -e js -e jsx . client/app/packs/

Length of output: 313


Switch Babel preset-env to useBuiltIns: 'usage' or add core-js imports
No core-js or regenerator-runtime imports were found in client/app/packs/*; with useBuiltIns: 'entry', polyfills won’t be included. Prefer:

['@babel/preset-env', {
-  useBuiltIns: 'entry',
+  useBuiltIns: 'usage',
   corejs: 3,
}]

Alternatively, keep entry and add import 'core-js/stable' and import 'regenerator-runtime/runtime' to each entry file.

📝 Committable suggestion

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

Suggested change
const commonWebpackConfig = () => {
const config = merge({}, baseClientWebpackConfig, commonOptions, ignoreWarningsConfig);
// Find the SWC rule and get its include/exclude
const swcRuleIndex = config.module.rules.findIndex(rule =>
rule.test && /\.(ts|tsx|js|jsx|mjs|coffee)/.test(rule.test.toString())
);
if (swcRuleIndex !== -1) {
const swcRule = config.module.rules[swcRuleIndex];
// Insert Babel rule BEFORE SWC rule so it matches .js files first
// This allows Babel to handle all JavaScript while SWC continues to match TypeScript
config.module.rules.splice(swcRuleIndex, 0, {
test: /\.(js|jsx|mjs)(\.erb)?$/,
include: swcRule.include,
exclude: swcRule.exclude,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
useBuiltIns: 'entry',
corejs: 3,
modules: 'auto',
bugfixes: true,
exclude: ['transform-typeof-symbol']
}],
['@babel/preset-react', {
runtime: 'automatic',
development: process.env.NODE_ENV !== 'production',
useBuiltIns: true
}]
]
}
}
});
}
return config;
};
const commonWebpackConfig = () => {
const config = merge({}, baseClientWebpackConfig, commonOptions, ignoreWarningsConfig);
// Find the SWC rule and get its include/exclude
const swcRuleIndex = config.module.rules.findIndex(rule =>
rule.test && /\.(ts|tsx|js|jsx|mjs|coffee)/.test(rule.test.toString())
);
if (swcRuleIndex !== -1) {
const swcRule = config.module.rules[swcRuleIndex];
// Insert Babel rule BEFORE SWC rule so it matches .js files first
// This allows Babel to handle all JavaScript while SWC continues to match TypeScript
config.module.rules.splice(swcRuleIndex, 0, {
test: /\.(js|jsx|mjs)(\.erb)?$/,
include: swcRule.include,
exclude: swcRule.exclude,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: 3,
modules: 'auto',
bugfixes: true,
exclude: ['transform-typeof-symbol']
}],
['@babel/preset-react', {
runtime: 'automatic',
development: process.env.NODE_ENV !== 'production',
useBuiltIns: true
}]
]
}
}
});
}
return config;
};
🤖 Prompt for AI Agents
In config/webpack/commonWebpackConfig.js around lines 73 to 113: the Babel
preset-env is configured with useBuiltIns: 'entry' but there are no
core-js/regenerator imports in client entry files, so polyfills are not being
injected; either change the preset-env option to useBuiltIns: 'usage' so Babel
injects polyfills where needed, or keep 'entry' and add import 'core-js/stable'
and import 'regenerator-runtime/runtime' to each client entry file (or a shared
bootstrap entry) so the required polyfills are bundled.

Copy link

github-actions bot commented Oct 5, 2025

🎉 ✨ Deploy Complete! 🚀

🌐 ➡️ Open Review App

Deployment successful for PR #669, commit 74d89c1

🎮 Control Plane Console
📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 5, 2025

PR Review: Migrate from Babel to SWC transpiler

Thank you for working on this migration! I've conducted a thorough review and identified several critical issues that need to be addressed before merging.


🔴 Critical Issues

1. Contradictory Architecture - Defeating the Purpose of Migration

The most significant issue is in config/webpack/commonWebpackConfig.js:84-109. This PR claims to migrate to SWC for performance benefits, but then adds Babel back to handle all JavaScript files:

// Insert Babel rule BEFORE SWC rule so it matches .js files first
// This allows Babel to handle all JavaScript while SWC continues to match TypeScript
config.module.rules.splice(swcRuleIndex, 0, {
  test: /\.(js|jsx|mjs)(\.erb)?$/,
  include: swcRule.include,
  exclude: swcRule.exclude,
  use: {
    loader: 'babel-loader',
    // ... babel configuration
  }
});

Problems:

  • The comment explicitly states "Babel to handle all JavaScript while SWC continues to match TypeScript"
  • This defeats the entire purpose of the migration since most of the codebase appears to be JavaScript/JSX, not TypeScript
  • You're not getting the 10-20x performance improvement mentioned in the PR description
  • This creates unnecessary complexity with two transpilers in the same build pipeline
  • The PR title says "Migrate from Babel to SWC" but you're actually running both

Impact: The claimed performance benefits are likely not being realized since Babel is still transpiling the majority of files.


2. Missing SWC Configuration File

The PR adds config/swc.config.js but I don't see it being referenced in the webpack configuration. SWC needs to be explicitly told to use this config file:

// In webpack config, you'd typically see:
{
  loader: 'swc-loader',
  options: require('../swc.config.js')
}

Without this reference, your SWC configuration (including the important keepClassNames: true for Stimulus compatibility) may not be applied.


3. Dependency Inconsistency

In package.json:

  • Babel dependencies are in devDependencies (lines 101-104, 110)
  • But babel-loader is actively used in production webpack config (config/webpack/commonWebpackConfig.js:91)

Issue: If someone runs npm install --production, babel-loader won't be installed, breaking production builds.

Recommendation: Either move these to dependencies or (better) remove them entirely if truly migrating to SWC.


4. ESLint Still Requires Babel

In .eslintrc:8-12:

parserOptions:
  requireConfigFile: false
  babelOptions:
    presets:
      - "@babel/preset-react"

This configuration requires @babel/preset-react to be installed and working. While this is acceptable for a dev tool, it creates confusion about whether Babel is truly removed from the project.

Consideration: Consider using @typescript-eslint/parser or ensuring this Babel requirement is documented.


⚠️ Major Concerns

5. No CoreJS Reference in SWC Config

The Babel configuration includes corejs: 3 for polyfills (line 96), but there's no equivalent in the SWC configuration. SWC handles polyfills differently and may not provide the same browser compatibility without proper configuration.

Recommendation: Verify that your target browser support (defined in browserslist) is maintained with SWC.


6. Missing React Refresh for SWC

The project uses @pmmmwh/react-refresh-webpack-plugin which typically works with Babel's react-refresh/babel plugin. The deleted babel.config.js had:

process.env.WEBPACK_SERVE && 'react-refresh/babel'

But I don't see the equivalent SWC React Refresh configuration. You may need swc-loader with { refresh: true } in development mode.

Impact: Hot Module Replacement (HMR) with React may be broken in development.


7. Test Coverage Verification

The PR description mentions tests pass, but:

  • Are there integration tests that verify the build output works correctly in all environments?
  • Have you tested HMR/Fast Refresh in development mode?
  • Have you verified production builds generate the same output?

Recommendation: Document what specific test scenarios were validated beyond unit tests.


📋 Minor Issues & Suggestions

8. Unused ReScript Fixes

The changes to bsconfig.json and CommentForm.res are good fixes but appear unrelated to the Babel→SWC migration. Consider moving these to a separate PR for cleaner history.


9. Missing Migration Documentation

For a migration this significant, consider adding:

  • Migration notes in CHANGELOG.md
  • Documentation about why certain files still use Babel
  • Rollback instructions if issues are found

🎯 Recommendations

Short-term (Required before merge):

  1. Decide on a consistent approach:

    • Option A (True SWC Migration): Remove the Babel webpack rule entirely, ensure SWC handles all JS/JSX/TS/TSX files
    • Option B (Hybrid Approach): Document why both are needed and update PR description to reflect that this is a "hybrid" approach, not a full migration
  2. Fix dependency placement: Move build-time dependencies to the correct section in package.json

  3. Verify React Refresh: Ensure HMR works in development mode

  4. Reference SWC config: Ensure config/swc.config.js is actually being used

Long-term:

  • Consider adding E2E tests for build verification
  • Document the build toolchain architecture
  • Add performance benchmarks to verify the claimed improvements

📊 Overall Assessment

While the intent of this PR is excellent (modernizing the build toolchain), the current implementation has critical architectural issues that prevent it from achieving its stated goals. The most significant problem is maintaining Babel for JavaScript files while claiming to migrate to SWC.

Recommendation: Request changes - This PR needs significant rework before it can be merged safely.

Please address the critical issues, particularly the dual-transpiler setup, before proceeding. Happy to review again once these are resolved!


Generated with Claude Code - Code Review Assistant

@justin808 justin808 force-pushed the justin808/migrate-to-swc branch from 74d89c1 to 4332a54 Compare October 5, 2025 22:37
@justin808 justin808 changed the title Migrate from Babel to SWC transpiler Fix ReScript deprecation warnings Oct 5, 2025
Copy link

github-actions bot commented Oct 5, 2025

🎉 ✨ Deploy Complete! 🚀

🌐 ➡️ Open Review App

Deployment successful for PR #669, commit 4332a54

🎮 Control Plane Console
📋 View Completed Action Build and Deploy Logs

Copy link

claude bot commented Oct 5, 2025

Pull Request Review

Summary

This PR addresses ReScript deprecation warnings by updating configuration and removing an unused event parameter. The changes are minimal, focused, and appropriate.

✅ Code Quality & Best Practices

Excellent:

  • Clear intent: Both changes directly address deprecation warnings
  • Minimal scope: Only touches what is necessary
  • Consistent naming: Using _event prefix follows ReScript conventions for explicitly unused parameters
  • Configuration update: The es6 → esmodule change aligns with ReScript modern module system

✅ Correctness

Both changes are technically sound:

  1. bsconfig.json: The module type esmodule is the current ReScript standard (previously es6 was an alias, now deprecated)
  2. CommentForm.res:107: The event parameter was never used in the onClick handler, so prefixing with _ correctly signals this to the compiler

✅ Security & Performance

No concerns:

  • No security implications
  • No performance impact (purely cosmetic/warning fixes)
  • No behavior changes

📝 Observations

Good:

  • The onClick handler only needs to dispatch an action, so the event parameter is genuinely unused
  • The change maintains the same functionality while eliminating compiler warnings

Minor note:

  • No test coverage changes needed since behavior is identical
  • Consider documenting the ReScript version requirements if this deprecation indicates a minimum version bump

Recommendation

✅ Approve - This is a clean, straightforward fix for deprecation warnings with no negative side effects.


Review generated with assistance from Claude Code

@justin808 justin808 merged commit 577e4b5 into master Oct 5, 2025
6 checks passed
@justin808 justin808 deleted the justin808/migrate-to-swc branch October 5, 2025 22:53
@justin808 justin808 restored the justin808/migrate-to-swc branch October 5, 2025 22:53
Copy link

github-actions bot commented Oct 5, 2025

✅ Review app for PR #669 was successfully deleted

View Completed Delete Logs

Control Plane Organization

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant