Skip to content

Polish RSC generator install follow-ups#3664

Merged
justin808 merged 6 commits into
mainfrom
jg-codex/follow-up-3640-3646-rsc-generator
Jun 5, 2026
Merged

Polish RSC generator install follow-ups#3664
justin808 merged 6 commits into
mainfrom
jg-codex/follow-up-3640-3646-rsc-generator

Conversation

@justin808

@justin808 justin808 commented Jun 5, 2026

Copy link
Copy Markdown
Member

Summary

  • Add install-time info that every --rsc install uses react-on-rails-rsc@19.0.5-rc.6 until stable 19.0.5 is published and tagged latest.
  • Make manual dependency recovery commands package-manager-aware instead of always showing npm.
  • Simplify active-bundler RSC plugin import normalization and clarify the multiline CommonJS destructuring regex comment.
  • Add mixed active/inactive RSC plugin verification for real JS imports and invocations.

Design Calls

  • All --rsc installs keep the prerelease react-on-rails-rsc pin for now, including Webpack projects. The generator no longer retries an unversioned latest fallback because npm latest may not include Rspack support yet.
  • Inactive plugin symbols are reported when they appear as real CommonJS or ESM imports, or real new InactivePlugin(...) invocations, alongside the active plugin.
  • Inactive plugin names inside comments or string literals are intentionally ignored during stale-symbol verification.
  • normalize_rsc_plugin_import_for_active_bundler now derives inactive plugin class and import path from the module-level helper methods instead of caller-supplied parameters.

Tests

  • git diff --check
  • bundle exec rspec spec/react_on_rails/generators/install_generator_spec.rb:2000 spec/react_on_rails/generators/rsc_generator_spec.rb:2559
  • bundle exec rspec spec/react_on_rails/generators/js_dependency_manager_spec.rb spec/react_on_rails/generators/generator_helper_spec.rb
  • bundle exec rspec spec/react_on_rails/generators/install_generator_spec.rb:2013 spec/react_on_rails/generators/install_generator_spec.rb:2025
  • bundle exec rspec spec/react_on_rails/generators/rsc_generator_spec.rb:2581 spec/react_on_rails/generators/rsc_generator_spec.rb:2604
  • bundle exec rspec spec/react_on_rails/generators/rsc_generator_spec.rb:1114
  • bundle exec rubocop lib/generators/react_on_rails/generator_helper.rb lib/generators/react_on_rails/js_dependency_manager.rb lib/generators/react_on_rails/rsc_setup.rb lib/generators/react_on_rails/rsc_setup/client_references.rb spec/react_on_rails/generators/generator_helper_spec.rb spec/react_on_rails/generators/install_generator_spec.rb spec/react_on_rails/generators/js_dependency_manager_spec.rb spec/react_on_rails/generators/rsc_generator_spec.rb
  • Pre-commit and pre-push hooks reran trailing newline and RuboCop checks for the changed Ruby files.

Closes #3640
Closes #3646


Note

Low Risk
Changes are limited to install-time generators and warning text; the main behavioral shift is refusing an unversioned RSC fallback, which is intentional and covered by updated specs.

Overview
Generator install UX now surfaces package-manager-aware manual recovery commands (npm, yarn, pnpm, bun) for add/remove/install failures instead of always showing npm install. Fallback installs drop --save-exact / --exact when specs use semver ranges (~, ^) so manual and CLI recovery match real constraints.

RSC JS dependencies: every --rsc run logs why react-on-rails-rsc is pinned to the prerelease (19.0.5-rc.6). On install failure the generator keeps the pin and stops retrying unversioned latest (avoids replacing a good pin with an incompatible package). Pin-failure copy is unified via rsc_dependency_failure_message and applies to Webpack and Rspack.

RSC webpack migration/verification: inactive bundler plugin detection uses real JS (CommonJS/ESM imports and new InactivePlugin(...)) and ignores comments/strings. Config checks can report stale inactive plugins when the active plugin is already present. Import normalization no longer takes inactive class/path from callers; multiline CommonJS require destructuring is documented as supported.

Reviewed by Cursor Bugbot for commit f17926a. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Bug Fixes

    • Generator messages now use package-manager-aware install/remove commands and exact-pinned install guidance for recoveries; fallback warnings reference "direct package manager commands" rather than only npm.
    • RSC setup emits clearer, consolidated warnings for React-version compatibility and stale/inactive RSC bundler plugins in webpack/client/server configs.
  • Tests

    • Specs updated to validate package-manager-aware messaging, pinned-install recovery commands, and stale-plugin detection.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 51d5d6a7-1d44-4679-a7ca-a72e8caf000d

📥 Commits

Reviewing files that changed from the base of the PR and between d6748c9 and f17926a.

📒 Files selected for processing (3)
  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
🚧 Files skipped from review as they are similar to previous changes (2)
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb

Walkthrough

Centralizes package-manager-aware command generation for generator warnings/rescue paths, consolidates RSC pin messaging, and adds stale-inactive RSC plugin detection and client-reference normalization with matching spec updates.

Changes

RSC Generator Package-Manager Awareness

Layer / File(s) Summary
Package-manager-aware command helpers
react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
New helpers (manual_add_packages_command, manual_install_dependencies_command, manual_remove_packages_command, and supporting flag/semver helpers) build install/uninstall command strings per detected package manager.
Dependency manager warning updates
react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
Dependency-add/remove messages and failure/rescue guidance for react-on-rails, React, CSS, Rspack, SWC, Babel React preset, TypeScript, Pro, Dev deps, and generic JS install now use the package-manager-aware helpers instead of hardcoded npm strings.
RSC dependency handling and pinning
react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb, react_on_rails/lib/generators/react_on_rails/rsc_setup.rb
Refactors RSC flows to compute rsc_packages and used_version_pins, centralizes pin-info output, and emits manual install guidance via manual_add_packages_command(rsc_packages) with exact-pin behavior when appropriate.
Generator-level wording updates
react_on_rails/lib/generators/react_on_rails/generator_helper.rb, react_on_rails/lib/generators/react_on_rails/rsc_setup.rb
Fallback warning wording changed to "direct package manager commands"; React compatibility warnings now render package-manager-aware install commands.
RSC webpack config validation and stale plugin detection
react_on_rails/lib/generators/react_on_rails/rsc_setup.rb
Server/client config checks now include stale_inactive_rsc_plugin_messages to warn about inactive bundler plugin symbols when both active and inactive plugins appear.
RSC plugin normalization and detection improvements
react_on_rails/lib/generators/react_on_rails/rsc_setup/client_references.rb
Simplified normalize_rsc_plugin_import_for_active_bundler signature, improved CommonJS multiline destructuring regex, and added invocation-detection (inactive_rsc_plugin_invocation_in_js_code?) to avoid matches in comments/strings.
Spec updates for messaging and plugin detection
react_on_rails/spec/react_on_rails/generators/*
Updated expectations for package-manager-aware fallback wording and commands; added tests for RSC pinned-install messaging across package managers and for stale inactive-plugin import/invocation detection and comment/string-safe behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

  • #3640: Follow up RSC generator install messaging nits from #3590 — Implements package-manager-aware manual commands and RSC pin messaging discussed in the issue.
  • #3646: Follow up RSC rspack generator polish from #3590 — Simplifies plugin normalization parameters and adds stale-plugin verification as requested.
  • #3620: Overlaps RSC compatibility warning messaging updates and manual command construction.

Possibly related PRs

Poem

🐇 I nudge the generators, tidy and quick,
Swap hardcoded npm for commands that pick,
Pins stay put and plugins get seen,
The rabbit hops in to keep configs clean.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: polishing RSC generator install follow-ups addressing package-manager awareness, messaging, and plugin verification.
Linked Issues check ✅ Passed All coding requirements from #3640 and #3646 are met: install-time pin messaging added, manual commands made package-manager-aware, plugin import normalization simplified, multiline regex clarified, and mixed plugin verification implemented.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked issues: messaging improvements, package-manager detection, plugin normalization, and configuration verification—no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jg-codex/follow-up-3640-3646-rsc-generator

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.

@justin808 justin808 marked this pull request as ready for review June 5, 2026 09:24
@greptile-apps

greptile-apps Bot commented Jun 5, 2026

Copy link
Copy Markdown

Greptile Summary

This PR polishes the RSC generator install flow with three focused changes: package-manager-aware manual recovery commands (replacing hardcoded npm install strings everywhere), a unified version-pin strategy that keeps react-on-rails-rsc@19.0.5-rc.6 for all --rsc installs rather than only for Rspack, and smarter inactive-plugin detection that ignores names appearing only in comments or string literals.

  • PM-aware helpers (manual_add_packages_command, manual_remove_packages_command, manual_install_dependencies_command) are wired through every warning message in js_dependency_manager.rb and rsc_setup.rb, replacing a dozen npm install … literals.
  • RSC pin unification: the Rspack-only no-retry path is deleted; all --rsc installs now log a rsc_dependency_pin_info message upfront and, on failure, emit a single rsc_dependency_pin_failed_warning without attempting an unversioned latest retry.
  • Inactive-plugin detection: inactive_rsc_plugin_symbol_in_js_code? replaces content.include?(inactive_rsc_plugin_class_name) substring checks, adding js_code_position?-guarded invocation scanning and comment/string exclusion for both CommonJS and ESM paths.

Confidence Score: 4/5

Changes are confined to generator messaging, dependency-install logic, and RSC config heuristics; no runtime app code or auth paths are touched, making this safe to merge.

The only notable issue is that when an RSC version-pin install fails, the user receives two consecutive warnings that both print the same manual install command. A separate test for rspack-specific RSC pin failure now exercises the same unified code path as the non-rspack test, which could mislead future maintainers.

The add_rsc_dependencies failure path in js_dependency_manager.rb (lines ~182–190) is worth a second look to confirm the redundant-warning behavior is intentional.

Important Files Changed

Filename Overview
react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Replaces all hardcoded npm install manual-recovery strings with manual_add_packages_command/manual_remove_packages_command helpers; unifies the rspack-only version-pin fallback path into a single path for all RSC installs.
react_on_rails/lib/generators/react_on_rails/rsc_setup.rb Adds stale_inactive_rsc_plugin_messages helper and replaces bare substring checks with the new inactive_rsc_plugin_symbol_in_js_code? predicate for both server and client config verification.
react_on_rails/lib/generators/react_on_rails/rsc_setup/client_references.rb Removes caller-supplied parameters from normalize_rsc_plugin_import_for_active_bundler; adds inactive_rsc_plugin_symbol_in_js_code? and inactive_rsc_plugin_invocation_in_js_code? predicates; corrects the rsc_plugin_commonjs_import_regex comment.
react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb Updates RSC dependency specs to reflect the new 'keeps pin' behavior and --save-exact in manual-install strings.

Comments Outside Diff (1)

  1. react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb, line 182-190 (link)

    P2 Duplicate manual command in sequential warnings when pin install fails

    When add_packages returns false and used_version_pins is true, the user receives two consecutive warnings that both embed the same manual_add_packages_command output: first rsc_dependency_pin_failed_warning (which already ends with "Run <command> to finish setup."), then the generic "⚠️ Failed to add React Server Components dependencies … #{manual_add_packages_command(manual_install_packages)}". The commands are identical because manual_install_packages = rsc_packages equals rsc_packages_with_pin in that branch. Consider either omitting the manual command from the generic failure block when the pin warning already contains it, or merging the two into a single warning.

Reviews (1): Last reviewed commit: "Polish RSC generator follow-ups" | Re-trigger Greptile

Comment thread react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb Outdated
@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Code Review — Polish RSC generator install follow-ups

Overview

This PR does four things well:

  • Replaces all hardcoded npm install manual-recovery strings with a new manual_add_packages_command helper that honours the detected package manager (npm/yarn/pnpm/bun).
  • Unifies the rspack-only pin-skip behaviour so every --rsc install keeps the prerelease pin and explains why.
  • Tightens the webpack RSC config verifier so stale inactive-plugin symbols in comments and string literals no longer trigger false "wrong bundler plugin" warnings.
  • Adds stale_inactive_rsc_plugin_messages to catch configs where both the active and inactive plugins coexist.

The overall direction is solid and the new test coverage is good (package-manager variants, comment/string exclusion, mixed-plugin detection).


Issues

1. Stale TODO comment — RSC_PACKAGE_VERSION_PIN block

The TODO at the top of js_dependency_manager.rb (near RSC_PACKAGE_VERSION_PIN) still says:

"the rspack-only fallback skip in add_rsc_dependencies can be removed (rspack can safely share the webpack unversioned-fallback path again)"

That fallback was removed entirely by this PR — there is no longer a "fallback skip" to remove when 19.0.5 stable ships. The TODO should be reworded, e.g.:

# TODO(#3488): when react-on-rails-rsc 19.0.5 stable ships, bump RSC_PACKAGE_VERSION_PIN to
# "19.0.5", set used_version_pins to false in rsc_packages_with_version (so the pin-info/pin-failed
# messages are no longer emitted), and verify peer-dep alignment between react@19.0.x and
# react-on-rails-rsc@19.0.5.

2. Duplicate manual-install command on failed RSC install

When add_packages returns false and used_version_pins is true, the user receives two consecutive warnings that both print the same install command:

  1. rsc_dependency_pin_failed_warning → "...Run pnpm add --save-exact react-on-rails-rsc@19.0.5-rc.6 to finish setup."
  2. The generic "⚠️ Failed to add RSC dependencies" → "You can install them manually by running: pnpm add --save-exact react-on-rails-rsc@19.0.5-rc.6"

The second command is entirely redundant. Either drop the MSG block when used_version_pins is true, or fold the pin-failed explanation into it.

3. Minor: manual_remove_packages_command duplicates the base_commands hash pattern

manual_remove_packages_command defines its own base_commands hash with the same four entries (npm/yarn/pnpm/bun) as build_install_args. A small build_remove_args(package_manager, packages) helper (mirroring build_install_args) would keep the two in sync and remove the duplication — especially important if a 5th package manager is ever added.


Minor observations (non-blocking)

  • build_install_args always emits --save-exact / --exact for all package managers. When used in the manual-recovery messages with range specifiers like react@~19.0.4, the combined instruction (npm install --save-exact react@~19.0.4) is semantically odd (npm will install the latest 19.0.x and save the exact resolved version, not the ~ range). This pre-dates the PR, but surfacing it in the user-visible messages makes it more visible now.
  • rsc_packages_with_version unconditionally returns [rsc_packages_with_pin, true], making the if used_version_pins guards always true. That's correct for the RC window and well-explained by the TODO — just noting it for the eventual cleanup.

Test coverage

New tests are well-targeted:

  • Pin-info message content and package-manager awareness (pnpm + yarn variants).
  • Mixed active/inactive plugin detection for both import and invocation forms.
  • Correct rejection of comment/string occurrences of the inactive plugin symbol.

The tests for the previous "fallback to latest" path are correctly updated to assert the pin-kept behavior.

Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Code Review: Polish RSC generator install follow-ups

Overview

This PR makes three related improvements to the RSC generator:

  1. Makes all manual-recovery error messages package-manager-aware (npm/yarn/pnpm/bun) instead of always hard-coding npm install
  2. Simplifies the RSC dependency install path by removing the branchy "retry unversioned" fallback — all bundlers keep the prerelease pin
  3. Improves the webpack RSC plugin verification to detect stale inactive plugins in real JS code (not comments/strings) and report them even when the active plugin is already present

Overall this is clean, well-motivated work. The test coverage is solid. One UX nit and one style observation below.


Issues

Duplicate manual install command in failure output

When the RSC package install fails and used_version_pins is true, add_rsc_dependencies emits two back-to-back warnings that both contain the same install command:

  1. rsc_dependency_pin_failed_warning already ends with: "Run pnpm add --save-exact react-on-rails-rsc@19.0.5-rc.6 to finish setup."
  2. The generic failure warning that follows immediately says: "You can install them manually by running: pnpm add --save-exact react-on-rails-rsc@19.0.5-rc.6"

The pin-failed warning is complete instructions on its own. The generic warning after it is redundant and will confuse users who see the same command recommended twice for the same failure.

Simplest fix — guard the generic warning so it only fires when there is no pin-specific warning already covering the failure:

GeneratorMessages.add_warning(rsc_dependency_pin_failed_warning) if used_version_pins

unless used_version_pins
  GeneratorMessages.add_warning(<<~MSG.strip)
    ⚠️  Failed to add React Server Components dependencies.

    You can install them manually by running:
      #{manual_add_packages_command(manual_install_packages)}
  MSG
end

Or drop the trailing manual-command sentence from rsc_dependency_pin_failed_warning and let the generic warning cover both cases.

Minor: duplicated base_commands structure in manual_remove_packages_command

manual_remove_packages_command defines its own base_commands hash (remove verb per PM), while build_install_args has a structurally identical one (add verb). If a new PM is ever supported, both need updating. A shared constant (e.g. PM_REMOVE_COMMANDS) beside build_install_args would prevent drift. Not blocking.


Positive notes

  • Unified helpers (manual_add_packages_command, manual_install_dependencies_command, manual_remove_packages_command) are a clean abstraction that made the large sweep of error messages a mechanical find-replace.
  • Simplified add_rsc_dependencies — dropping the webpack/rspack branch and the unversioned-retry path removes a real source of divergence bugs.
  • inactive_rsc_plugin_symbol_in_js_code? is a meaningful improvement over the old content.include? — skipping comments and string literals avoids false positives.
  • stale_inactive_rsc_plugin_messages correctly reports stale plugins even when the active plugin is already present, closing a gap in the prior logic.
  • Test additions for pnpm/yarn recovery commands and mixed-plugin verification are well-targeted.

Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
@justin808 justin808 force-pushed the jg-codex/follow-up-3640-3646-rsc-generator branch from ca43f11 to 57d03d8 Compare June 5, 2026 10:10
@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Code Review

Overall: Clean, well-scoped follow-up. Generalizing hardcoded npm strings to package-manager-aware helpers is the right call, and the RSC plugin detection improvements are solid. The PR is low-risk (generator-only, no production runtime paths) and the new specs cover the key new behaviors.


Strengths

  • manual_add_packages_command / manual_install_dependencies_command / manual_remove_packages_command are a clean trio that eliminate a large swath of hardcoded npm install strings uniformly across all failure messages.
  • inactive_rsc_plugin_symbol_in_js_code? combining CJS import + ESM import + invocation detection is thorough. The three test cases (stale import, stale invocation, names-in-comments/strings) give good coverage of the boundary cases.
  • Dropping the unversioned-latest retry path simplifies add_rsc_dependencies considerably and the reasoning is well-documented.
  • fallback_package_manager already normalises unsupported managers to "npm", so the fetch calls in both build_install_args and manual_remove_packages_command are safe without a default.

Issues

Minor — unnecessary .dup in manual_remove_packages_command

base_commands is declared locally inside the method, so every call creates a fresh hash. Array#+ already produces a new array without touching the source, so .dup does nothing. (Contrast with build_install_args line 632 where .dup is required because a destructive << follows — that usage is correct.)

Minor — rescue path skips rsc_dependency_pin_failed_warning

In the normal failure path (line 426) rsc_dependency_pin_failed_warning is emitted before the generic "Failed to add" warning. In the rescue StandardError path (line 434) it is not, so a network error silently omits the pin context that tells the user why the pinned version matters. Likely just an oversight — the fix is a one-liner before the warning block.


Nitpick

When install fails, the user receives both rsc_dependency_pin_info (already queued before the install attempt) and rsc_dependency_pin_failed_warning. Both messages explain the pin rationale, so there is some redundancy in the failure path. Intentional or worth collapsing the info message into the failure warning?

Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
@justin808 justin808 force-pushed the jg-codex/follow-up-3640-3646-rsc-generator branch from 57d03d8 to bf167dd Compare June 5, 2026 10:11
@justin808 justin808 force-pushed the jg-codex/follow-up-3640-3646-rsc-generator branch from bf167dd to 53627c9 Compare June 5, 2026 10:12
@justin808

Copy link
Copy Markdown
Member Author

Update pushed in 53627c92.

What changed:

  • Rebased the PR branch onto current origin/main after Derive Pro RSC client refs from the RSC graph #3556.
  • Kept the RSC pin failure explanation, but moved the actionable manual install command to the generic recovery warning so it appears once.
  • Added the same pin-context warning on the raised-error path.
  • Replaced the duplicated remove-command mapping with shared package-manager command lookup and removed the unnecessary remove-path .dup.
  • Folded the Rspack-specific failure assertions into the shared pin-failure spec so the spec no longer implies a separate Rspack branch.

Validation:

  • bundle exec rspec react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb - 74 examples, 0 failures
  • bundle exec rubocop react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb - no offenses

CI restarted for the rebased branch and is currently queued/pending.

Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Code Review

Overview

Solid cleanup PR that addresses two gaps from the previous RSC generator work (#3640, #3646):

  1. Package-manager-aware manual recovery commands — replaces hardcoded npm install/npm uninstall in every error message with manual_add_packages_command / manual_remove_packages_command helpers that use the detected package manager (npm/yarn/pnpm/bun).
  2. RSC pin UX — removes the silent "retry unversioned latest" fallback, adds an upfront add_info message explaining the temporary pin, and detects mixed active+inactive RSC plugins (e.g. both RSCRspackPlugin and RSCWebpackPlugin) in webpack/rspack configs.

What's good

  • package_manager_commands hash cleanly centralizes install/remove commands per package manager, replacing an ad-hoc build_install_args map that only covered install. Adding remove alongside it is the right design.
  • fallback_package_manager already defaults to "npm" for unknown managers, so the .fetch(package_manager) inside package_manager_commands can never raise in practice.
  • Comment fix on rsc_plugin_commonjs_import_regex — the old "matches single-line only" comment was factually wrong ([^}]* does cross newlines in Ruby because it matches any character except }). The new comment correctly documents multiline behaviour.
  • inactive_rsc_plugin_symbol_in_js_code? uses js_code_position? to ignore comment/string occurrences of the inactive plugin name — the three new specs (import, invocation, and comment/string-ignore) give good confidence.
  • Duplicate-command guard in the spec (warning_text.scan(manual_command).size).to eq(1)) is a nice regression trap.
  • Good test coverage — new install_generator_spec block covers info-on-success, pnpm-aware recovery, and yarn-aware recovery for the pin path.

Minor issue (see inline)

Both rsc_dependency_pin_info and rsc_dependency_pin_failed_warning hardcode the string "19.0.5" as the stable target while RSC_PACKAGE_VERSION_PIN is used for the prerelease pin. If the pin is bumped (e.g. to "19.1.0-rc.1" once that ships), these messages will silently say "stable 19.0.5" even though the stable target has changed. See inline comment for two fix options.

Nit

build_remove_args calls .fetch(:remove).dup + packages. The .dup is defensive-correct (avoids mutating the hash's stored array), but since + already returns a new array in Ruby, dup is redundant. Low-stakes, but worth a one-liner cleanup.

Verdict

Approve with minor fix — the hardcoded "19.0.5" should be extracted (constant or derived) before merging so future pin bumps don't produce stale messages. Everything else looks correct and well-tested.

@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Code Review: Polish RSC generator install follow-ups

This is a well-structured PR with clear goals. The changes are low-risk (generator/install-time only), test coverage is solid, and the simplifications are sensible. A few observations below.


What this does

  • Package-manager-aware recovery commands: replaces all hardcoded npm install / npm uninstall in fallback warning messages with dynamic helpers that detect the active package manager (npm, yarn, pnpm, bun).
  • RSC pin simplification: removes the "retry with unversioned latest" fallback; all RSC installs now keep the prerelease pin and emit an informational message explaining the temporary pin.
  • Stale inactive plugin detection: when the active bundler plugin is already configured, the generator now also checks for and reports the inactive bundler plugin alongside it (in real JS code, not comments or strings).
  • Regex/comment fix: corrects the misleading comment on rsc_plugin_commonjs_import_regex — the regex already crossed newlines via [^}]*, so the old "single-line only" claim was wrong.

Strengths

  • DRY refactor: package_manager_commands table centralises all four package managers cleanly. manual_add_packages_command, manual_remove_packages_command, and manual_install_dependencies_command give the callsites a clean API.
  • Invocation detection: inactive_rsc_plugin_invocation_in_js_code? correctly uses js_code_position? to avoid false positives from comments or string literals, and the spec covers exactly those cases.
  • Simplification of RSC retry logic: removing the webpack/rspack conditional retry path and keeping a single pin for all RSC installs is the right call while the Rspack-capable version is prerelease.
  • Test coverage: the new specs comprehensively exercise package-manager switching, the info/warning messages, and the mixed active+inactive plugin scenarios.

Issues and Observations

1. --save-exact combined with a version range in the React version hint

manual_add_packages_command(['react@~19.0.4', 'react-dom@~19.0.4']) produces:

npm install --save-exact react@~19.0.4 react-dom@~19.0.4

The --save-exact flag pins the resolved version to package.json (no ^ or ~ prefix saved), but the ~19.0.4 range spec still controls what npm resolves to first. The combination is semantically valid but looks contradictory to users — they see both --save-exact and ~ in the same command. For the "downgrade from 19.1.x" case especially, it may puzzle someone. Consider using an explicit version (react@19.0.4) or dropping --save-exact from recovery commands that already contain a range specifier.

2. Two separate warning messages on RSC pin failure

When add_packages returns false and version pins were used, users now receive two back-to-back warning messages:

  1. rsc_dependency_pin_failed_warning — explains why the pin is kept
  2. The "Failed to add RSC dependencies" message with the manual command

Before this PR they were combined into one. Splitting is cleaner in the code but may read as duplicated noise in the terminal. Consider folding the pin-failure context into the single warning block so there is one actionable message.

3. Rescue block may mislead when add_packages raises mid-flight

rsc_dependency_pin_failed_warning says "the generator left the version pin in package.json". However, if an exception is thrown from add_packages before write_versioned_package_specs_to_package_json runs (e.g. from the initial add_npm_dependencies call), the pin may not have been written. The user would then be told to run the pinned command against a package.json that does not yet contain the pin. This is a rare edge case inside an already-exceptional path, but the wording could be softened to "may have left the version pin" or the pin context dropped from the rescue branch entirely.

4. fallback_package_manager called on every manual_* helper

manual_add_packages_command calls build_install_args which calls fallback_package_manager which calls detect_package_manager (potentially doing file-system I/O). Error paths that emit multiple recovery messages call it on each string interpolation. If detect_package_manager is cheap this is a non-issue — just worth confirming it is not re-scanning the project each time.

5. rsc_dependency_pin_info shown on every successful RSC install

The info message about the temporary prerelease pin is always emitted (even on a clean, fast install) because GeneratorMessages.add_info(rsc_dependency_pin_info) if used_version_pins runs before add_packages. This is intentional and useful for transparency, but it will appear on every --rsc install until 19.0.5 is stable. Confirm this is the desired verbosity level.


Minor nits

  • manual_install_packages = rsc_packages_with_pin in the rescue block recomputes what rsc_packages already holds (both return the same value for the base class). Using the already-computed rsc_packages would avoid the redundant call.
  • rsc_dependency_pin_failed_warning no longer mentions a specific manual command — the command appears only in the subsequent separate warning. If the two warnings are ever shown in isolation (e.g. pasted in a bug report), the pin warning alone is missing the actionable step.

Summary

The direction is correct. The package-manager-aware commands and the RSC retry simplification are solid improvements. The two main things worth a second look before merge are the double-warning UX on pin failure and the --save-exact + range-selector combination in the React version hint messages.

@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Code Review

Overview

This PR polishes the RSC generator install experience in three focused areas: (1) package-manager-aware manual recovery commands replacing hardcoded npm; (2) simplified RSC install logic that drops the unversioned latest fallback; (3) improved inactive-plugin detection that ignores comments and strings. All three are well-scoped and low-risk.


Strengths

Package manager awareness - replacing 14+ hardcoded npm install / npm uninstall strings with manual_add_packages_command / manual_remove_packages_command helpers is clean and correct. The helpers delegate to fallback_package_manager which already defaults to npm for unrecognized managers, so package_manager_commands.fetch(package_manager) cannot raise in practice.

RSC install simplification - dropping the Webpack/Rspack branch and the unversioned latest retry simplifies add_rsc_dependencies significantly. The reasoning (both bundlers need the same pin until 19.0.5 is stable) is sound and clearly documented in the PR and in rsc_dependency_pin_info.

Regex comment fix - the old comment on rsc_plugin_commonjs_import_regex said the regex was single-line-only; the new comment is accurate. [^}]* in Ruby does match newlines (only . skips them by default), so the regex has always handled multiline destructuring. Now the comment says so.

Inactive-plugin detection - inactive_rsc_plugin_symbol_in_js_code? is the right guard for the stale-symbol report. Using js_code_position? (not js_top_level_position?) for the new InactivePlugin(...) invocation check is intentional and correct: plugin instantiation can appear inside callback functions, not just at module scope.

Test coverage - new specs directly exercise the three changed behaviours (pnpm/yarn command strings, pin-failure output, comment/string ignoring). The renaming of the old test to keeps-the-pin correctly reflects the new intent.


Issues and observations

1. Triple-message verbosity on install failure

In add_rsc_dependencies, rsc_dependency_pin_info is emitted before the install attempt (line 413). On failure the user sees three messages: the pre-install info, the pin-failed warning, then the main failure warning. The info message was designed for the success path; showing it before a failed install is confusing. Consider emitting it only on success, inside the success branch of add_packages(rsc_packages).

2. --save-exact with range specifiers in recovery commands

manual_add_packages_command always delegates to build_install_args, which adds --save-exact. Some recovery messages pass range-specified packages, e.g. react@~19.0.4 and react-dom@~19.0.4 from warn_about_react_version_for_rsc. Running npm install --save-exact react@~19.0.4 resolves the range and pins the exact resolved version to package.json, discarding the intended range. For RSC pinned packages this is correct; for advisory minimum-version messages it is at best surprising. This is a pre-existing pattern, but the PR makes it more visible.

3. Hardcoded 19.0.5 in rsc_dependency_pin_info

The stable target version is mentioned literally in the string rather than via a constant. RSC_PACKAGE_VERSION_PIN already holds the prerelease string. If 19.0.5 ships under a different tag this message will be stale. Consider a constant (e.g. RSC_STABLE_PACKAGE_VERSION) or an explicit TODO comment. Minor, but the message is user-visible.

4. Pin-failed warning emitted for all errors in the rescue path

In the rescue block, rsc_dependency_pin_failed_warning is added unconditionally (when used_version_pins) even for failures unrelated to the pin (e.g. a network timeout). This can mislead users into thinking the pin is the root cause. Folding the pin note into the main error message, or making the warning conditional on absence of an explicit exception message, would reduce noise.


Summary

The core changes are correct, well-tested, and a genuine improvement. The main suggestion worth acting on before merge is the info-message ordering (issue 1). Items 2-4 are cosmetic and can be addressed in a follow-up.

@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Code Review: Polish RSC generator install follow-ups

Overall: Solid cleanup. The package-manager-aware messaging is a meaningful improvement for yarn/pnpm/bun users, dropping the latest retry simplifies the install path safely, and detecting stale inactive plugins via real JS positions (not string inclusion) is strictly more correct. Tests are well-targeted.

A few items worth discussing:


Verbosity on install failure

When add_packages returns false and used_version_pins is true, the user receives three separate GeneratorMessages entries in sequence:

  1. Info: pin explanation (added before the install attempt at line 413)
  2. Warning: rsc_dependency_pin_failed_warning (line 416)
  3. Warning: generic "Failed to add RSC dependencies" with manual install command (lines 418–423)

Messages 2 and 3 could be consolidated — the pin failure warning's "left the version pin in package.json" sentence and the manual install command belong in the same block. As-is, some UIs that display generator messages sequentially will show the explanation separated from the remediation by an unrelated message.


rsc_dependency_pin_failed_warning is still Rspack-centric in language

The method is now called for all RSC projects (Webpack included), but the body only mentions react-on-rails-rsc/RspackPlugin as the reason the pin is needed — it doesn't mention WebpackPlugin. A Webpack user reading this warning might wonder why RspackPlugin concerns them. The rsc_dependency_pin_info sibling (shown on success) does explain both plugins; the failure warning should match that framing.


Spec duplicates extraction logic

install_generator_spec.rb defines let(:rsc_stable_target) { rsc_pin.split("-", 2).first }, which replicates the same transformation as the new rsc_stable_package_version_target helper. If the extraction logic ever changes (e.g. adopting a semver library), the spec will keep passing because it recomputes independently. Calling install_generator.send(:rsc_stable_package_version_target) in the let would make the spec sensitive to the real implementation.


Minor: rsc_packages_with_pin used unconditionally in rescue branch

In the rescue block manual_install_packages = rsc_packages_with_pin is always called unconditionally, even when used_version_pins is false (meaning rsc_packages_with_version returned the packages without a pin). In that case rsc_packages_with_pin returns the same result (it reads the constant directly), so this is harmless — but it silently ignores the caller-supplied packages in favour of the pinned set. Worth a comment or an explicit conditional.


Positives worth calling out

  • Regex comment correction in rsc_plugin_commonjs_import_regex: the old comment claimed single-line only, but [^}]* always crossed newlines. The new comment is accurate.
  • normalize_rsc_plugin_import_for_active_bundler simplification — removing the caller-supplied parameters and using the module-level helpers directly reduces the API surface and avoids the risk of caller/module state diverging.
  • inactive_rsc_plugin_invocation_in_js_code? correctly uses js_code_position? to skip matches inside comments and strings, which was the main gap the old content.include? check had.

Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
Comment thread react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Code Review — Polish RSC Generator Install Follow-ups

Overall assessment: Solid, well-motivated cleanup. The package-manager-aware command helpers eliminate a whole class of "why does it tell me to run npm when I'm using pnpm?" UX bugs, and the RSC retry-removal simplifies a subtle, hard-to-test code path. Test coverage is comprehensive. A few things worth looking at below.


Findings

--save-exact added to all existing add_react_dependencies recovery commands (unintended behavior change?)

manual_add_packages_command routes through build_install_args, which always prepends --save-exact. The prior warning for add_react_dependencies was:

npm install react@~19.0.4 react-dom@~19.0.4 prop-types@^15.0.0

It's now:

npm install --save-exact react@~19.0.4 react-dom@~19.0.4 prop-types@^15.0.0

--save-exact combined with a semver range (~) tells npm to resolve via the range but save the exact resolved version. That's a semantically different instruction than the original command, and the ~19.0.4 and ^15.0.0 ranges in the displayed command now look contradictory to a user who knows what --save-exact does. If the intent is to lock a specific resolved version (desirable for RSC packages), this should be intentional; if it's an unintentional consequence of routing all commands through the same helper, the semver-ranged packages might deserve their own path.

The updated test confirms the new output (npm install --save-exact react@~19.0.4 ...) but doesn't verify whether this is the intended behavior change vs. an artifact of the refactor.

Test isolation: new install_generator_spec.rb block doesn't clear GeneratorMessages

The new describe "#add_rsc_dependencies" block in install_generator_spec.rb reads GeneratorMessages.messages directly:

before do
  allow(install_generator).to receive(:say)
  allow(install_generator).to receive(:fallback_package_manager).and_return("pnpm")
end
# ...
message_text = GeneratorMessages.messages.join("\n")

There's no GeneratorMessages.clear in the before block. If other tests in the same file leave messages in GeneratorMessages, these assertions could pick up stale state. The js_dependency_manager_spec.rb already demonstrates the correct pattern (GeneratorMessages.clear in its shared before block). Worth adding to this new block for consistency.

Blank line in warning when rsc_packages_with_version raises (minor formatting)

When rsc_packages_with_version itself raises (the "pin lookup failed" path), used_version_pins remains false and rsc_dependency_pin_failure_details returns "". The interpolated template then renders as:

⚠️  Error adding React Server Components dependencies: pin lookup failed

You can install them manually by running:
  npm install --save-exact react-on-rails-rsc

The blank line (from the empty interpolation surrounded by newlines in the heredoc) is cosmetically slightly off but harmless.


Positive callouts

  • normalize_rsc_plugin_import_for_active_bundler signature cleanup — removing the caller-supplied inactive_plugin_class_name / inactive_plugin_import_path parameters in favor of the module-level helpers is a clear correctness improvement; callers could previously pass mismatched values.
  • Comment fix on rsc_plugin_commonjs_import_regex — the old comment ("Intentionally matches single-line destructuring only") was factually wrong; [^}]* crosses newlines in Ruby by default. The new comment accurately describes what the regex does.
  • Stale inactive plugin detectioninactive_rsc_plugin_symbol_in_js_code? correctly distinguishes real imports and new Plugin(...) invocations from occurrences inside comments or strings. The test that verifies comment/string exemption is exactly the right edge case to cover.
  • RSC retry removal — eliminating the unversioned latest fallback is the right call during the RC window; the old retry could silently swap in an incompatible version. The simplified add_rsc_dependencies is much easier to reason about.

Comment thread react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb Outdated
Comment thread react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Code Review

Overall this is a clean, well-scoped follow-up. The package-manager-aware commands, unified RSC failure messaging, and improved inactive-plugin detection (real JS only, ignoring comments/strings) are all solid. Tests are comprehensive and the logic changes are covered. A few things worth addressing:


Issues

1. Non-obvious rescue fallback in add_rsc_dependencies (lines 411–414)

rsc_packages = RSC_DEPENDENCIES
used_version_pins = false
say "Installing React Server Components dependencies..."
rsc_packages, used_version_pins = rsc_packages_with_version

The first two lines look like dead code — they're immediately overwritten on the happy path. In fact they are the rescue-block fallbacks: if rsc_packages_with_version raises, the rescue block still needs valid rsc_packages / used_version_pins values. The test "falls back to unversioned rsc packages when version resolution raises" exercises this, but a reader skimming the method would likely read these as redundant and remove them in a future cleanup. A single comment like # defaults used by rescue if rsc_packages_with_version raises would make the intent clear.


2. Indentation inconsistency in rsc_dependency_failure_message

"  #{manual_add_packages_command(rsc_packages)}"

Other warning messages in the same file indent the recovery command with 4–12 spaces inside a <<~MSG.strip heredoc (e.g., " #{manual_add_packages_command(...)}"). The rsc_dependency_failure_message helper uses 2 spaces, so the RSC failure output has a noticeably different visual weight than every other recovery message.

Additionally, when used_version_pins is true the assembled output is:

⚠️  Failed to add React Server Components dependencies.
Warning: Could not install the pinned react-on-rails-rsc@X.Y.Z. ...long sentence...
You can install them manually by running:
  pnpm add --save-exact react-on-rails-rsc@X.Y.Z

All the other <<~MSG.strip messages include a blank line between the prose and the recovery command. Adding "" as the third list element (before "You can install...") would match that pattern.


3. package_uses_semver_range? silently ignores other semver operators

package_version.start_with?("~", "^")

Only ~ and ^ are recognised. The npm spec also includes >, >=, <, <=, hyphen ranges, and wildcard ranges (*, x, X). Currently every DEPENDENCIES constant in the file uses either an exact pin or ~/^, so this is not a current bug. However, a future constant with (say) >=19.0.0 would silently get --save-exact applied, which would override the intended constraint. A comment noting the intentional scope makes the tradeoff explicit: # only ~ and ^ are used in this codebase's DEPENDENCIES constants.


Nits

  • The package_manager_commands helper builds a full four-key hash and then fetches one entry on every call. Since this is generator code (runs once) there's no performance concern, but it contrasts with exact_install_flags_for which uses a case statement; either style is fine but they could be consistent.
  • The three new rsc_generator_spec.rb tests (stale inactive import, stale inactive invocation, comments-and-strings ignored) are well-targeted and clearly named.

Overall: Low-risk, well-tested, and a meaningful UX improvement. The rescue-fallback issue (#1) is the only thing I'd want addressed before merge — it's a correctness-silent footgun that could lose the fallback behaviour in a future refactor.

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Pro Node Renderer Benchmark Summary

Benchmark RPS p50(ms) p90(ms) Status
Pro Node Renderer: simple_eval (non-RSC) 2141.27 ▼2.4% (2193.85) 4.1 ▼1.4% (4.16) 5.94 ▼32.9% (8.85) 200=64249
Pro Node Renderer: react_ssr (non-RSC) 1955.46 ▲1.4% (1929.03) 4.62 ▼2.1% (4.72) 5.88 ▼34.2% (8.93) 200=58669

▲/▼ non-zero change vs baseline · 0.0% exact/near-zero match · 🔴 significant regression · 🟢 significant improvement (tracked measures) · (n) = baseline

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Core Benchmark Summary

Benchmark RPS p50(ms) p90(ms) Status
/: Core 2.77 ▲1.1% (2.74) 2869.48 ▲4.4% (2747.37) 3534.7 ▼4.0% (3682.67) 200=92
/client_side_hello_world: Core 655.66 ▲1.9% (643.51) 9.29 ▼0.1% (9.3) 20.2 ▼11.3% (22.76) 200=19810
/client_side_rescript_hello_world: Core 690.27 ▲4.8% (658.56) 8.63 ▼7.1% (9.29) 21.91 ▼0.7% (22.07) 200=20853
/client_side_hello_world_shared_store: Core 687.83 ▲10.3% (623.34) 8.54 ▼14.0% (9.94) 22.08 ▼4.7% (23.17) 200=20778
/client_side_hello_world_shared_store_controller: Core 702.95 ▲13.7% (618.34) 8.43 ▼14.1% (9.82) 21.44 ▼11.2% (24.15) 200=21236
/client_side_hello_world_shared_store_defer: Core 694.26 ▲10.9% (626.13) 8.49 ▼15.3% (10.02) 22.02 ▼3.2% (22.76) 200=20979
/server_side_hello_world_shared_store: Core 12.46 ▲6.2% (11.73) 731.06 ▲10.4% (662.34) 885.37 ▲3.8% (852.74) 200=382
/server_side_hello_world_shared_store_controller: Core 10.1 ▼14.5% (11.82) 581.2 ▼10.5% (649.35) 665.06 ▼21.9% (851.23) 200=315
/server_side_hello_world_shared_store_defer: Core 12.21 ▲4.6% (11.67) 695.87 ▲8.2% (643.02) 896.76 ▲3.3% (868.34) 200=375
/server_side_hello_world: Core 24.61 ▲4.3% (23.59) 242.55 ▼24.3% (320.37) 379.51 ▼4.8% (398.51) 200=755
/server_side_hello_world_hooks: Core 18.98 ▼20.0% (23.71) 318.17 ▼1.3% (322.32) 388.13 ▼3.3% (401.56) 200=580
/server_side_hello_world_props: Core 25.0 ▲4.6% (23.9) 340.49 ▲4.2% (326.74) 392.06 ▼0.7% (394.9) 200=762
/client_side_log_throw: Core 774.53 ▲16.2% (666.6) 8.39 ▼10.0% (9.33) 20.22 ▲1.5% (19.92) 200=23408
/server_side_log_throw: Core 24.55 ▲5.5% (23.27) 344.35 ▲3.5% (332.64) 401.47 ▼0.9% (404.96) 200=749
/server_side_log_throw_plain_js: Core 24.59 ▲4.8% (23.46) 341.97 ▲7.5% (318.03) 390.96 ▼3.1% (403.63) 200=752
/server_side_log_throw_raise: Core 24.72 ▲5.1% (23.52) 344.53 ▲8.7% (316.85) 398.8 ▼1.1% (403.35) 3xx=755
/server_side_log_throw_raise_invoker: Core 882.38 ▲14.3% (772.04) 7.63 ▼10.0% (8.48) 16.67 ▲0.4% (16.6) 200=26656
/server_side_hello_world_es5: Core 25.03 ▲6.5% (23.51) 255.28 ▼21.7% (325.91) 378.15 ▼6.2% (403.27) 200=764
/server_side_redux_app: Core 24.16 ▲5.4% (22.92) 346.92 ▲4.8% (331.16) 397.67 ▼2.3% (407.17) 200=738
/server_side_hello_world_with_options: Core 25.32 ▲6.0% (23.88) 338.99 ▲5.0% (322.79) 382.97 ▼4.0% (399.04) 200=771
/server_side_redux_app_cached: Core 699.51 ▲7.6% (650.34) 9.68 ▼6.8% (10.39) 17.84 ▼5.6% (18.9) 200=21134
/client_side_manual_render: Core 700.84 ▲2.3% (685.1) 8.5 ▼9.0% (9.34) 21.29 ▲7.5% (19.81) 200=21171
/render_js: Core 19.96 ▼18.1% (24.36) 304.38 ▼1.1% (307.69) 366.89 ▼4.6% (384.53) 200=610
/react_router: Core 23.68 ▲6.2% (22.29) 251.78 ▼28.3% (351.31) 398.36 ▼4.9% (418.7) 200=725
/pure_component: Core 25.28 ▲4.2% (24.25) 336.51 ▲3.6% (324.91) 388.65 ▼2.8% (399.98) 200=770
/css_modules_images_fonts_example: Core 25.12 ▲6.4% (23.6) 334.96 ▲4.2% (321.37) 390.37 ▼2.4% (399.77) 200=764
/turbolinks_cache_disabled: Core 699.14 ▲5.5% (662.41) 8.81 ▼7.3% (9.5) 18.65 ▼7.6% (20.18) 200=21147
/rendered_html: Core 17.73 ▼23.9% (23.31) 349.29 ▲8.0% (323.34) 476.91 ▲19.0% (400.86) 200=540
/xhr_refresh: Core 9.95 🔴 19.4% (12.34) 615.67 ▼2.5% (631.62) 763.16 ▼10.1% (849.28) 200=307
/react_helmet: Core 24.46 ▲4.7% (23.36) 345.53 ▲5.0% (329.04) 403.54 ▲0.2% (402.93) 200=745
/broken_app: Core 24.24 ▲3.4% (23.44) 339.72 ▲4.1% (326.22) 396.17 ▼1.0% (400.07) 200=741
/image_example: Core 25.18 ▲10.9% (22.71) 339.89 ▲3.7% (327.76) 386.06 ▼4.5% (404.18) 200=766
/turbo_frame_tag_hello_world: Core 800.82 ▲10.1% (727.66) 8.09 ▼6.7% (8.67) 17.88 ▼2.8% (18.4) 200=24193
/manual_render_test: Core 749.19 ▲11.2% (673.68) 8.53 ▼8.1% (9.29) 20.93 ▲1.5% (20.62) 200=22633

▲/▼ non-zero change vs baseline · 0.0% exact/near-zero match · 🔴 significant regression · 🟢 significant improvement (tracked measures) · (n) = baseline

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Pro (shard 1/2) Benchmark Summary

Benchmark RPS p50(ms) p90(ms) Status
/: Pro 194.99 ▲11.0% (175.69) 41.29 ▼0.4% (41.46) 56.63 ▼9.6% (62.63) 200=5896
/error_scenarios_hub: Pro 413.14 ▲17.9% (350.4) 18.8 ▼5.5% (19.89) 29.54 ▼6.2% (31.49) 200=12483
/ssr_async_error: Pro 385.65 ▲18.2% (326.22) 20.23 ▼1.8% (20.59) 32.91 ▼4.3% (34.4) 200=11650
/ssr_async_prop_error: Pro 366.12 ▲14.0% (321.12) 21.31 ▼2.6% (21.87) 32.04 ▼13.3% (36.94) 200=11062
/non_existing_react_component: Pro 393.62 ▲14.6% (343.48) 20.02 ▼3.3% (20.7) 28.98 ▼19.9% (36.18) 200=11893
/non_existing_rsc_payload: Pro 419.25 ▲17.6% (356.44) 18.36 ▼8.9% (20.16) 28.08 ▼22.9% (36.43) 200=12671
/cached_react_helmet: Pro 428.1 ▲15.2% (371.65) 18.64 ▼5.7% (19.76) 29.38 ▼5.6% (31.13) 200=12935
/cached_redux_component: Pro 423.61 ▲9.9% (385.39) 20.75 ▲8.2% (19.17) 27.56 ▼12.9% (31.63) 200=12796
/lazy_apollo_graphql: Pro 173.2 ▲15.8% (149.56) 41.71 ▼14.1% (48.54) 69.14 ▼16.9% (83.16) 200=5234
/redis_receiver: Pro 76.74 ▼11.7% (86.92) 58.88 ▼12.1% (67.01) 129.47 ▼12.2% (147.44) 200=3356,3xx=6
/stream_shell_error_demo: Pro 383.01 ▲13.8% (336.46) 20.58 ▼1.3% (20.85) 32.94 ▼4.1% (34.36) 200=11573
/test_incremental_rendering: Pro 387.35 ▲13.7% (340.75) 20.18 ▼4.5% (21.14) 32.91 ▼9.3% (36.3) 200=11706
/rsc_posts_page_over_redis: Pro 100.52 ▼7.2% (108.37) 57.36 ▼8.6% (62.73) 112.04 ▲2.2% (109.65) 200=3041
/async_on_server_sync_on_client: Pro 366.47 ▲16.0% (315.95) 21.34 ▼3.1% (22.03) 31.87 ▼21.4% (40.55) 200=11076
/server_router: Pro 369.33 ▲12.0% (329.9) 21.15 ▼1.2% (21.4) 31.8 ▼10.4% (35.5) 200=11160
/unwrapped_rsc_route_client_render: Pro 432.49 ▲17.4% (368.3) 17.8 ▼8.9% (19.55) 28.6 ▼8.2% (31.14) 200=13067
/async_render_function_returns_string: Pro 395.21 ▲15.7% (341.71) 20.06 ▼3.4% (20.77) 29.59 ▼12.6% (33.85) 200=11943
/async_components_demo: Pro 234.03 ▲15.6% (202.37) 35.47 ▼0.8% (35.76) 48.69 ▼6.1% (51.87) 200=7075
/stream_native_metadata: Pro 388.38 ▲15.8% (335.4) 20.07 ▼5.4% (21.22) 30.24 ▼14.0% (35.15) 200=11733
/rsc_native_metadata: Pro 377.73 ▲15.2% (327.86) 20.06 ▼10.8% (22.5) 31.49 ▼13.7% (36.51) 200=11415
/client_side_hello_world: Pro 408.67 ▲13.3% (360.68) 18.91 ▼5.3% (19.97) 28.09 ▼9.4% (31.0) 200=12349
/client_side_hello_world_shared_store_controller: Pro 390.76 ▲15.4% (338.69) 20.14 ▼3.2% (20.8) 31.14 ▼5.9% (33.08) 200=11806
/server_side_hello_world_shared_store: Pro 323.34 ▲11.8% (289.21) 24.88 ▼3.3% (25.73) 37.29 ▼3.4% (38.59) 200=9768
/server_side_hello_world_shared_store_defer: Pro 328.15 ▲12.9% (290.65) 19.38 ▼25.1% (25.88) 31.82 ▼15.5% (37.64) 200=9917
/server_side_hello_world_hooks: Pro 393.89 ▲13.1% (348.31) 19.51 ▼6.5% (20.87) 30.46 ▼14.5% (35.63) 200=11902
/server_side_log_throw: Pro 392.56 ▲13.8% (344.93) 20.13 ▼6.9% (21.62) 29.93 ▼11.5% (33.82) 200=11863
/server_side_log_throw_raise: Pro 745.48 ▲14.1% (653.52) 10.52 ▼6.0% (11.2) 15.43 ▼16.3% (18.43) 3xx=22520
/server_side_hello_world_es5: Pro 393.37 ▲16.5% (337.63) 20.16 ▼7.6% (21.81) 31.59 ▼8.2% (34.41) 200=11887
/server_side_hello_world_with_options: Pro 379.3 ▲14.8% (330.32) 23.19 ▲6.7% (21.74) 31.06 ▼10.1% (34.55) 200=11460
/client_side_manual_render: Pro 415.45 ▲13.9% (364.61) 15.17 ▼20.7% (19.12) 25.62 ▼15.0% (30.13) 200=12560
/react_router: Pro 453.78 ▲14.9% (394.87) 16.1 ▼8.9% (17.67) 29.96 ▲1.2% (29.61) 200=13710
/css_modules_images_fonts_example: Pro 317.67 ▼6.6% (340.08) 18.35 ▼14.0% (21.33) 26.71 ▼20.3% (33.51) 200=9601
/rendered_html: Pro 322.57 ▼6.1% (343.36) 18.1 ▼14.9% (21.28) 29.27 ▼12.8% (33.57) 200=9749
/react_helmet: Pro 382.8 ▲13.9% (336.16) 20.63 ▼5.6% (21.84) 30.84 ▼7.9% (33.47) 200=11573
/image_example: Pro 332.27 ▲2.2% (325.2) 14.19 ▼35.3% (21.92) 20.45 ▼42.4% (35.52) 200=10108
/posts_page: Pro 91.98 ▼87.8% (751.33) 94.82 ▲431.3% (17.85) 124.92 ▲420.1% (24.02) 200=2781

▲/▼ non-zero change vs baseline · 0.0% exact/near-zero match · 🔴 significant regression · 🟢 significant improvement (tracked measures) · (n) = baseline

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Pro (shard 2/2) Benchmark Summary

Benchmark RPS p50(ms) p90(ms) Status
/empty: Pro 1503.64 ▲22.8% (1224.56) 5.29 ▼10.2% (5.89) 7.54 ▼15.9% (8.96) 200=45419
/ssr_shell_error: Pro 423.28 ▲28.1% (330.51) 17.85 ▼17.8% (21.71) 30.31 ▼14.0% (35.25) 200=12789
/ssr_sync_error: Pro 331.46 ▲1.4% (326.92) 17.05 ▼21.7% (21.79) 22.07 ▼40.8% (37.29) 200=10082
/rsc_component_error: Pro 403.15 ▲23.3% (326.98) 19.12 ▼12.7% (21.9) 29.01 ▼18.1% (35.41) 200=12184
/non_existing_stream_react_component: Pro 411.75 ▲20.6% (341.38) 13.36 ▼35.8% (20.8) 25.73 ▼24.8% (34.2) 200=12444
/server_side_redux_app_cached: Pro 379.34 ▲3.9% (365.18) 15.17 ▼25.7% (20.41) 26.0 ▼18.0% (31.7) 200=11476
/loadable: Pro 308.83 ▲3.1% (299.52) 18.44 ▼23.8% (24.18) 30.64 ▼14.1% (35.65) 200=9334
/apollo_graphql: Pro 157.73 ▲12.8% (139.79) 49.0 ▼3.6% (50.84) 72.61 ▼16.7% (87.15) 200=4770
/console_logs_in_async_server: Pro 3.16 ▼1.2% (3.2) 2120.98 ▼0.1% (2122.4) 2147.86 ▼2.5% (2203.26) 200=108
/stream_error_demo: Pro 340.45 ▲5.2% (323.61) 16.44 ▼23.7% (21.56) 21.48 ▼40.7% (36.25) 200=10355
/stream_async_components: Pro 410.54 ▲24.8% (328.92) 18.51 ▼15.7% (21.95) 31.08 ▼15.4% (36.72) 200=12405
/rsc_posts_page_over_http: Pro 381.59 ▲16.8% (326.63) 20.16 ▼10.1% (22.43) 30.4 ▼14.1% (35.4) 200=11530
/rsc_echo_props: Pro 252.12 ▲9.9% (229.33) 31.34 ▼2.1% (32.02) 45.33 ▼6.7% (48.6) 200=7621
/async_on_server_sync_on_client_client_render: Pro 340.39 ▼3.4% (352.55) 17.02 ▼16.5% (20.38) 35.25 ▲4.7% (33.68) 200=10286
/server_router_client_render: Pro 405.15 ▲16.0% (349.19) 18.91 ▼7.2% (20.37) 30.35 ▼6.8% (32.55) 200=12238
/unwrapped_rsc_route_stream_render: Pro 409.19 ▲23.0% (332.62) 17.6 ▼14.7% (20.63) 29.81 ▼16.6% (35.75) 200=12373
/async_render_function_returns_component: Pro 351.2 ▲6.6% (329.37) 16.33 ▼23.9% (21.47) 26.8 ▼23.0% (34.82) 200=10613
/native_metadata: Pro 397.58 ▲18.8% (334.61) 19.54 ▼12.2% (22.25) 28.87 ▼19.0% (35.66) 200=12014
/hybrid_metadata_streaming: Pro 373.88 ▲13.1% (330.66) 12.38 ▼42.6% (21.59) 18.18 ▼50.6% (36.81) 200=11375
/cache_demo: Pro 343.85 ▲6.2% (323.83) 16.54 ▼25.5% (22.21) 40.21 ▲6.2% (37.87) 200=10391
/client_side_hello_world_shared_store: Pro 409.67 ▲23.7% (331.17) 20.86 ▼3.2% (21.54) 28.66 ▼14.5% (33.51) 200=12376
/client_side_hello_world_shared_store_defer: Pro 415.07 ▲25.1% (331.71) 18.37 ▼17.6% (22.29) 29.66 ▼13.0% (34.1) 200=12540
/server_side_hello_world_shared_store_controller: Pro 324.82 ▲17.5% (276.52) 23.96 ▼8.1% (26.06) 35.75 ▼11.2% (40.24) 200=9820
/server_side_hello_world: Pro 398.56 ▲23.5% (322.76) 19.0 ▼14.5% (22.21) 29.61 ▼17.2% (35.77) 200=12043
/client_side_log_throw: Pro 386.61 ▲5.4% (366.73) 12.12 ▼39.2% (19.95) 17.65 ▼41.9% (30.37) 200=11758
/server_side_log_throw_plain_js: Pro 377.3 ▲1.5% (371.89) 15.23 ▼21.3% (19.35) 41.51 ▲32.0% (31.44) 200=11400
/server_side_log_throw_raise_invoker: Pro 499.18 ▲23.7% (403.48) 15.45 ▼11.3% (17.41) 25.21 ▼9.7% (27.9) 200=14983
/server_side_redux_app: Pro 400.83 ▲23.3% (325.01) 19.41 ▼10.9% (21.79) 28.53 ▼17.8% (34.71) 200=12113
/server_side_redux_app_cached: Pro 448.85 ▲22.9% (365.18) 17.16 ▼15.9% (20.41) 28.49 ▼10.1% (31.7) 200=13563
/render_js: Pro 445.25 ▲20.9% (368.35) 17.23 ▼11.8% (19.53) 25.96 ▼17.9% (31.62) 200=13451
/pure_component: Pro 415.68 ▲25.1% (332.4) 18.37 ▼16.3% (21.94) 30.39 ▼17.0% (36.63) 200=12560
/turbolinks_cache_disabled: Pro 373.27 ▲2.7% (363.35) 15.3 ▼23.9% (20.11) 50.16 ▲58.4% (31.67) 200=11279
/xhr_refresh: Pro 275.06 ▼1.2% (278.28) 20.79 ▼20.9% (26.27) 53.16 ▲36.9% (38.83) 200=8312
/broken_app: Pro 407.03 ▲18.0% (345.05) 13.51 ▼37.4% (21.58) 26.33 ▼23.4% (34.36) 200=12383
/server_render_with_timeout: Pro 413.08 ▲18.9% (347.56) 18.86 ▼13.4% (21.78) 27.41 ▼18.2% (33.49) 200=12481

▲/▼ non-zero change vs baseline · 0.0% exact/near-zero match · 🔴 significant regression · 🟢 significant improvement (tracked measures) · (n) = baseline

@justin808 justin808 merged commit d39a95c into main Jun 5, 2026
42 checks passed
@justin808 justin808 deleted the jg-codex/follow-up-3640-3646-rsc-generator branch June 5, 2026 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow up RSC rspack generator polish from #3590 Follow up RSC generator install messaging nits from #3590

1 participant