Skip to content

Pro RSC migration 1/3: Swap gem and npm to react_on_rails_pro#726

Merged
ihabadham merged 2 commits intoihabadham/feature/pro-rsc/basefrom
ihabadham/feature/pro-rsc/gem-swap
Apr 20, 2026
Merged

Pro RSC migration 1/3: Swap gem and npm to react_on_rails_pro#726
ihabadham merged 2 commits intoihabadham/feature/pro-rsc/basefrom
ihabadham/feature/pro-rsc/gem-swap

Conversation

@ihabadham
Copy link
Copy Markdown
Collaborator

@ihabadham ihabadham commented Apr 20, 2026

Summary

Part 1 of a stacked-PR series migrating this tutorial to React on Rails Pro so React Server Components can be demoed here (enable_rsc_support is Pro-only). Pure dependency swap — no functional change. ExecJS server rendering is still used; no Pro runtime features enabled yet.

  • Gemfile: react_on_rails 16.6.0.rc.0react_on_rails_pro 16.6.0
  • package.json: react-on-rails 16.6.0-rc.0react-on-rails-pro 16.6.0
  • shakapacker: 10.0.0.rc.010.0.0 stable (lockstep with the Pro gem)
  • First-party imports rewritten: 'react-on-rails''react-on-rails-pro' across 10 files (matches react_on_rails :pro generator's update_imports_to_pro_package step)
  • config/webpack/commonWebpackConfig.js: narrow alias react-on-rails$react-on-rails-pro to shim the one third-party package still importing the core specifier (rescript-react-on-rails). Prevents the runtime "Cannot mix react-on-rails (core) with react-on-rails-pro" error.

Supersedes PR #723

PR #723 bundled the full migration (gem swap + NodeRenderer + RSC demo + a custom Rspack RSC plugin) in a single branch. This stacked series splits that work into focused sub-PRs and realigns several choices with the canonical Pro references (react_on_rails_pro/spec/dummy, marketplace demo). Branch ihabadham/feature/pro-rsc/base is the integration branch; sub-PRs target it, and it'll merge to master as one atomic unit once all three land.

Stack context

Targets ihabadham/feature/pro-rsc/base, not master. The base PR against master will open as Draft (with [DO NOT MERGE] title prefix) once this sub-PR merges and gives it a non-empty diff. Planned follow-ups:

  • Sub-PR 2: Switch SSR to NodeRenderer via webpack (target: 'node', node: false, upstream RSCWebpackPlugin on the server bundle, create_pro_initializer with NodeRenderer fields, renderer/node-renderer.js launcher, Procfile.dev entry, webpack transforms from the :pro generator's update_webpack_config_for_pro). This is where the production license story becomes load-bearing and gets handled (.env.example, CI secret).
  • Sub-PR 3: Add the RSC demo page on webpack (upstream RSCWebpackPlugin, rscWebpackConfig.js derived from serverWebpackConfig(true), initializer RSC fields, server components page + routes, 'use client' directives). No custom plugin, no separate rsc-bundle.js source, no manual rsc-client-components.js side-import — all of that is replaced by the upstream plugin's clientReferences option.
  • Post-merge follow-up: flip shakapacker.yml back to rspack once shakacode/react_on_rails_rsc#29 ships RSCRspackPlugin in a release. The manifest contract is shared between the two plugins, so it'll be a small diff.

Test plan

  • CI green
  • bundle install resolves react_on_rails_pro 16.6.0; react_on_rails 16.6.0 pulled in as transitive
  • yarn install resolves; one expected rescript-react-on-rails peer-dep warning (handled by the narrowed webpack alias)
  • bundle exec rake shakapacker:compile — clean build, 3 benign size warnings (pre-existing)
  • bin/rails s boots clean; dev log shows [React on Rails Pro] No license found. No license required for development/test environments.
  • GET / returns HTTP 200
  • No "Cannot mix react-on-rails (core) with react-on-rails-pro" error

🤖 Generated with Claude Code

First of three stacked sub-PRs enabling React Server Components here,
since enable_rsc_support is a Pro-only configuration. Pure dependency
swap — ExecJS server rendering and existing behavior are unchanged.

- Gemfile: react_on_rails 16.6.0.rc.0 → react_on_rails_pro 16.6.0
- package.json: react-on-rails 16.6.0-rc.0 → react-on-rails-pro 16.6.0
- shakapacker: rc.0 → 10.0.0 stable (lockstep with the Pro gem pair)
- commonWebpackConfig.js: alias react-on-rails → react-on-rails-pro so
  third-party packages still importing 'react-on-rails' (such as
  rescript-react-on-rails) resolve to Pro. Prevents the runtime error
  "Cannot mix react-on-rails (core) with react-on-rails-pro".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 35c2b359-04b9-42b5-addb-a92788274419

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ihabadham/feature/pro-rsc/gem-swap

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.

@github-actions
Copy link
Copy Markdown

🚀 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.


@claude
Copy link
Copy Markdown

claude Bot commented Apr 20, 2026

Code Review: Pro RSC Migration 1/3 — Gem/NPM Swap

Overview

Clean, well-scoped dependency swap: RC versions out, stable Pro versions in. The stacked-PR strategy is well-explained and the scope is appropriately limited to just the package swap. No functional behavior changes are claimed, which matches the diff.


What's Good

  • RC → stable upgrades for both shakapacker and react-on-rails(-pro) — right move before building on top
  • Webpack alias approach is the correct fix for the "Cannot mix" dual-singleton error
  • The $ suffix in react-on-rails$ correctly limits the first alias to exact-match only
  • Clear PR description with an explicit test plan and stack context

Issues

Webpack alias coverage gap

The alias only covers two import paths:

'react-on-rails$': 'react-on-rails-pro',
'react-on-rails/node_package': 'react-on-rails-pro/node_package',

If rescript-react-on-rails (or any third-party package) imports from other sub-paths of react-on-rails (e.g. react-on-rails/node_package/libs/ReactOnRails, react-on-rails/server, etc.), those bypass the alias and pull in the core package, triggering the same mixing error at runtime.

A single alias without the $ is the idiomatic webpack way to redirect all sub-paths and makes the second entry redundant:

alias: {
  'react-on-rails': 'react-on-rails-pro',  // catches exact import AND any sub-paths
},

The only risk would be if react-on-rails-pro is missing a sub-path that core exposes, but since Pro ships core as a peer dep with the same package structure, this should be safe.

First-party code still imports react-on-rails

Application bundle code contains import ReactOnRails from 'react-on-rails'. This works via the alias, but first-party code should import directly from react-on-rails-pro to make the dependency explicit and avoid confusion. The alias is meant as a shim for third-party packages you don't control.

Production license handling not addressed

The dev log shows No license required for development/test environments. but production deployments (and any CI stage running in production mode) need REACT_ON_RAILS_PRO_LICENSE set. There's no mention of how this is handled for the tutorial's deployment environment. Even a note or a placeholder in .env.example would help users following this tutorial.


Minor Notes

  • New Gemfile transitive deps (async, httpx, http-2, jwt): Unused in this PR but they land in the dependency tree now. Expected for future NodeRenderer support, but worth including in a security-review checklist pass, especially jwt and httpx.
  • pack-config-diff@^0.1.0 is a new transitive dep via shakapacker 10.0.0 stable that wasn't in rc.0 — entirely benign, just wasn't there before.
  • CI check is still pending in the test plan; the rest of the review assumes it passes.

Overall, solid groundwork for the RSC migration. Main things to address before merge: simplify the webpack alias (drop the $ + second entry) and document/resolve the production license story.

Comment thread config/webpack/commonWebpackConfig.js
The previous commit aliased all 'react-on-rails' imports to
'react-on-rails-pro' at bundle time. That worked but left two things
sloppy:

1. First-party code still read as if it depended on the core package,
   hiding the real Pro dependency behind a webpack alias. Anyone reading
   the source couldn't tell we were on Pro.
2. The alias had a '/node_package' sub-path entry that was legacy —
   neither package actually ships a node_package/ folder, and nothing
   imports that path anywhere in the tree.

Rewriting first-party imports to 'react-on-rails-pro' directly matches
the react_on_rails :pro generator's update_imports_to_pro_package step
and makes the dependency legible. The webpack alias is now narrowed to
its real job: shimming rescript-react-on-rails (the one third-party
package still importing 'react-on-rails'), and only for exact-specifier
imports — Pro's package exports don't mirror core's sub-path surface,
so a prefix alias could break resolution for OSS-only sub-paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@claude
Copy link
Copy Markdown

claude Bot commented Apr 20, 2026

Code Review: Pro RSC Migration 1/3 — Dependency Swap

Overall: Clean, well-scoped PR. The changes are consistent, the lockfiles are properly updated, and the webpack alias approach is the right solution for the third-party compat problem. A few things worth flagging before this lands.


✅ What's done well

  • Every first-party react-on-rails import has been migrated to react-on-rails-pro — verified no missed imports remain.
  • RC → stable promotions for both shakapacker and react_on_rails_pro is the right move before the RSC work builds on top.
  • The webpack alias with $ is the idiomatic way to handle this kind of package shim; the comment explains the rationale clearly.
  • Lockfiles (Gemfile.lock, yarn.lock) are fully in sync with the manifest changes.

⚠️ Issues to address

1. Webpack alias doesn't cover sub-path imports

The 'react-on-rails$': 'react-on-rails-pro' alias redirects only exact-string imports of 'react-on-rails'. Any third-party package that imports a sub-path — e.g. 'react-on-rails/server' or 'react-on-rails/client' — bypasses the alias entirely and resolves to the core package, which would still trigger the "Cannot mix react-on-rails (core) with react-on-rails-pro" runtime error.

This is safe today since rescript-react-on-rails only imports the root specifier, but it's a silent footgun as deps evolve. Consider also aliasing the common sub-paths or documenting the known-safe assumption explicitly.

2. No production license key setup

The dev log shows No license found. No license required for development/test environments. — Pro silently succeeds in dev/test without a key but will fail (or degrade) in production. There's no env var, initializer, or README note here covering how to set REACT_ON_RAILS_PRO_LICENSE. Deployment will fail or behave unexpectedly without it. Please add at minimum a .env.example entry or a note in the README before this reaches a production environment.

3. Heavy transitive dependencies loaded but not yet used

react_on_rails_pro 16.6.0 pulls in async, httpx, http-2, jwt, io-event, traces, etc. — all infrastructure for the Node renderer. Since this PR explicitly keeps ExecJS and defers the Node renderer to sub-PR 2, every one of these gems is loaded in every Rails process for zero current benefit. This isn't a blocker for a tutorial repo, but it's worth a comment in the Gemfile noting that these transitive deps become relevant in sub-PR 2, so future maintainers don't prune them as "unused".


📝 Minor notes

  • pack-config-diff ^0.1.0 is a new transitive dep of shakapacker 10.0.0 not present in rc.0 — not a concern, just newly visible in the lockfile.
  • react_on_rails_pro tightens the execjs constraint to ~> 2.9 (vs core's ~> 2.5). The lockfile resolves this fine; just worth knowing if you ever need to pin execjs manually.

Verdict: Approve with the production license documentation addressed before any deployment beyond CI. The sub-path alias gap is lower priority but should be tracked.

Comment thread config/webpack/commonWebpackConfig.js
Comment thread Gemfile
@ihabadham
Copy link
Copy Markdown
Collaborator Author

License: deferring to Sub-PR 2 where NodeRenderer activates and the license becomes load-bearing. This PR stays on ExecJS, so the Pro engine just logs the dev-environment notice. Sub-PR 2 adds .env.example + CI secret.

@ihabadham ihabadham merged commit 5551af9 into ihabadham/feature/pro-rsc/base Apr 20, 2026
14 checks passed
@ihabadham ihabadham deleted the ihabadham/feature/pro-rsc/gem-swap branch April 20, 2026 20:17
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 20, 2026

✅ Review app for PR #726 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