Skip to content

Fix Pro RSC manifests for Rspack builds#3385

Closed
justin808 wants to merge 47 commits into
mainfrom
jg-conductor/fix-issue-1828-comment
Closed

Fix Pro RSC manifests for Rspack builds#3385
justin808 wants to merge 47 commits into
mainfrom
jg-conductor/fix-issue-1828-comment

Conversation

@justin808

@justin808 justin808 commented May 24, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #1828. Generated Rspack configs were applying webpack-only RSCWebpackPlugin APIs to the Rspack compiler, so Pro RSC client/server manifests were never emitted and the build crashed. This routes Rspack RSC manifest generation through a new generated rscManifestPlugin.js helper while leaving webpack behavior unchanged.

What changed

New generated helper — config/(webpack|rspack)/rscManifestPlugin.js exposing addRSCManifestPlugin(bundlerConfig, { isServer, clientReferences }):

  • Rspack path (config.assets_bundler === 'rspack'): scans Shakapacker source paths for 'use client' modules at config-evaluation time, injects a synthetic rsc-client-references entry, and emits react-client-manifest.json / react-server-client-manifest.json via a pure-Rspack RspackRSCManifestPlugin that uses only public compilation hooks.
  • webpack path: lazy-requires react-on-rails-rsc/WebpackPlugin and delegates discovery to RSCWebpackPlugin's module graph. The lazy require keeps Rspack-only projects from pulling webpack in at config-load time (previously a MODULE_NOT_FOUND).

Generators scaffold the helper and wire clientWebpackConfig.js / serverWebpackConfig.js through addRSCManifestPlugin (server still skips when rscBundle is true). Existing new RSCWebpackPlugin(...) setups are migrated in place, with rollback + a clear warning for ambiguous or partial configs (mixed server/client calls in one file, custom plugins.push(...) shapes, custom configureServer signatures) so the helper is never left half-applied.

Manifest shape mirrors react-server-dom-webpack/plugin: alternating [chunkId, filename, ...] pairs, accumulated across chunk groups for shared modules. Non-JS and *.hot-update.js files are skipped within a chunk's file list (the original bug aborted the scan before a later valid .js file).

Synthetic client-reference entry is shared by client and server manifest builds. Server builds get a fixed rsc-client-references.js filename so LimitChunkCountPlugin / fixed output.filename settings don't fold client-only modules into server-bundle.js; client builds keep the cache-busted template.

Docsdocs/pro/react-server-components/rspack-compatibility.md documents the Rspack-first manifest behavior and known limitations: new 'use client' files may need a dev-server restart in watch mode; publicPath: 'auto' / CDN prefixes; wildcard name: '*' named-export tracking.

Tests

  • react_on_rails/spec/react_on_rails/generators/rsc_generator_spec.rb + install_generator_spec.rb — assert helper scaffolding, config wiring, and migration/rollback behavior.
  • react_on_rails/spec/dummy/tests/rscManifestPlugin.test.js — Jest unit tests that load the ERB-free template directly and lock in the tricky pure-logic branches: glob→RegExp translation (brace alternation, bracket expressions), the 'use client' directive scanner (including multi-line trailing comments), collectChunkGroupPairs (the Rspack support for RSC #1828 break→continue regression), chunk-pair merge, and crossOriginLoading normalization.

Test plan

  • bundle exec rspec spec/react_on_rails/generators/rsc_generator_spec.rb — 211 examples, 0 failures
  • bundle exec rspec spec/react_on_rails/generators/install_generator_spec.rb — 457 examples, 0 failures
  • cd react_on_rails/spec/dummy && npx jest ./tests/rscManifestPlugin.test.js — 60 tests, 0 failures
  • node --check --input-type=commonjs < .../rscManifestPlugin.js.tt
  • pnpm exec prettier --check on the template and the Jest test
  • (cd react_on_rails && bundle exec rubocop) — no offenses

Pull Request checklist

  • Add/update test to cover these changes
  • Update documentation
  • Update CHANGELOG file

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a generated rscManifestPlugin.js helper and rewrites generator, template, and migration logic so Rspack builds emit RSC manifests (react-client-manifest.json, react-server-client-manifest.json) without calling webpack-only plugin APIs; tests and docs are updated.

Changes

Rspack RSC Manifest Plugin and Integration

Layer / File(s) Summary
RSC manifest plugin implementation
react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/rscManifestPlugin.js.tt
New template providing "use client" scanning, client-reference collection, entry injection, RspackRSCManifestPlugin that emits manifest JSON during Rspack asset processing, plus addRSCManifestPlugin and entry helper exports.
Base generator template mapping & creation
react_on_rails/lib/generators/react_on_rails/base_generator.rb, react_on_rails/lib/generators/react_on_rails/rsc_setup.rb
Adds rscManifestPlugin.js to managed templates, creates config/webpack/rscManifestPlugin.js during setup_rsc, and includes it only when use_rsc?.
Generator orchestration & plugin file usage
react_on_rails/lib/generators/react_on_rails/rsc_setup.rb, react_on_rails/lib/generators/react_on_rails/rsc/USAGE
Orchestrates creation and wiring of the manifest helper, updates USAGE wording and adds module-level helper/import constants.
Webpack / Rspack config templates use helper
react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt, .../serverWebpackConfig.js.tt, .../rscWebpackConfig.js.tt
Client/server templates now import/invoke addRSCManifestPlugin instead of directly instantiating RSCWebpackPlugin; server config uses rscBundle gating for manifest generation.
Generator config transform logic
react_on_rails/lib/generators/react_on_rails/rsc_setup.rb
Transform methods updated to migrate existing RSCWebpackPlugin usage to addRSCManifestPlugin, ensure imports, add rscBundle = false to configureServer, inject conditional helper invocation, and support rollback if anchors are missing.
Client references parsing & migration helpers
react_on_rails/lib/generators/react_on_rails/rsc_setup/client_references.rb
Improve detection/parsing of RSCWebpackPlugin calls (new matchers, call-end computation), add plugin_pending: flag, and update user-facing messages for migration/manual steps.
Spec updates & runtime coverage
react_on_rails/spec/react_on_rails/generators/*
Generator and install specs updated to expect addRSCManifestPlugin / ./rscManifestPlugin; add migration tests rewriting multiline plugin calls; expand Rspack runtime tests to assert RspackRSCManifestPlugin and conditional manifest gating.
Docs and changelog
CHANGELOG.md, docs/pro/react-server-components/rspack-compatibility.md, react_on_rails/lib/generators/react_on_rails/rsc/USAGE
Add Pro changelog entry; update Rspack compatibility doc to describe generated manifest helper, testing checklist (require both manifest files and no compilation errors), known limitations, and related resources; update generator USAGE.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • AbanoubGhadban
  • alexeyr-ci2

🐰 A helper hops in, ears alert and bright,
I sniff "use client" by day and night,
Rspack sings manifests, client and server too,
no webpack-only tangles to undo.
Hooray — small hops made this work new.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.71% 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
Title check ✅ Passed The title 'Fix Pro RSC manifests for Rspack builds' is clear, concise, and directly describes the main change: fixing React Server Components manifest generation specifically for Rspack builds.
Linked Issues check ✅ Passed The PR comprehensively addresses all objectives from #1828: researches and implements Rspack compatibility for RSC, determines and implements a manifest-generation solution (rscManifestPlugin.js), and delivers manifest generation for rspack-based projects with webpack fallback.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing Rspack RSC support: manifest plugin implementation, generator updates, config templates, migration logic, tests, and documentation—with no unrelated modifications detected.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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-conductor/fix-issue-1828-comment

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.

Comment thread react_on_rails/lib/generators/react_on_rails/rsc_setup.rb
Comment thread react_on_rails/lib/generators/react_on_rails/rsc_setup.rb
@greptile-apps

greptile-apps Bot commented May 24, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes Rspack + RSC compatibility by introducing rscManifestPlugin.js — a new generated helper that replaces direct use of RSCWebpackPlugin (a webpack-only API) in Rspack configurations, and updates the generator and its migration logic to wire it in for both new and existing projects.

  • rscManifestPlugin.js.tt: The template implements addRSCManifestPlugin, which dispatches to the original RSCWebpackPlugin for webpack builds and, for Rspack, walks the Shakapacker source paths for 'use client' files at config-eval time, injects them into the bundle entry, and emits react-client-manifest.json / react-server-client-manifest.json via Rspack's public processAssets hook.
  • rsc_setup.rb migration: add_or_replace_rsc_manifest_helper_import handles both fresh installs (no existing RSC wiring) and existing configs that still reference RSCWebpackPlugin, replacing the import and plugin call in both serverWebpackConfig.js and clientWebpackConfig.js using content-based branching.
  • Generator + specs: base_generator.rb conditionally emits rscManifestPlugin.js when RSC is enabled; generator specs are updated to assert the new helper names and a new Rspack-specific test suite verifies the plugin file is created and RSCWebpackPlugin is absent from Rspack configs.

Confidence Score: 3/5

The Rspack manifest path has a concrete bug in how publicPath:'auto' is handled that would silently emit a broken manifest prefix in any project using that setting.

The plugin template has a concrete defect in publicPath handling and silently misses client components in files that start with JS comments — both issues affect the correctness of the emitted manifests in real-world configurations.

react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/rscManifestPlugin.js.tt — specifically the publicPath handling on line 216 and the hasUseClientDirective implementation on lines 33–45.

Important Files Changed

Filename Overview
react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/rscManifestPlugin.js.tt New Rspack-compatible RSC manifest plugin template; has a publicPath:'auto' handling bug that would corrupt the manifest prefix, and silently misses 'use client' files that begin with JS comments
react_on_rails/lib/generators/react_on_rails/rsc_setup.rb Adds migration logic to replace legacy RSCWebpackPlugin wiring with the new helper; handles both fresh installs and existing configs with a content-based branch; logic is sound
react_on_rails/lib/generators/react_on_rails/base_generator.rb Conditionally emits rscManifestPlugin.js to the target config directory when use_rsc? is true; change is minimal and correct
react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt Replaces RSCWebpackPlugin instantiation with addRSCManifestPlugin helper call; straightforward template update
react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt Replaces RSCWebpackPlugin instantiation with addRSCManifestPlugin helper call; straightforward template update
react_on_rails/spec/react_on_rails/generators/rsc_generator_spec.rb Updated expectations to match new helper names; adds new tests asserting the manifest plugin file is created and that RSCWebpackPlugin is absent from Rspack configs
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb Test descriptions and assertions updated to reflect new helper-based manifest wiring; no logic gaps

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[addRSCManifestPlugin called\nfrom client/serverWebpackConfig.js] --> B{config.assets_bundler\n=== 'rspack'?}

    B -- No/webpack --> C[new RSCWebpackPlugin\nfrom react-on-rails-rsc]
    C --> D[Webpack compiler hooks\ngenerate manifests]

    B -- Yes/rspack --> E[collectClientReferenceFiles\nwalk source_path at config time]
    E --> F[Scan each .js/.ts/.jsx/.tsx\nfor 'use client' directive]
    F --> G[addClientReferencesToEntry\nadd client ref files to bundle entry]
    G --> H[new RspackRSCManifestPlugin\npushed to config.plugins]

    H --> I[compiler.hooks.thisCompilation]
    I --> J[processAssets REPORT stage\niterate compilation.modules]
    J --> K{module.resource in\nclientReferenceSet?}
    K -- Yes --> L[Record: id, chunks: empty, name '*'\nkeyed by file:// URL]
    K -- No --> M[Skip]
    L --> N[emitAsset\nreact-client-manifest.json\nor react-server-client-manifest.json]
Loading

Reviews (1): Last reviewed commit: "Generate Rspack RSC manifests without we..." | Re-trigger Greptile

@justin808 justin808 force-pushed the jg-conductor/fix-issue-1828-comment branch from e88362f to ab27cc0 Compare May 27, 2026 02:33

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab27cc0d57

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread react_on_rails/lib/generators/react_on_rails/rsc_setup.rb Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/rscManifestPlugin.js.tt`:
- Around line 198-202: The manifest currently writes empty chunks for each
module (filePathToModuleMetadata[...] = { id: moduleId, chunks: [], name: '*'
}), which causes client chunk filenames to be lost; change the code that builds
filePathToModuleMetadata so it collects the emitted client chunk filename(s) for
the given module and stores them in chunks. Concretely, for each module
(variable module / moduleId) use the compilation's chunk graph (e.g.,
compilation.chunkGraph or compilation.moduleGraph helpers) to enumerate chunks
for that module (chunkGraph.getModuleChunksIterable(module) or equivalent), then
map each chunk to its emitted filename(s) (chunk.files or
compilation.getAssetPath/compilation.getPath calls) and include those filenames
(including their real extensions like .js or .mjs) in the chunks array; leave
name as '*' and keep id as moduleId. Ensure you handle multiple files per chunk
and deduplicate filenames before assigning to filePathToModuleMetadata.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2428d0ea-e2e0-4b08-b14f-f432e6077744

📥 Commits

Reviewing files that changed from the base of the PR and between 600500a and ab27cc0.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • docs/pro/react-server-components/rspack-compatibility.md
  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
  • react_on_rails/lib/generators/react_on_rails/rsc/USAGE
  • react_on_rails/lib/generators/react_on_rails/rsc_setup.rb
  • react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt
  • react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/rscManifestPlugin.js.tt
  • react_on_rails/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt
  • react_on_rails/lib/generators/react_on_rails/templates/rsc/base/config/webpack/rscWebpackConfig.js.tt
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
  • react_on_rails/spec/react_on_rails/generators/rsc_generator_spec.rb

@justin808 justin808 changed the title Fix Rspack RSC manifest generation Fix Pro RSC manifest generation for Rspack May 27, 2026
@claude

claude Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Code Review

Overview

This PR fixes #1828 by introducing rscManifestPlugin.js — a generated helper that routes RSC manifest generation through Rspack-compatible public APIs instead of applying react-on-rails-rsc/WebpackPlugin (which uses webpack-internal APIs) directly to the Rspack compiler. The approach is sound and the overall structure is clean.


Critical Issues

1. publicPath: 'auto' is not handled — prefix will be the literal string 'auto'

prefix: compilation.outputOptions.publicPath || '',

When output.publicPath is 'auto', the string 'auto' is truthy, so 'auto' || '' evaluates to 'auto'. The PR description explicitly claims this is handled ("treating output.publicPath: 'auto' as an empty manifest prefix"), but the code doesn't implement it.

Fix:

const rawPath = compilation.outputOptions.publicPath;
const prefix = !rawPath || rawPath === 'auto' ? '' : rawPath;

2. chunks: [] is always empty — PR description contradicts the implementation

The PR description says "writing emitted chunk filenames into react-client-manifest.json" was addressed, but in recordModule the chunks array is hard-coded to [] and never populated with actual emitted chunk filenames. The RSC runtime uses the chunks array to know which JS bundles to fetch for a client component boundary; leaving it empty may prevent the runtime from loading those modules.

The webpack RSCWebpackPlugin populates chunks by querying chunk graph iterables and mapping each chunk to its emitted filename. The Rspack plugin needs equivalent logic.


3. hasUseClientDirective does not skip JS comments — PR description contradicts the code

The PR description says "detecting 'use client' after leading JavaScript comments" was addressed, but the current implementation only walks through consecutive string-literal expressions. It returns false immediately on the first non-string-literal token — including // line comments and /* block comments */.

A file like:

// @license MIT
'use client';

...would be missed by the scanner, so that client component would be excluded from the manifests.


Non-Critical Issues

4. Webpack migration path silently drops user-configured clientReferences

options at the call sites is always { isServer: true } or { isServer: false }. The previously generated scoped rscClientReferences object is no longer passed to RSCWebpackPlugin. Any webpack user who had customised the scan scope will silently lose that configuration after running the generator. If relying on the plugin's own default is intentional, it should be documented.


5. Symlinked directories are silently skipped

Dirent.isDirectory() returns false for symbolic links to directories. Apps that symlink subdirectories under source_path (monorepos, component libraries) will silently miss all client references under those symlinks. Consider adding a fs.statSync follow-symlink check alongside entry.isDirectory().


6. addRequestsToEntry object branch mutates in place while other branches return new values

The object branch calls entryValue[entryName] = ... (mutation + same reference returned), while string and array branches return a new value without mutation. This is internally consistent for the current callers but surprising for future readers. A spread-based rewrite would make all branches consistently immutable.


Positive Notes

  • The routing design (delegate to RSCWebpackPlugin for webpack, use the custom Rspack plugin otherwise) is clean and makes the generated file a single source of truth for both bundlers.
  • Removing the rollback machinery and multi-stage prepare_rsc_plugin_imports flow simplifies rsc_setup.rb significantly.
  • Generator idempotency guards (return if content.include?("addRSCManifestPlugin")) are correct.
  • Concatenated-module handling in recordModule is a good defensive addition.
  • Documentation and changelog entries are clear and accurate.

Test Coverage Gap

Existing specs verify string presence in generated files but do not cover:

  • hasUseClientDirective with leading comments
  • publicPath: 'auto' producing an empty prefix
  • chunks being populated in the emitted manifest JSON

Unit tests for the JS helper (or additional generator spec assertions on the emitted manifest structure) would make these regressions much easier to catch.

@justin808 justin808 force-pushed the jg-conductor/fix-issue-1828-comment branch from ab27cc0 to ee0f7b3 Compare May 27, 2026 22:08
@justin808 justin808 changed the title Fix Pro RSC manifest generation for Rspack Fix Rspack RSC manifest generation for Pro RSC May 27, 2026
@justin808

Copy link
Copy Markdown
Member Author

Mattered

  • Addressed Rspack manifest correctness items: clientReferences are preserved on the webpack delegation path, multiline RSCWebpackPlugin calls migrate to addRSCManifestPlugin, leading JS comments are skipped before detecting 'use client' directives, emitted chunk filenames are written into manifest entries, and publicPath: auto becomes an empty manifest prefix.
  • Addressed review optional items inline: object-form entries are now updated immutably, and symlinked client-reference directories are followed with a realpath cycle guard.
  • Discussion item: the static scan in Rspack watch mode is documented as a current limitation. Advice: keep this PR scoped as a manifest-generation fix; if live discovery of newly added 'use client' files during rspack serve becomes important, implement compiler-hook rescanning as a follow-up so it can be designed and tested independently.

Optional

  • Addressed inline: immutable object entry updates and symlinked directory traversal.

Skipped

  • No actionable review comments were skipped. Duplicate findings were resolved through the same underlying fixes.

Scan window: full PR history because no prior <!-- address-review-summary --> marker existed. Future full-PR scans should start after this comment unless check all reviews is requested.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee0f7b356f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread react_on_rails/lib/generators/react_on_rails/rsc_setup.rb
@claude

claude Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Code Review: Fix Rspack RSC Manifest Generation

Overview

This PR correctly identifies the root cause of issue 1828: applying webpack-internal plugin APIs to the Rspack compiler. The solution (a thin rscManifestPlugin.js helper that delegates to RSCWebpackPlugin on webpack and uses Rspack public compilation hooks otherwise) is the right architectural split. The generator migration path (multiline call handling, import replacement, cycle guard, immutable entry spreading) is comprehensive and well-tested.

Strengths

  • Clean single-dispatch in addRSCManifestPlugin: webpack path is unchanged, Rspack path is Rspack-safe.
  • RspackRSCManifestPlugin handles concatenated modules correctly via module.modules traversal.
  • BOM removal and comment-skipping in hasUseClientDirective are proper edge-case handling.
  • Symlink cycle guard with visitedDirectories uses realpathSync for identity -- correct approach.
  • Generator migration tests are thorough, including the new multiline plugin call cases.
  • appendImports spreads object-form entries immutably -- no aliasing issues.

Issues

MEDIUM 1: Partial state after failed migration (no rollback)

In migrate_rsc_webpack_plugin_to_manifest_helper, update_existing_rsc_webpack_config may successfully add the rscClientReferences scoping block and inject clientReferences: into some plugin calls -- then rsc_manifest_plugin_sections_ready? returns false and the method returns early with no rollback. The file is left in a modified-but-not-fully-migrated state (old RSCWebpackPlugin push calls remain). Subsequent generator runs re-enter the migration branch and get stuck: rscClientReferences is already present so it cannot be re-inserted, but the sections still pass rsc_webpack_plugin_invocation?.

Suggested fix: capture original_content before calling update_existing_rsc_webpack_config and call rollback_incomplete_rsc_manifest_setup when rsc_manifest_plugin_sections_ready? returns false.

MEDIUM 2: normalizeClientReferences fallback scans from CWD

When config.source_path is blank and config.additional_paths is empty, directories falls back to ['.'], triggering a recursive walk of the entire project. DEFAULT_EXCLUDED_DIRECTORIES catches common Rails directories by name but only at the top level -- nested directories with those names are still visited. config.source_path is always set by shakapacker in practice, but a defensive fallback (warn and return []) would be safer than silently scanning from root.

LOW 3: Redundant existsSync/statSync in collectFile on the walk path

walk already confirms an entry is not a directory via isDirectoryEntry before calling collectFile, so the existsSync + statSync guard inside collectFile is only necessary on the direct-string-reference path. Minor performance nit for large source trees.

LOW 4: Silent manifest miss when module.resource is absent

Virtual/synthetic modules correctly get filtered out. But if a 'use client' file is processed by a loader chain that drops the resource property from the module object, it is silently absent from the manifest. A dev-mode warning when a file from clientReferenceSet has no corresponding manifest entry after iterating compilation.modules would help diagnose this class of problem.

LOW 5: name: '*' is hardcoded

Every client reference is recorded as name: '*' (all-exports). This matches RSCWebpackPlugin convention and is fine for namespace imports, but worth a comment in the file since it affects how the RSC runtime resolves named re-exports across chunks.

LOW 6: Test assertions check string presence only

Tests like expect(content).to include('class RspackRSCManifestPlugin') verify the file was copied, not that the plugin works against a real Rspack build. The PR acknowledges this -- flagging for the integration test checklist.

Minor wording

In warn_missing_rsc_plugin_target (client_references.rb), the message still reads "no plugin options with isServer: ..." -- the surrounding context now refers to addRSCManifestPlugin, so the option description should match the helper interface rather than RSCWebpackPlugin's.

Summary

The core fix is sound and the test surface is good. The two medium issues (partial migration state on edge-case failure, CWD fallback scan) are worth addressing before merge. The low items can be follow-ups if you prefer to keep this PR focused on the crash fix.

Comment thread react_on_rails/lib/generators/react_on_rails/rsc_setup.rb Outdated
Comment on lines +632 to +638
if (crossOrigin === 'use-credentials' || crossOrigin === 'anonymous') {
return { value: crossOrigin };
}

return {
value: 'anonymous',
warning:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

'same-origin' is a valid crossOriginLoading string that Rspack accepts — it maps to the HTML crossorigin="use-credentials" equivalent when the request is same-origin. Falling back silently to 'anonymous' (even with a warning) would weaken credentials isolation for apps that deliberately configure this value.

Consider allowing it through:

Suggested change
if (crossOrigin === 'use-credentials' || crossOrigin === 'anonymous') {
return { value: crossOrigin };
}
return {
value: 'anonymous',
warning:
if (crossOrigin === 'use-credentials' || crossOrigin === 'anonymous' || crossOrigin === 'same-origin') {
return { value: crossOrigin };
}

Or at minimum add 'same-origin' to the normalizeCrossOrigin test matrix so the behaviour is explicit.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks, but I (Claude Code) don't think this one holds up, so I've left the code as-is — flagging for a human decision.

'same-origin' is not a valid value for webpack/Rspack output.crossOriginLoading. The bundler schema accepts only false | 'anonymous' | 'use-credentials'. That value also feeds the manifest's crossOrigin field, which becomes the HTML crossorigin attribute on the <script>/preload tags the RSC runtime injects — and the crossorigin attribute only accepts anonymous, use-credentials, or the empty string (≡ anonymous). same-origin is valid for the Fetch API (credentials: 'same-origin', Request.mode), which I think is the source of the mix-up, but not for crossOriginLoading or crossorigin.

So allowing 'same-origin' through would emit an invalid crossorigin attribute; the current behavior (warn once, fall back to the safe 'anonymous') is the correct guard for any unsupported value. The existing normalizeCrossOrigin test matrix already covers the anonymous/use-credentials pass-through and the unsupported-string fallback.

Happy to make the warning message enumerate the accepted values if that'd be useful, but I'd avoid passing same-origin into the manifest. Leaving this thread open for you to resolve if you agree.

Comment thread react_on_rails/spec/dummy/tests/rscManifestPlugin.test.js
Comment thread react_on_rails/spec/dummy/tests/rscManifestPlugin.test.js Outdated
justin808 and others added 2 commits May 29, 2026 11:19
Commit a582c32 reworded the mergeChunkPairsInPlace comment from
"`existing` is always a `.slice()` copy" to "first-write path passes a
`.slice()` copy" but left the rsc_generator_spec assertion checking the
old wording, breaking the generators CI job. Update the assertion to the
current comment text, preserving the intent (verifying the .slice()
first-write invariant is documented).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Addresses the latest PR #3385 review comments:

- hasUseClientDirective: the trailing block-comment alternative used
  `.*?`, which does not match newlines, so a directive followed by a
  multi-line block comment (`'use client' /* a\nb */;`) was not detected.
  Switch to `[\s\S]*?` and add a multi-line test case.
- Export collectChunkGroupPairs to the test harness and add regression
  tests for the issue #1828 break->continue fix (a `.css`/`.hot-update.js`
  file preceding the `.js` file in chunk.files no longer suppresses the
  chunk pair), plus null-id and first-JS-only coverage.
- Replace the dead `#issuecomment-` anchor in the test header (the URL
  only resolves post-merge) with the plain PR link.

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

claude Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Code Review

Overview

This PR correctly solves Issue #1828: generated Rspack configs were applying RSCWebpackPlugin (which uses webpack-internal compilation APIs) directly to the Rspack compiler, causing build crashes. The fix introduces rscManifestPlugin.js, a generated helper that routes manifest generation through Rspack's public processAssets hook while preserving the existing webpack code path via a lazy require.

The approach is sound. Rspack v2 exposes enough of the compilation API (chunkGroups, chunkGraph, emitAsset) that a pure-Rspack manifest plugin is achievable without forking into webpack internals.


Strengths

  • Correct fix for Rspack support for RSC #1828: The collectChunkGroupPairs break to continue regression is well-documented and the Jest test locks it in with a dedicated case (CSS file before JS file in chunk.files).
  • Rollback safety: The generator rolls back partial writes for every failure path (missing anchor, unrecognized configureServer signature, failed plugin push replacement). The new rollback_incomplete_rsc_manifest_setup is cleaner than the previous per-codepath variants.
  • Migration guard: migrate_or_block_on_rsc_webpack_plugin always returns true once it detects an existing RSCWebpackPlugin invocation — whether migration succeeds or rolls back. The comment explains why (prevents re-entering fresh setup after an ambiguous partial migration), which is the right design.
  • Test coverage is solid: 60 Jest unit tests covering glob-to-regexp edge cases, the 'use client' scanner (BOM, trailing block/line comments, multi-line block comments), chunk-pair merge deduplication, and crossOriginLoading normalization. Generator RSpec suites cover fresh setup, migration, and rollback paths.
  • Documentation is thorough: All known limitations (watch-mode restart, publicPath: 'auto', wildcard name: '*', native Rspack RSC future path) are documented in rspack-compatibility.md.

Issues and Observations

1. name: '*' may silently break named-export RSC patterns (worth a runtime test)

The recordModule path writes name: '*' for every client reference instead of enumerating named exports the way RSCWebpackPlugin does via compilation.moduleGraph. The RSC runtime uses these manifest entries to resolve specific exports during streaming. If downstream code destructures named exports from a 'use client' module across the server/client boundary, the runtime may fail silently or fall back in unexpected ways — and a unit test won't catch that.

The limitation is correctly documented in both the compatibility doc and the file itself. A follow-up integration test against the Pro Node Renderer with at least one named-export 'use client' component would de-risk this before the GA release.

2. Process-lifetime scan cache can accumulate in long-running harnesses

clientReferenceScanCache is a module-level Map that is never evicted. In normal webpack/rspack runs this holds ~2 entries (one per client/server config). However, test harnesses that require/import the helper many times in the same long-lived Node.js process (e.g., Jest with --runInBand across many test suites) will accumulate entries indefinitely. Not a production concern, but worth noting for CI flakiness if the Jest test suite grows.

3. config.additional_paths reliance on undocumented Shakapacker internals

normalizeClientReferences reads config.additional_paths, which the comment correctly flags as an internal Shakapacker property not in the public API. If Shakapacker removes or renames it, the scan silently narrows to source_path only in dev and throws in production. Consider pinning a Shakapacker version range in the gem dependency or adding a version-check guard that names the minimum tested version.

4. DEFAULT_EXCLUDED_DIRECTORIES does not exclude .git

.git is absent from the exclusion set. In practice this is harmless because CLIENT_REFERENCE_EXTENSIONS filters to JS/TS extensions and .git objects don't use those extensions. But adding .git and .cache would make the exclusion rationale self-documenting and prevent unintended scanning if a project unconventionally stores JS under .git/.

5. Symlink TOCTOU window between config-eval and compilation

clientReferenceSet is built at config-eval time with resolveRealPath, while cachedRealPath in apply() runs at compilation time. If a symlink target changes between config evaluation and compilation (unlikely but possible in Docker volume mounts), the two could resolve to different canonical paths and a real 'use client' module could silently drop out of the manifest. Worth a comment in the constructor to document this assumption.

6. Minor: double file re-read in update_server_webpack_config_for_rsc

In the server path, the file is read from disk twice after writes — once after ensure_rsc_client_references_setup and once after the configureServer signature rewrite. Both are needed for their callers, but this pattern could be reduced by passing updated content through helpers rather than re-reading from disk. Not a correctness issue — just reduces unnecessary disk I/O in generator runs.


Minor Nits

  • rsc_plugin_push_replacement_range uses Regexp.escape(bundler_config_name) with a \z anchor and /m flag — correct anchoring that prevents a partial prefix match.
  • The globToRegExp ** handling correctly emits (?:.*/)? for **/ and .* for trailing **, matching standard glob semantics. Jest tests confirm this.
  • The hasUseClientDirective regex uses [\s\S]*? (not .*?) for the optional trailing block comment, correctly handling multi-line cases like 'use client' /* multi-line */;. The test suite covers this.

Verdict

The implementation is correct and production-quality for its stated scope. The webpack path is unchanged. The Rspack path's name: '*' limitation and watch-mode restart requirement are the only things that could surprise users in production, and both are documented. Ready to merge once the Pro Node Renderer integration verification mentioned in the docs is completed.


const CLIENT_REFERENCE_EXTENSIONS = /\.(?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$/;
const RSC_CLIENT_REFERENCES_ENTRY_NAME = 'rsc-client-references';
const DEFAULT_EXCLUDED_DIRECTORIES = new Set(['node_modules', 'public', 'tmp', 'log', 'storage']);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Consider adding '.git' and '.cache' to this exclusion set:

Suggested change
const DEFAULT_EXCLUDED_DIRECTORIES = new Set(['node_modules', 'public', 'tmp', 'log', 'storage']);
const DEFAULT_EXCLUDED_DIRECTORIES = new Set(['node_modules', 'public', 'tmp', 'log', 'storage', '.git', '.cache']);

.git objects don't have JS/TS extensions so they'd be filtered anyway, but making the exclusion explicit avoids any edge case where a project stores JS under .git/ (e.g., a git hook helper) and it prevents unnecessarily descending into the directory tree to discover that.

// in place, so each module's metadata must own a private chunk-pair copy.
chunks: chunkPairs.slice(),
// Known limitation: all exports are treated as client references.
// Rspack helper does not yet enumerate named exports like RSCWebpackPlugin.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The name: '*' wildcard is documented as a known limitation, but it's worth calling out the failure mode explicitly: if application code does something like:

// Server component
import { MyButton, MyForm } from './components.client';

the RSC runtime may attempt to look up the specific export names (MyButton, MyForm) in the manifest. With name: '*', those lookups could resolve differently depending on how react-server-dom-webpack interprets wildcard entries, potentially causing a silent hydration mismatch rather than a visible error.

Before the GA release, it's worth verifying a named-export 'use client' component against the Pro Node Renderer under Rspack to confirm the runtime either resolves * correctly or produces a clear diagnostic.


class RspackRSCManifestPlugin {
constructor(options, clientReferenceFiles, clientReferenceRequests) {
if (!options || typeof options.isServer !== 'boolean') {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The clientReferenceSet is built here at config-evaluation time using resolveRealPath, while cachedRealPath inside apply() resolves the same paths again at compilation time. In environments where symlink targets change between the two (e.g., Docker volume mounts that swap symlinks during a dev-server session), a 'use client' module could silently drop out of the manifest because the two realpath calls diverge.

This is an unlikely edge case, but a brief comment here would help future readers understand the implicit assumption that symlink targets are stable across the config-eval → compilation lifecycle.

fallback_import_pattern: fallback_import_pattern,
is_server: is_server
)
# Always returns true after seeing an RSCWebpackPlugin invocation so the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The "always true" return contract is correct and the comment explains the reasoning well. One thing worth adding: future callers that want to distinguish a successful migration from a failed rollback cannot do so through this method's return value — they'd need to re-read the file and check for the helper invocation. If that distinction ever becomes necessary (e.g., for reporting), consider returning a symbol (:migrated / :rolled_back / :not_applicable) instead of a boolean, so callers can make informed decisions without another file read.

@claude

claude Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Code Review — Fix Pro RSC manifests for Rspack builds

Overview

This PR introduces a generated rscManifestPlugin.js helper that routes RSC manifest generation through pure-Rspack compilation hooks instead of applying webpack-only RSCWebpackPlugin APIs to the Rspack compiler. The implementation is split across a large JS template (~850 lines), a generator migration layer, and comprehensive Ruby + Jest tests.


Correctness

Core bug fix is correct. The breakcontinue change in collectChunkGroupPairs is exactly the right fix for issue #1828: the old code aborted the file scan on the first non-JS entry (e.g. a .css file), silently dropping the pair for a chunk whose .js file came later. The new code skips non-JS / hot-update entries with continue and only breaks once it records the primary JS file. The Jest regression test locks this in cleanly.

Manifest shape. The alternating [chunkId, filename, ...] format mirrors react-server-dom-webpack/plugin output. The mergeChunkPairsInPlace deduplication is correct and the copy-before-mutate pattern (the .slice() comment) prevents silent aliasing bugs.

Directive scanner. hasUseClientDirective is carefully written — BOM stripping, comment-in-prologue handling, backreference-based quote matching. The multi-line trailing block-comment case is tested and correct.

Generator migration layer. The rollback logic correctly captures original_content before any modifications and restores it on any failure. The migrate_or_block_on_rsc_webpack_plugin always returns true after seeing an RSCWebpackPlugin invocation (even on rollback) to prevent re-entering fresh setup — this is the right defensive move.


Significant Concerns

1. Process-level scan cache is never invalidated

The clientReferenceScanCache Map at the top of the template encodes the context + clientReferences shape but not file contents, so it is correct across multiple config evaluations in the same process. However, a test harness or monorepo build system that evaluates many distinct configs in one long-lived process will accumulate entries indefinitely. The comment acknowledges this but the wording is subtle. Consider adding a clearClientReferenceScanCache export for testing, or calling out the long-lived-process risk more explicitly in the generated file's header comment.

2. config.additional_paths is an undocumented internal Shakapacker API

The fallback (warn + scan source_path only) is the safe degraded path. The concern is that a Shakapacker minor could silently rename the property, narrowing the scan scope without any build error. Consider a dedicated test that asserts the key is accessed so a Shakapacker upgrade that removes it produces a clear failure rather than a silent coverage gap.

3. Async-wrapping a sync entry function defers errors

When bundlerConfig.entry is already a function, the helper wraps it in an async wrapper. The comment acknowledges that a synchronously-throwing entry factory now defers its error to compilation start rather than config-parse time. This is the correct tradeoff (webpack 5 and Rspack both normalize sync/async entry factories), but a user whose sync entry factory throws a config-time error (e.g. a missing env variable) will see it later with a different call stack. Worth a brief doc note so users know where to look.

4. rollback_incomplete_rsc_manifest_setup bypasses Thor's write mechanism

The method calls File.write directly rather than going through Thor's file collision/conflict pipeline. It does check :pretend/:skip first, and this is the same pattern as the code it replaces. A comment noting the intentional bypass would help future contributors.


Minor Issues

5. Redundant variable alias in collectStringReferenceconst absoluteGlobPattern = absolutePath; is used exactly once and could be inlined.

6. NEVER_MATCH_PATTERN sentinel deserves a comment/(?!)/ is an elegant impossibly-satisfied lookahead, but a one-line comment explaining why it is used (vs. a simpler-looking alternative with different semantics) would help future readers.


Test Coverage

Coverage is excellent: 60 Jest unit tests lock in glob translation, bracket expressions, directive scanner edge cases, chunk-pair merge, and crossOrigin normalization. Generator specs cover fresh install, migration from RSCWebpackPlugin, rollback, trailing comments, multiline calls, shorthand/quoted options, custom configureServer signatures, and the "import without invocation" edge case. The breakcontinue regression is explicitly documented and tested.

One gap: there is no integration test that builds a small Rspack project and verifies the emitted manifest JSON shape. This is acknowledged in the docs ("runtime verification is still in progress") and is acceptable for an experimental feature.


Summary

The core logic is sound, the fix for #1828 is correct, and the test coverage is unusually thorough for a generator change. The main concerns are the never-invalidated process cache (low risk, documentation gap), the config.additional_paths internal API dependency (medium risk for future Shakapacker upgrades), and the async entry-wrapping error-deferral behavior (low risk, documentation gap). None of these block the fix.

// dev-server restart"). In normal config evaluation this Map holds only a couple of
// entries; it is never invalidated, so a harness that evaluates many distinct configs
// in one long-lived process would accumulate entries.
const clientReferenceScanCache = new Map();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The cache is never invalidated and the comment documents this intentionally. One edge case worth noting: a test harness (or Jest --runInBand suite) that exercises multiple distinct clientReferences shapes in a single long-lived process will accumulate entries forever. Consider exporting a clearClientReferenceScanCache function so test code can reset between cases, or at minimum add a brief note in the header comment calling out the long-lived-process risk for harness authors.

const DEFAULT_EXCLUDED_DIRECTORIES = new Set(['node_modules', 'public', 'tmp', 'log', 'storage']);
const GLOB_MAGIC_PATTERN = /[*?\[\]{}]/;
// Empty negative lookahead is impossible to satisfy, so this rejects every candidate.
const NEVER_MATCH_PATTERN = /(?!)/;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Clever sentinel — a zero-width negative lookahead that is impossible to satisfy, so every test() call returns false. Worth a one-line comment so a future reader does not simplify it to something like /a^/ or /$a/ which are subtly different (both reject all inputs, but they pollute RegExp.lastIndex differently under g/y flags, and /(?!)/ is canonically the "always-fails" pattern). Example:

Suggested change
const NEVER_MATCH_PATTERN = /(?!)/;
// /(?!)/ is a zero-width negative lookahead that can never be satisfied — every test() returns false.
const NEVER_MATCH_PATTERN = /(?!)/;

// documented public API). Verified against Shakapacker 7.x/8.x. If a future
// Shakapacker release removes it, dev builds warn and scan scope narrows to
// `source_path` only. Revisit if Shakapacker exposes an official accessor.
const additionalPaths = config.additional_paths;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

config.additional_paths is correctly flagged as an internal Shakapacker property. The silent-degradation path (warn + fall back to source_path only) is safe, but a future Shakapacker rename would narrow scan scope with no build error. One way to make the breakage more visible: add a generator-spec assertion that config.additional_paths is accessed (e.g. via a spy or by checking the warn message is not present in a Shakapacker stub that still exposes the property). That way a Shakapacker upgrade that renames it breaks the test rather than silently shrinking the client-reference scan.

}

const baseDirectory = globBaseDirectory(context, reference);
const absoluteGlobPattern = absolutePath;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

absoluteGlobPattern is an alias for absolutePath used only on the next line. Inlining it removes a mental-mapping step:

Suggested change
const absoluteGlobPattern = absolutePath;
const relativePattern = `./${toPosixPath(path.relative(baseDirectory, absolutePath))}`;

// factories at build time.
// If the original factory throws synchronously, that error is deferred until
// compilation starts rather than surfacing at config-parse time.
bundlerConfig.entry = async (...args) => addRequestsToEntry(await entry(...args));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The comment correctly notes that a synchronously-throwing entry factory now defers its error to compilation start rather than config-parse time. One practical consequence: if a user's entry factory reads a required env variable and throws when it is absent, the error message now appears in the Rspack/webpack compilation output rather than immediately after require('./serverWebpackConfig'). Consider adding a sentence to the known-limitations doc or the inline comment so users have a clear place to look when their entry factory errors appear at an unexpected time.

return if options[:pretend] || options[:skip]

say_status(:revert, config_path, :yellow)
File.write(File.join(destination_root, config_path), original_content)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

File.write bypasses Thor's conflict-detection and --force pipeline. The :pretend/:skip guard above is correct, and this pattern matches the previous rollback_incomplete_new_rsc_plugin_setup implementation. A short comment would help future contributors understand the deliberate bypass — e.g.:

# Use File.write directly (bypassing Thor's conflict pipeline) so the rollback
# always restores the original content regardless of --force or conflict mode.
File.write(File.join(destination_root, config_path), original_content)

@github-actions

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchjg-conductor/fix-issue-1828-comment
Testbedgithub-actions

🚨 4 Alerts

BenchmarkMeasure
Units
ViewBenchmark Result
(Result Δ%)
Lower Boundary
(Limit %)
Upper Boundary
(Limit %)
/broken_app: Corep99_latency
ms x 1e3
📈 plot
🚷 threshold
🚨 alert (🔔)
6.18 x 1e3
(+56.00%)Baseline: 3.96 x 1e3
5.47 x 1e3
(112.95%)

/context_function_return_jsx: Corep90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
30.73
(+49.79%)Baseline: 20.52
26.87
(114.37%)

/css_modules_images_fonts_example: Corerps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
17.56
(-24.27%)Baseline: 23.19
17.90
(101.91%)

/xhr_refresh: Corerps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
9.75
(-20.29%)Baseline: 12.23
10.15
(104.10%)

Click to view all benchmark results
Benchmarkfailed_pct%p50_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p90_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p99_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
rpsBenchmark Result
req/s
(Result Δ%)
Lower Boundary
req/s
(Limit %)
/: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
2,893.29
(+2.93%)Baseline: 2,811.03
3,413.95
(84.75%)
📈 view plot
🚷 view threshold
3,434.92
(-3.30%)Baseline: 3,552.09
4,284.83
(80.16%)
📈 view plot
🚷 view threshold
32,583.93
(+12.20%)Baseline: 29,040.63
43,764.83
(74.45%)
📈 view plot
🚷 view threshold
2.79
(+1.73%)Baseline: 2.74
2.36
(84.73%)
/broken_app: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
277.75
(-13.85%)Baseline: 322.41
406.34
(68.35%)
📈 view plot
🚷 view threshold
313.90
(-21.48%)Baseline: 399.75
463.53
(67.72%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
6,181.64
(+56.00%)Baseline: 3,962.65
5,473.02
(112.95%)

📈 view plot
🚷 view threshold
20.04
(-13.76%)Baseline: 23.24
18.97
(94.67%)
/client_side_hello_world: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
9.14
(-6.79%)Baseline: 9.81
13.17
(69.41%)
📈 view plot
🚷 view threshold
18.62
(-18.97%)Baseline: 22.98
35.95
(51.80%)
📈 view plot
🚷 view threshold
110.29
(-27.33%)Baseline: 151.76
234.92
(46.95%)
📈 view plot
🚷 view threshold
702.08
(+14.57%)Baseline: 612.82
433.25
(61.71%)
/client_side_hello_world_shared_store: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
9.08
(-11.47%)Baseline: 10.26
13.55
(67.02%)
📈 view plot
🚷 view threshold
20.64
(-12.00%)Baseline: 23.46
36.18
(57.05%)
📈 view plot
🚷 view threshold
167.48
(+2.63%)Baseline: 163.19
252.22
(66.40%)
📈 view plot
🚷 view threshold
636.03
(+8.47%)Baseline: 586.34
398.68
(62.68%)
/client_side_hello_world_shared_store_controller: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
12.04
(+17.32%)Baseline: 10.26
13.71
(87.80%)
📈 view plot
🚷 view threshold
22.92
(-4.38%)Baseline: 23.97
36.82
(62.25%)
📈 view plot
🚷 view threshold
80.13
(-52.81%)Baseline: 169.81
265.11
(30.23%)
📈 view plot
🚷 view threshold
638.05
(+12.40%)Baseline: 567.65
399.97
(62.69%)
/client_side_hello_world_shared_store_defer: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
9.38
(-8.87%)Baseline: 10.29
13.76
(68.17%)
📈 view plot
🚷 view threshold
19.81
(-19.41%)Baseline: 24.58
38.66
(51.24%)
📈 view plot
🚷 view threshold
129.42
(-17.83%)Baseline: 157.51
242.30
(53.41%)
📈 view plot
🚷 view threshold
661.78
(+14.06%)Baseline: 580.20
405.36
(61.25%)
/client_side_log_throw: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.51
(-8.55%)Baseline: 9.31
11.99
(70.98%)
📈 view plot
🚷 view threshold
23.09
(+5.72%)Baseline: 21.84
32.36
(71.36%)
📈 view plot
🚷 view threshold
130.35
(-16.35%)Baseline: 155.83
243.86
(53.45%)
📈 view plot
🚷 view threshold
668.10
(+6.30%)Baseline: 628.48
467.18
(69.93%)
/client_side_manual_render: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
9.49
(-6.38%)Baseline: 10.14
13.34
(71.14%)
📈 view plot
🚷 view threshold
26.07
(+29.64%)Baseline: 20.11
28.84
(90.40%)
📈 view plot
🚷 view threshold
95.70
(-38.70%)Baseline: 156.13
263.48
(36.32%)
📈 view plot
🚷 view threshold
653.68
(+9.27%)Baseline: 598.20
416.05
(63.65%)
/client_side_rescript_hello_world: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.44
(-12.34%)Baseline: 9.63
12.96
(65.13%)
📈 view plot
🚷 view threshold
22.27
(+2.16%)Baseline: 21.80
32.80
(67.89%)
📈 view plot
🚷 view threshold
122.64
(-27.10%)Baseline: 168.22
264.12
(46.43%)
📈 view plot
🚷 view threshold
689.31
(+14.08%)Baseline: 604.25
410.15
(59.50%)
/context_function_return_jsx: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
11.63
(+25.38%)Baseline: 9.28
12.34
(94.21%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
30.73
(+49.79%)Baseline: 20.52
26.87
(114.37%)

📈 view plot
🚷 view threshold
170.24
(+12.82%)Baseline: 150.90
249.54
(68.22%)
📈 view plot
🚷 view threshold
470.59
(-27.02%)Baseline: 644.82
465.89
(99.00%)
/css_modules_images_fonts_example: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
353.50
(+7.70%)Baseline: 328.21
395.98
(89.27%)
📈 view plot
🚷 view threshold
413.13
(+0.95%)Baseline: 409.25
479.10
(86.23%)
📈 view plot
🚷 view threshold
3,880.20
(-1.92%)Baseline: 3,956.04
5,434.03
(71.41%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
17.56
(-24.27%)Baseline: 23.19
17.90
(101.91%)

/image_example: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
346.88
(+4.24%)Baseline: 332.76
391.17
(88.68%)
📈 view plot
🚷 view threshold
411.49
(+0.97%)Baseline: 407.52
456.60
(90.12%)
📈 view plot
🚷 view threshold
3,757.46
(-1.17%)Baseline: 3,801.88
5,179.81
(72.54%)
📈 view plot
🚷 view threshold
24.39
(+4.77%)Baseline: 23.28
19.06
(78.15%)
/manual_render_test: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
7.79
(-16.72%)Baseline: 9.35
12.00
(64.91%)
📈 view plot
🚷 view threshold
16.66
(-20.55%)Baseline: 20.97
28.83
(57.79%)
📈 view plot
🚷 view threshold
199.35
(+49.41%)Baseline: 133.43
205.36
(97.07%)
📈 view plot
🚷 view threshold
671.55
(+2.63%)Baseline: 654.37
484.80
(72.19%)
/pure_component: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
342.94
(+7.84%)Baseline: 318.01
401.47
(85.42%)
📈 view plot
🚷 view threshold
408.01
(+3.07%)Baseline: 395.85
456.41
(89.39%)
📈 view plot
🚷 view threshold
3,698.69
(-5.82%)Baseline: 3,927.32
5,294.14
(69.86%)
📈 view plot
🚷 view threshold
24.51
(+1.94%)Baseline: 24.04
19.22
(78.41%)
/pure_component_wrapped_in_function: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.63
(-13.04%)Baseline: 9.92
12.67
(68.12%)
📈 view plot
🚷 view threshold
23.22
(+7.44%)Baseline: 21.61
33.50
(69.32%)
📈 view plot
🚷 view threshold
122.52
(-13.09%)Baseline: 140.98
227.81
(53.78%)
📈 view plot
🚷 view threshold
671.94
(+6.05%)Baseline: 633.60
455.82
(67.84%)
/react_helmet: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
341.57
(+6.47%)Baseline: 320.81
388.83
(87.85%)
📈 view plot
🚷 view threshold
397.67
(+0.31%)Baseline: 396.45
453.81
(87.63%)
📈 view plot
🚷 view threshold
4,032.34
(+2.11%)Baseline: 3,949.16
5,276.67
(76.42%)
📈 view plot
🚷 view threshold
24.20
(+2.54%)Baseline: 23.60
20.19
(83.44%)
/react_helmet_broken: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
357.82
(+7.22%)Baseline: 333.72
423.50
(84.49%)
📈 view plot
🚷 view threshold
433.77
(+4.34%)Baseline: 415.73
460.60
(94.17%)
📈 view plot
🚷 view threshold
3,636.21
(-7.95%)Baseline: 3,950.10
5,389.37
(67.47%)
📈 view plot
🚷 view threshold
23.39
(+2.02%)Baseline: 22.93
19.36
(82.76%)
/react_router: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
354.73
(+4.07%)Baseline: 340.84
417.84
(84.90%)
📈 view plot
🚷 view threshold
434.46
(+3.73%)Baseline: 418.83
473.48
(91.76%)
📈 view plot
🚷 view threshold
4,051.03
(-2.27%)Baseline: 4,145.06
5,522.43
(73.36%)
📈 view plot
🚷 view threshold
23.18
(+2.39%)Baseline: 22.64
17.67
(76.21%)
/render_js: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
250.70
(-17.40%)Baseline: 303.52
391.90
(63.97%)
📈 view plot
🚷 view threshold
366.13
(-3.61%)Baseline: 379.84
432.41
(84.67%)
📈 view plot
🚷 view threshold
3,720.26
(-0.21%)Baseline: 3,728.08
5,350.66
(69.53%)
📈 view plot
🚷 view threshold
25.95
(+3.42%)Baseline: 25.09
19.84
(76.46%)
/rendered_html: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
347.24
(+7.04%)Baseline: 324.41
385.72
(90.02%)
📈 view plot
🚷 view threshold
404.45
(+1.36%)Baseline: 399.02
460.53
(87.82%)
📈 view plot
🚷 view threshold
4,054.51
(+4.70%)Baseline: 3,872.50
5,178.67
(78.29%)
📈 view plot
🚷 view threshold
24.18
(+0.92%)Baseline: 23.96
19.35
(80.03%)
/server_side_hello_world: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
339.53
(+3.46%)Baseline: 328.18
407.43
(83.33%)
📈 view plot
🚷 view threshold
394.00
(-1.98%)Baseline: 401.95
466.44
(84.47%)
📈 view plot
🚷 view threshold
3,693.64
(-8.32%)Baseline: 4,028.73
5,745.19
(64.29%)
📈 view plot
🚷 view threshold
24.82
(+6.43%)Baseline: 23.32
17.88
(72.02%)
/server_side_hello_world_es5: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
343.89
(+4.71%)Baseline: 328.43
389.67
(88.25%)
📈 view plot
🚷 view threshold
401.76
(-1.07%)Baseline: 406.09
476.36
(84.34%)
📈 view plot
🚷 view threshold
3,733.72
(-5.12%)Baseline: 3,935.25
5,288.78
(70.60%)
📈 view plot
🚷 view threshold
24.90
(+8.66%)Baseline: 22.92
17.45
(70.07%)
/server_side_hello_world_hooks: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
340.79
(+2.47%)Baseline: 332.57
398.05
(85.62%)
📈 view plot
🚷 view threshold
403.64
(-0.79%)Baseline: 406.86
469.93
(85.89%)
📈 view plot
🚷 view threshold
3,424.24
(-9.69%)Baseline: 3,791.80
5,174.02
(66.18%)
📈 view plot
🚷 view threshold
25.01
(+5.73%)Baseline: 23.65
18.39
(73.55%)
/server_side_hello_world_props: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
362.65
(+14.52%)Baseline: 316.67
403.49
(89.88%)
📈 view plot
🚷 view threshold
399.18
(-2.37%)Baseline: 408.88
513.51
(77.74%)
📈 view plot
🚷 view threshold
2,264.81
(-45.89%)Baseline: 4,185.88
5,933.51
(38.17%)
📈 view plot
🚷 view threshold
25.00
(+8.07%)Baseline: 23.13
17.56
(70.25%)
/server_side_hello_world_shared_store: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
678.35
(+3.48%)Baseline: 655.52
822.23
(82.50%)
📈 view plot
🚷 view threshold
905.61
(+6.95%)Baseline: 846.74
986.87
(91.77%)
📈 view plot
🚷 view threshold
7,554.05
(+4.00%)Baseline: 7,263.82
10,661.16
(70.86%)
📈 view plot
🚷 view threshold
12.14
(+2.95%)Baseline: 11.79
9.85
(81.10%)
/server_side_hello_world_shared_store_controller: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
687.86
(+5.74%)Baseline: 650.49
799.46
(86.04%)
📈 view plot
🚷 view threshold
895.22
(+7.52%)Baseline: 832.57
991.66
(90.28%)
📈 view plot
🚷 view threshold
7,780.91
(+3.99%)Baseline: 7,482.42
10,767.79
(72.26%)
📈 view plot
🚷 view threshold
12.17
(+4.41%)Baseline: 11.66
9.87
(81.10%)
/server_side_hello_world_shared_store_defer: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
680.69
(+3.43%)Baseline: 658.13
761.59
(89.38%)
📈 view plot
🚷 view threshold
936.54
(+11.05%)Baseline: 843.35
1,019.61
(91.85%)
📈 view plot
🚷 view threshold
7,075.06
(-3.59%)Baseline: 7,338.24
9,939.61
(71.18%)
📈 view plot
🚷 view threshold
12.17
(+5.21%)Baseline: 11.57
9.33
(76.63%)
/server_side_hello_world_with_options: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
341.60
(+5.96%)Baseline: 322.37
390.15
(87.56%)
📈 view plot
🚷 view threshold
400.84
(+0.85%)Baseline: 397.46
456.85
(87.74%)
📈 view plot
🚷 view threshold
3,910.11
(-1.30%)Baseline: 3,961.58
5,512.74
(70.93%)
📈 view plot
🚷 view threshold
24.87
(+4.08%)Baseline: 23.89
19.05
(76.61%)
/server_side_log_throw: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
247.10
(-23.92%)Baseline: 324.79
396.97
(62.25%)
📈 view plot
🚷 view threshold
399.60
(-0.42%)Baseline: 401.28
468.61
(85.27%)
📈 view plot
🚷 view threshold
4,656.46
(+15.88%)Baseline: 4,018.35
5,486.36
(84.87%)
📈 view plot
🚷 view threshold
23.79
(+2.46%)Baseline: 23.22
19.59
(82.33%)
/server_side_log_throw_plain_js: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
346.84
(+7.80%)Baseline: 321.75
395.73
(87.64%)
📈 view plot
🚷 view threshold
406.44
(+1.00%)Baseline: 402.40
454.74
(89.38%)
📈 view plot
🚷 view threshold
3,850.67
(-0.84%)Baseline: 3,883.17
5,527.04
(69.67%)
📈 view plot
🚷 view threshold
24.35
(+3.93%)Baseline: 23.43
19.55
(80.29%)
/server_side_log_throw_raise: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
335.28
(+7.51%)Baseline: 311.87
384.44
(87.21%)
📈 view plot
🚷 view threshold
403.84
(+0.38%)Baseline: 402.30
457.08
(88.35%)
📈 view plot
🚷 view threshold
4,098.73
(+5.88%)Baseline: 3,871.13
5,189.78
(78.98%)
📈 view plot
🚷 view threshold
24.50
(+3.50%)Baseline: 23.67
19.50
(79.60%)
/server_side_log_throw_raise_invoker: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.12
(-2.22%)Baseline: 8.30
10.89
(74.56%)
📈 view plot
🚷 view threshold
18.75
(+9.99%)Baseline: 17.05
23.07
(81.27%)
📈 view plot
🚷 view threshold
103.76
(-17.57%)Baseline: 125.88
202.39
(51.27%)
📈 view plot
🚷 view threshold
775.95
(+4.01%)Baseline: 746.03
561.46
(72.36%)
/server_side_redux_app: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
353.47
(+6.96%)Baseline: 330.46
398.86
(88.62%)
📈 view plot
🚷 view threshold
415.09
(+1.88%)Baseline: 407.41
476.93
(87.03%)
📈 view plot
🚷 view threshold
3,779.29
(-2.31%)Baseline: 3,868.62
5,124.52
(73.75%)
📈 view plot
🚷 view threshold
23.76
(+4.29%)Baseline: 22.78
18.79
(79.08%)
/server_side_redux_app_cached: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
10.03
(-1.15%)Baseline: 10.15
13.38
(74.98%)
📈 view plot
🚷 view threshold
23.44
(+23.26%)Baseline: 19.02
27.71
(84.58%)
📈 view plot
🚷 view threshold
152.86
(+8.74%)Baseline: 140.57
223.71
(68.33%)
📈 view plot
🚷 view threshold
618.78
(-5.03%)Baseline: 651.55
470.84
(76.09%)
/turbo_frame_tag_hello_world: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.30
(-6.08%)Baseline: 8.84
11.59
(71.61%)
📈 view plot
🚷 view threshold
17.46
(-4.38%)Baseline: 18.26
26.15
(66.76%)
📈 view plot
🚷 view threshold
97.13
(-27.02%)Baseline: 133.10
214.32
(45.32%)
📈 view plot
🚷 view threshold
768.80
(+9.07%)Baseline: 704.89
492.84
(64.10%)
/turbolinks_cache_disabled: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
10.12
(+3.86%)Baseline: 9.74
12.43
(81.43%)
📈 view plot
🚷 view threshold
27.17
(+26.95%)Baseline: 21.40
31.51
(86.23%)
📈 view plot
🚷 view threshold
106.65
(-28.13%)Baseline: 148.40
237.62
(44.88%)
📈 view plot
🚷 view threshold
615.64
(-0.73%)Baseline: 620.15
427.91
(69.51%)
/xhr_refresh: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
615.86
(+0.41%)Baseline: 613.36
783.18
(78.64%)
📈 view plot
🚷 view threshold
698.63
(-14.28%)Baseline: 815.06
946.16
(73.84%)
📈 view plot
🚷 view threshold
6,740.34
(-11.50%)Baseline: 7,616.20
11,149.50
(60.45%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
9.75
(-20.29%)Baseline: 12.23
10.15
(104.10%)

🐰 View full continuous benchmarking report in Bencher

@github-actions

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchjg-conductor/fix-issue-1828-comment
Testbedgithub-actions

🚨 16 Alerts

BenchmarkMeasure
Units
ViewBenchmark Result
(Result Δ%)
Lower Boundary
(Limit %)
Upper Boundary
(Limit %)
/async_render_function_returns_string: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
265.56
(-26.72%)Baseline: 362.40
285.87
(107.65%)

/cached_react_helmet: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
293.57
(-23.99%)Baseline: 386.24
299.25
(101.94%)

/client_side_log_throw: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
40.63
(+42.62%)Baseline: 28.49
39.31
(103.36%)

/error_scenarios_hub: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
264.17
(-28.36%)Baseline: 368.76
298.78
(113.10%)

/lazy_apollo_graphql: Prop50_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
65.13
(+31.21%)Baseline: 49.64
63.82
(102.05%)

/non_existing_react_component: Prop50_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
26.37
(+35.58%)Baseline: 19.45
26.03
(101.31%)

/rsc_native_metadata: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
260.74
(-24.86%)Baseline: 347.02
268.36
(102.92%)

/rsc_native_metadata: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
465.75
(+85.89%)Baseline: 250.55
361.99
(128.66%)

/server_router: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
258.85
(-25.24%)Baseline: 346.25
265.24
(102.47%)

/server_router: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
53.69
(+55.52%)Baseline: 34.52
48.06
(111.71%)

/server_side_redux_app: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
270.09
(-21.45%)Baseline: 343.82
273.10
(101.11%)

/server_side_redux_app: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
61.16
(+82.74%)Baseline: 33.47
45.38
(134.78%)

/ssr_async_error: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
257.18
(-25.21%)Baseline: 343.86
275.82
(107.25%)

/stream_native_metadata: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
267.28
(-24.23%)Baseline: 352.77
268.93
(100.62%)

/stream_shell_error_demo: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
250.26
(-28.48%)Baseline: 349.92
260.51
(104.09%)

/turbolinks_cache_disabled: Prop50_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
24.27
(+30.61%)Baseline: 18.58
24.09
(100.73%)

Click to view all benchmark results
Benchmarkfailed_pct%p50_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p90_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p99_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
rpsBenchmark Result
req/s
(Result Δ%)
Lower Boundary
req/s
(Limit %)
/: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
50.89
(+25.29%)Baseline: 40.62
52.26
(97.37%)
📈 view plot
🚷 view threshold
73.85
(+18.41%)Baseline: 62.37
79.46
(92.94%)
📈 view plot
🚷 view threshold
421.73
(-15.17%)Baseline: 497.13
716.38
(58.87%)
📈 view plot
🚷 view threshold
158.42
(-13.29%)Baseline: 182.71
146.09
(92.21%)
/async_components_demo: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
41.20
(+16.11%)Baseline: 35.48
45.99
(89.58%)
📈 view plot
🚷 view threshold
57.38
(+10.38%)Baseline: 51.98
64.59
(88.84%)
📈 view plot
🚷 view threshold
457.48
(+7.99%)Baseline: 423.65
621.51
(73.61%)
📈 view plot
🚷 view threshold
192.46
(-7.57%)Baseline: 208.23
160.48
(83.38%)
/async_on_server_sync_on_client: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.28
(-0.39%)Baseline: 21.36
27.89
(76.29%)
📈 view plot
🚷 view threshold
35.59
(-5.66%)Baseline: 37.73
54.65
(65.12%)
📈 view plot
🚷 view threshold
344.53
(+37.18%)Baseline: 251.16
373.52
(92.24%)
📈 view plot
🚷 view threshold
300.25
(-10.69%)Baseline: 336.21
257.15
(85.64%)
/async_render_function_returns_string: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.55
(+9.00%)Baseline: 19.77
25.85
(83.35%)
📈 view plot
🚷 view threshold
41.07
(+21.71%)Baseline: 33.74
48.13
(85.32%)
📈 view plot
🚷 view threshold
266.29
(+8.72%)Baseline: 244.93
370.28
(71.92%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
265.56
(-26.72%)Baseline: 362.40
285.87
(107.65%)

/cached_react_helmet: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
19.05
(+1.40%)Baseline: 18.79
23.55
(80.91%)
📈 view plot
🚷 view threshold
26.25
(-18.20%)Baseline: 32.09
49.29
(53.26%)
📈 view plot
🚷 view threshold
345.46
(+47.06%)Baseline: 234.91
347.27
(99.48%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
293.57
(-23.99%)Baseline: 386.24
299.25
(101.94%)

/cached_redux_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.66
(+11.56%)Baseline: 18.52
23.71
(87.15%)
📈 view plot
🚷 view threshold
31.87
(-8.27%)Baseline: 34.74
90.62
(35.17%)
📈 view plot
🚷 view threshold
286.32
(+20.84%)Baseline: 236.94
362.04
(79.08%)
📈 view plot
🚷 view threshold
373.54
(-3.31%)Baseline: 386.31
284.86
(76.26%)
/client_side_hello_world_shared_store: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
23.52
(+20.52%)Baseline: 19.51
24.96
(94.25%)
📈 view plot
🚷 view threshold
35.94
(+17.20%)Baseline: 30.66
40.15
(89.51%)
📈 view plot
🚷 view threshold
258.85
(+2.64%)Baseline: 252.20
369.77
(70.00%)
📈 view plot
🚷 view threshold
325.11
(-8.47%)Baseline: 355.19
270.53
(83.21%)
/client_side_hello_world_shared_store_defer: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
23.33
(+13.90%)Baseline: 20.48
25.69
(90.80%)
📈 view plot
🚷 view threshold
35.73
(+10.88%)Baseline: 32.22
44.11
(81.00%)
📈 view plot
🚷 view threshold
319.35
(+29.34%)Baseline: 246.92
366.86
(87.05%)
📈 view plot
🚷 view threshold
322.56
(-8.85%)Baseline: 353.87
268.50
(83.24%)
/client_side_log_throw: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.44
(+3.43%)Baseline: 17.83
24.55
(75.10%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
40.63
(+42.62%)Baseline: 28.49
39.31
(103.36%)

📈 view plot
🚷 view threshold
231.71
(-3.74%)Baseline: 240.71
371.79
(62.32%)
📈 view plot
🚷 view threshold
307.06
(-21.47%)Baseline: 391.03
301.13
(98.07%)
/context_function_return_jsx: Pro📈 view plot
🚷 view threshold
100.00📈 view plot
🚷 view threshold
19.35
(+5.10%)Baseline: 18.41
22.45
(86.18%)
📈 view plot
🚷 view threshold
31.40
(+0.32%)Baseline: 31.30
44.88
(69.97%)
📈 view plot
🚷 view threshold
278.34
(+32.05%)Baseline: 210.79
309.91
(89.81%)
📈 view plot
🚷 view threshold
390.49
(-0.68%)Baseline: 393.15
320.98
(82.20%)
/error_scenarios_hub: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.79
(+12.66%)Baseline: 19.34
24.71
(88.19%)
📈 view plot
🚷 view threshold
35.63
(+19.12%)Baseline: 29.91
38.04
(93.65%)
📈 view plot
🚷 view threshold
265.30
(+11.60%)Baseline: 237.72
368.48
(72.00%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
264.17
(-28.36%)Baseline: 368.76
298.78
(113.10%)

/image_example: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
24.52
(+18.90%)Baseline: 20.62
25.19
(97.33%)
📈 view plot
🚷 view threshold
39.84
(+12.09%)Baseline: 35.54
53.10
(75.03%)
📈 view plot
🚷 view threshold
266.47
(+8.22%)Baseline: 246.24
339.85
(78.41%)
📈 view plot
🚷 view threshold
318.19
(-7.19%)Baseline: 342.83
261.83
(82.29%)
/lazy_apollo_graphql: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
🚨 view alert (🔔)
65.13
(+31.21%)Baseline: 49.64
63.82
(102.05%)

📈 view plot
🚷 view threshold
103.53
(+13.77%)Baseline: 91.00
134.74
(76.84%)
📈 view plot
🚷 view threshold
600.98
(-8.90%)Baseline: 659.68
922.35
(65.16%)
📈 view plot
🚷 view threshold
118.74
(-6.18%)Baseline: 126.56
104.43
(87.95%)
/non_existing_react_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
🚨 view alert (🔔)
26.37
(+35.58%)Baseline: 19.45
26.03
(101.31%)

📈 view plot
🚷 view threshold
36.98
(+15.38%)Baseline: 32.05
44.41
(83.26%)
📈 view plot
🚷 view threshold
154.08
(-39.69%)Baseline: 255.47
392.11
(39.30%)
📈 view plot
🚷 view threshold
327.35
(-9.46%)Baseline: 361.57
281.10
(85.87%)
/non_existing_rsc_payload: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
23.81
(+23.17%)Baseline: 19.33
25.21
(94.44%)
📈 view plot
🚷 view threshold
34.05
(-1.57%)Baseline: 34.59
48.73
(69.88%)
📈 view plot
🚷 view threshold
125.47
(-44.67%)Baseline: 226.76
341.92
(36.70%)
📈 view plot
🚷 view threshold
365.63
(-0.18%)Baseline: 366.30
297.93
(81.48%)
/posts_page: Pro📈 view plot
🚷 view threshold
100.00📈 view plot
🚷 view threshold
9.23
(+0.53%)Baseline: 9.18
11.55
(79.92%)
📈 view plot
🚷 view threshold
13.38
(-1.83%)Baseline: 13.63
16.44
(81.37%)
📈 view plot
🚷 view threshold
78.06
(-28.32%)Baseline: 108.91
152.99
(51.02%)
📈 view plot
🚷 view threshold
877.26
(+11.60%)Baseline: 786.08
619.06
(70.57%)
/pure_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.62
(+12.36%)Baseline: 20.13
25.44
(88.92%)
📈 view plot
🚷 view threshold
36.30
(+8.66%)Baseline: 33.41
47.69
(76.11%)
📈 view plot
🚷 view threshold
187.55
(-23.44%)Baseline: 244.96
376.80
(49.77%)
📈 view plot
🚷 view threshold
345.52
(-2.95%)Baseline: 356.02
273.14
(79.05%)
/react_helmet_broken: Pro📈 view plot
🚷 view threshold
100.00📈 view plot
🚷 view threshold
22.54
(+13.50%)Baseline: 19.86
26.04
(86.55%)
📈 view plot
🚷 view threshold
31.67
(+2.08%)Baseline: 31.02
38.55
(82.15%)
📈 view plot
🚷 view threshold
238.77
(-7.59%)Baseline: 258.38
398.28
(59.95%)
📈 view plot
🚷 view threshold
351.82
(-3.86%)Baseline: 365.96
287.58
(81.74%)
/redis_receiver: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
80.13
(+16.47%)Baseline: 68.80
89.38
(89.65%)
📈 view plot
🚷 view threshold
190.27
(+30.25%)Baseline: 146.08
191.37
(99.43%)
📈 view plot
🚷 view threshold
992.21
(+3.59%)Baseline: 957.84
1,383.69
(71.71%)
📈 view plot
🚷 view threshold
82.96
(-7.44%)Baseline: 89.63
71.48
(86.16%)
/render_js: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
19.75
(+10.85%)Baseline: 17.82
22.90
(86.26%)
📈 view plot
🚷 view threshold
29.33
(-4.72%)Baseline: 30.78
42.84
(68.47%)
📈 view plot
🚷 view threshold
205.71
(-10.35%)Baseline: 229.45
344.03
(59.79%)
📈 view plot
🚷 view threshold
394.10
(+1.23%)Baseline: 389.32
292.82
(74.30%)
/rsc_native_metadata: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.18
(-11.77%)Baseline: 20.61
27.22
(66.80%)
📈 view plot
🚷 view threshold
27.48
(-23.01%)Baseline: 35.69
50.78
(54.12%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
465.75
(+85.89%)Baseline: 250.55
361.99
(128.66%)

📈 view plot
🚷 view threshold
🚨 view alert (🔔)
260.74
(-24.86%)Baseline: 347.02
268.36
(102.92%)

/rsc_posts_page_over_redis: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
75.62
(+11.75%)Baseline: 67.67
86.87
(87.05%)
📈 view plot
🚷 view threshold
126.49
(+12.91%)Baseline: 112.03
139.35
(90.77%)
📈 view plot
🚷 view threshold
811.03
(+7.11%)Baseline: 757.18
1,080.14
(75.09%)
📈 view plot
🚷 view threshold
95.38
(-7.86%)Baseline: 103.52
84.64
(88.74%)
/server_router: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.91
(+4.30%)Baseline: 21.01
26.64
(82.26%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
53.69
(+55.52%)Baseline: 34.52
48.06
(111.71%)

📈 view plot
🚷 view threshold
254.46
(+4.75%)Baseline: 242.91
357.31
(71.21%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
258.85
(-25.24%)Baseline: 346.25
265.24
(102.47%)

/server_side_hello_world: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
24.33
(+15.90%)Baseline: 20.99
27.05
(89.93%)
📈 view plot
🚷 view threshold
38.14
(+9.81%)Baseline: 34.73
49.86
(76.49%)
📈 view plot
🚷 view threshold
196.49
(-19.82%)Baseline: 245.06
365.28
(53.79%)
📈 view plot
🚷 view threshold
322.37
(-7.45%)Baseline: 348.32
261.10
(80.99%)
/server_side_hello_world_shared_store_controller: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
28.91
(+16.12%)Baseline: 24.90
31.84
(90.80%)
📈 view plot
🚷 view threshold
43.06
(+9.86%)Baseline: 39.20
52.69
(81.73%)
📈 view plot
🚷 view threshold
246.49
(-14.64%)Baseline: 288.77
420.83
(58.57%)
📈 view plot
🚷 view threshold
276.67
(-5.70%)Baseline: 293.39
221.26
(79.97%)
/server_side_log_throw_plain_js: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.95
(+14.95%)Baseline: 18.23
23.97
(87.40%)
📈 view plot
🚷 view threshold
32.58
(+5.67%)Baseline: 30.83
44.79
(72.75%)
📈 view plot
🚷 view threshold
154.35
(-30.01%)Baseline: 220.53
346.27
(44.58%)
📈 view plot
🚷 view threshold
377.37
(-4.83%)Baseline: 396.52
293.29
(77.72%)
/server_side_log_throw_raise_invoker: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.97
(+14.35%)Baseline: 16.59
20.83
(91.08%)
📈 view plot
🚷 view threshold
28.12
(+4.85%)Baseline: 26.82
35.08
(80.16%)
📈 view plot
🚷 view threshold
210.93
(+5.43%)Baseline: 200.07
303.21
(69.57%)
📈 view plot
🚷 view threshold
405.96
(-5.64%)Baseline: 430.25
317.74
(78.27%)
/server_side_redux_app: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.29
(+1.11%)Baseline: 21.06
27.19
(78.31%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
61.16
(+82.74%)Baseline: 33.47
45.38
(134.78%)

📈 view plot
🚷 view threshold
239.59
(-6.11%)Baseline: 255.19
372.27
(64.36%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
270.09
(-21.45%)Baseline: 343.82
273.10
(101.11%)

/server_side_redux_app_cached: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.95
(+9.58%)Baseline: 19.12
23.73
(88.30%)
📈 view plot
🚷 view threshold
30.45
(+1.20%)Baseline: 30.09
40.65
(74.91%)
📈 view plot
🚷 view threshold
228.21
(+1.71%)Baseline: 224.37
321.30
(71.03%)
📈 view plot
🚷 view threshold
374.43
(-2.46%)Baseline: 383.86
302.46
(80.78%)
/ssr_async_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.06
(+9.29%)Baseline: 20.18
26.85
(82.17%)
📈 view plot
🚷 view threshold
29.66
(-13.58%)Baseline: 34.32
48.81
(60.76%)
📈 view plot
🚷 view threshold
368.84
(+42.93%)Baseline: 258.06
384.94
(95.82%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
257.18
(-25.21%)Baseline: 343.86
275.82
(107.25%)

/ssr_async_prop_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
24.17
(+14.17%)Baseline: 21.17
26.90
(89.87%)
📈 view plot
🚷 view threshold
39.75
(+8.95%)Baseline: 36.49
53.34
(74.53%)
📈 view plot
🚷 view threshold
202.45
(-22.08%)Baseline: 259.81
375.97
(53.85%)
📈 view plot
🚷 view threshold
324.64
(-2.52%)Baseline: 333.05
267.93
(82.53%)
/stream_native_metadata: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.30
(+6.23%)Baseline: 20.05
26.08
(81.68%)
📈 view plot
🚷 view threshold
42.33
(+22.33%)Baseline: 34.60
49.53
(85.46%)
📈 view plot
🚷 view threshold
260.71
(+5.20%)Baseline: 247.83
363.39
(71.74%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
267.28
(-24.23%)Baseline: 352.77
268.93
(100.62%)

/stream_shell_error_demo: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.79
(+15.12%)Baseline: 19.80
25.44
(89.60%)
📈 view plot
🚷 view threshold
52.04
(+37.92%)Baseline: 37.73
96.62
(53.86%)
📈 view plot
🚷 view threshold
280.61
(+11.58%)Baseline: 251.50
399.34
(70.27%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
250.26
(-28.48%)Baseline: 349.92
260.51
(104.09%)

/test_incremental_rendering: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
24.89
(+23.35%)Baseline: 20.18
25.55
(97.43%)
📈 view plot
🚷 view threshold
37.62
(+2.44%)Baseline: 36.72
53.05
(70.92%)
📈 view plot
🚷 view threshold
263.95
(+4.67%)Baseline: 252.17
352.27
(74.93%)
📈 view plot
🚷 view threshold
312.48
(-8.63%)Baseline: 341.98
271.02
(86.73%)
/turbolinks_cache_disabled: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
🚨 view alert (🔔)
24.27
(+30.61%)Baseline: 18.58
24.09
(100.73%)

📈 view plot
🚷 view threshold
34.31
(+14.96%)Baseline: 29.84
40.62
(84.47%)
📈 view plot
🚷 view threshold
138.31
(-35.87%)Baseline: 215.65
312.77
(44.22%)
📈 view plot
🚷 view threshold
353.02
(-7.81%)Baseline: 382.93
296.84
(84.09%)
/xhr_refresh: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
27.10
(+13.24%)Baseline: 23.93
31.49
(86.05%)
📈 view plot
🚷 view threshold
41.70
(+13.53%)Baseline: 36.73
48.49
(86.00%)
📈 view plot
🚷 view threshold
304.78
(+0.68%)Baseline: 302.72
430.95
(70.72%)
📈 view plot
🚷 view threshold
296.54
(-2.61%)Baseline: 304.47
232.78
(78.50%)
🐰 View full continuous benchmarking report in Bencher

@github-actions

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchjg-conductor/fix-issue-1828-comment
Testbedgithub-actions

🚨 15 Alerts

BenchmarkMeasure
Units
ViewBenchmark Result
(Result Δ%)
Lower Boundary
(Limit %)
Upper Boundary
(Limit %)
/apollo_graphql: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
1,049.11
(+63.51%)Baseline: 641.62
931.38
(112.64%)

/client_side_manual_render: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
294.78
(-23.70%)Baseline: 386.35
304.02
(103.14%)

/client_side_manual_render: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
40.64
(+40.35%)Baseline: 28.96
39.75
(102.24%)

/client_side_manual_render: Prop50_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
26.73
(+47.80%)Baseline: 18.08
24.03
(111.22%)

/css_modules_images_fonts_example: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
444.68
(+83.02%)Baseline: 242.97
383.01
(116.10%)

/non_existing_stream_react_component: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
384.28
(+53.46%)Baseline: 250.41
363.73
(105.65%)

/server_side_hello_world_es5: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
264.01
(-25.71%)Baseline: 355.38
269.79
(102.19%)

/server_side_hello_world_es5: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
45.28
(+35.63%)Baseline: 33.38
45.19
(100.20%)

/server_side_hello_world_es5: Prop50_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
29.94
(+46.43%)Baseline: 20.45
26.71
(112.11%)

/server_side_hello_world_with_options: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
260.26
(-25.85%)Baseline: 351.00
266.52
(102.40%)

/server_side_hello_world_with_options: Prop50_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
30.50
(+47.70%)Baseline: 20.65
26.48
(115.16%)

/server_side_log_throw: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
260.23
(-27.47%)Baseline: 358.78
281.49
(108.17%)

/server_side_log_throw_raise: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
198.09
(+53.71%)Baseline: 128.87
188.00
(105.37%)

/ssr_sync_error: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
288.14
(-18.05%)Baseline: 351.59
288.42
(100.10%)

/ssr_sync_error: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
57.02
(+68.98%)Baseline: 33.74
46.17
(123.50%)

Click to view all benchmark results
Benchmarkfailed_pct%p50_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p90_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p99_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
rpsBenchmark Result
req/s
(Result Δ%)
Lower Boundary
req/s
(Limit %)
/apollo_graphql: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
41.90
(-21.93%)Baseline: 53.67
66.16
(63.33%)
📈 view plot
🚷 view threshold
66.51
(-28.92%)Baseline: 93.57
130.83
(50.84%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
1,049.11
(+63.51%)Baseline: 641.62
931.38
(112.64%)

📈 view plot
🚷 view threshold
112.98
(-11.17%)Baseline: 127.19
104.17
(92.21%)
/async_on_server_sync_on_client_client_render: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.45
(+19.01%)Baseline: 18.86
25.15
(89.26%)
📈 view plot
🚷 view threshold
33.57
(+5.79%)Baseline: 31.73
44.03
(76.24%)
📈 view plot
🚷 view threshold
248.87
(+9.24%)Baseline: 227.82
339.43
(73.32%)
📈 view plot
🚷 view threshold
345.90
(-8.38%)Baseline: 377.54
297.01
(85.87%)
/async_render_function_returns_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
25.39
(+24.60%)Baseline: 20.38
25.94
(97.87%)
📈 view plot
🚷 view threshold
34.57
(+5.76%)Baseline: 32.69
43.75
(79.02%)
📈 view plot
🚷 view threshold
135.17
(-44.01%)Baseline: 241.41
376.46
(35.91%)
📈 view plot
🚷 view threshold
342.40
(-5.40%)Baseline: 361.95
274.31
(80.11%)
/broken_app: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.49
(+11.97%)Baseline: 20.09
26.33
(85.41%)
📈 view plot
🚷 view threshold
33.05
(+0.27%)Baseline: 32.96
47.66
(69.35%)
📈 view plot
🚷 view threshold
303.60
(+23.56%)Baseline: 245.70
384.25
(79.01%)
📈 view plot
🚷 view threshold
351.64
(-2.73%)Baseline: 361.49
272.99
(77.63%)
/client_side_hello_world: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
17.17
(-8.31%)Baseline: 18.73
23.99
(71.56%)
📈 view plot
🚷 view threshold
28.74
(-4.27%)Baseline: 30.02
42.57
(67.51%)
📈 view plot
🚷 view threshold
280.60
(+26.81%)Baseline: 221.28
345.11
(81.31%)
📈 view plot
🚷 view threshold
368.20
(-4.49%)Baseline: 385.51
294.87
(80.08%)
/client_side_hello_world_shared_store_controller: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.53
(+3.96%)Baseline: 20.71
25.86
(83.26%)
📈 view plot
🚷 view threshold
32.26
(-5.25%)Baseline: 34.05
46.44
(69.47%)
📈 view plot
🚷 view threshold
239.25
(+1.86%)Baseline: 234.87
336.50
(71.10%)
📈 view plot
🚷 view threshold
357.02
(+0.91%)Baseline: 353.81
271.46
(76.03%)
/client_side_manual_render: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
🚨 view alert (🔔)
26.73
(+47.80%)Baseline: 18.08
24.03
(111.22%)

📈 view plot
🚷 view threshold
🚨 view alert (🔔)
40.64
(+40.35%)Baseline: 28.96
39.75
(102.24%)

📈 view plot
🚷 view threshold
200.78
(-14.28%)Baseline: 234.23
356.22
(56.36%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
294.78
(-23.70%)Baseline: 386.35
304.02
(103.14%)

/console_logs_in_async_server: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
2,121.65
(-0.15%)Baseline: 2,124.85
2,132.59
(99.49%)
📈 view plot
🚷 view threshold
2,157.40
(-9.87%)Baseline: 2,393.59
5,161.48
(41.80%)
📈 view plot
🚷 view threshold
23,491.12
(+5.11%)Baseline: 22,349.69
30,422.99
(77.22%)
📈 view plot
🚷 view threshold
3.15
(+0.28%)Baseline: 3.14
2.36
(75.06%)
/css_modules_images_fonts_example: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
16.96
(-15.34%)Baseline: 20.03
27.14
(62.49%)
📈 view plot
🚷 view threshold
32.01
(-5.32%)Baseline: 33.81
48.23
(66.37%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
444.68
(+83.02%)Baseline: 242.97
383.01
(116.10%)

📈 view plot
🚷 view threshold
331.09
(-6.51%)Baseline: 354.13
271.38
(81.96%)
/empty: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
6.26
(+12.86%)Baseline: 5.55
7.17
(87.30%)
📈 view plot
🚷 view threshold
9.18
(+3.22%)Baseline: 8.89
11.62
(79.03%)
📈 view plot
🚷 view threshold
49.73
(-29.66%)Baseline: 70.70
104.89
(47.41%)
📈 view plot
🚷 view threshold
1,288.10
(-0.06%)Baseline: 1,288.87
1,059.71
(82.27%)
/hybrid_metadata_streaming: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.85
(+13.09%)Baseline: 20.20
25.98
(87.94%)
📈 view plot
🚷 view threshold
34.26
(-3.90%)Baseline: 35.65
50.87
(67.35%)
📈 view plot
🚷 view threshold
246.20
(-0.61%)Baseline: 247.71
390.48
(63.05%)
📈 view plot
🚷 view threshold
342.05
(-1.02%)Baseline: 345.58
275.51
(80.55%)
/loadable: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.64
(-2.61%)Baseline: 22.22
28.20
(76.74%)
📈 view plot
🚷 view threshold
43.88
(+25.47%)Baseline: 34.97
45.70
(96.02%)
📈 view plot
🚷 view threshold
238.12
(-14.09%)Baseline: 277.18
415.36
(57.33%)
📈 view plot
🚷 view threshold
266.99
(-16.56%)Baseline: 319.96
237.49
(88.95%)
/native_metadata: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.35
(-0.16%)Baseline: 20.38
26.85
(75.80%)
📈 view plot
🚷 view threshold
43.83
(+28.65%)Baseline: 34.07
50.28
(87.17%)
📈 view plot
🚷 view threshold
236.05
(-8.31%)Baseline: 257.44
397.28
(59.42%)
📈 view plot
🚷 view threshold
286.27
(-17.48%)Baseline: 346.92
266.50
(93.10%)
/non_existing_stream_react_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
15.37
(-22.38%)Baseline: 19.80
24.34
(63.15%)
📈 view plot
🚷 view threshold
28.94
(-17.23%)Baseline: 34.96
49.21
(58.80%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
384.28
(+53.46%)Baseline: 250.41
363.73
(105.65%)

📈 view plot
🚷 view threshold
365.62
(+2.47%)Baseline: 356.82
282.08
(77.15%)
/pure_component_wrapped_in_function: Pro📈 view plot
🚷 view threshold
100.00📈 view plot
🚷 view threshold
20.12
(+11.02%)Baseline: 18.12
22.08
(91.12%)
📈 view plot
🚷 view threshold
26.78
(-12.20%)Baseline: 30.50
45.33
(59.07%)
📈 view plot
🚷 view threshold
114.78
(-47.98%)Baseline: 220.64
305.52
(37.57%)
📈 view plot
🚷 view threshold
435.65
(+11.43%)Baseline: 390.97
311.54
(71.51%)
/react_helmet: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.92
(+11.96%)Baseline: 20.47
26.75
(85.70%)
📈 view plot
🚷 view threshold
32.73
(-0.14%)Baseline: 32.78
45.27
(72.31%)
📈 view plot
🚷 view threshold
243.35
(-6.17%)Baseline: 259.35
395.12
(61.59%)
📈 view plot
🚷 view threshold
344.15
(-1.70%)Baseline: 350.12
275.81
(80.14%)
/react_router: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
15.83
(-8.75%)Baseline: 17.35
22.49
(70.39%)
📈 view plot
🚷 view threshold
27.22
(-6.54%)Baseline: 29.13
36.28
(75.02%)
📈 view plot
🚷 view threshold
273.48
(+25.38%)Baseline: 218.12
340.12
(80.41%)
📈 view plot
🚷 view threshold
403.65
(+2.22%)Baseline: 394.90
278.26
(68.94%)
/rendered_html: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.09
(+9.22%)Baseline: 20.23
25.62
(86.23%)
📈 view plot
🚷 view threshold
34.80
(-0.05%)Baseline: 34.82
50.69
(68.66%)
📈 view plot
🚷 view threshold
252.37
(+10.02%)Baseline: 229.38
325.84
(77.45%)
📈 view plot
🚷 view threshold
357.77
(+1.45%)Baseline: 352.66
272.02
(76.03%)
/rsc_component_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
23.25
(+17.31%)Baseline: 19.82
25.54
(91.03%)
📈 view plot
🚷 view threshold
34.40
(+3.36%)Baseline: 33.28
44.54
(77.23%)
📈 view plot
🚷 view threshold
253.70
(-2.22%)Baseline: 259.47
374.23
(67.79%)
📈 view plot
🚷 view threshold
337.53
(-3.99%)Baseline: 351.54
283.39
(83.96%)
/rsc_echo_props: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
32.69
(+15.11%)Baseline: 28.40
37.06
(88.21%)
📈 view plot
🚷 view threshold
47.97
(+2.88%)Baseline: 46.63
61.63
(77.83%)
📈 view plot
🚷 view threshold
432.01
(+11.27%)Baseline: 388.24
592.75
(72.88%)
📈 view plot
🚷 view threshold
242.14
(+0.37%)Baseline: 241.24
181.92
(75.13%)
/rsc_posts_page_over_http: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
23.36
(+17.70%)Baseline: 19.85
25.47
(91.70%)
📈 view plot
🚷 view threshold
34.85
(-0.23%)Baseline: 34.93
53.26
(65.44%)
📈 view plot
🚷 view threshold
242.72
(-7.01%)Baseline: 261.03
384.86
(63.07%)
📈 view plot
🚷 view threshold
334.13
(-3.53%)Baseline: 346.37
269.05
(80.52%)
/server_render_with_timeout: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.02
(+9.85%)Baseline: 20.05
26.26
(83.87%)
📈 view plot
🚷 view threshold
32.04
(-0.75%)Baseline: 32.28
45.53
(70.36%)
📈 view plot
🚷 view threshold
299.18
(+20.13%)Baseline: 249.04
374.02
(79.99%)
📈 view plot
🚷 view threshold
362.82
(+2.00%)Baseline: 355.71
283.57
(78.16%)
/server_router_client_render: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.60
(+12.08%)Baseline: 19.27
24.41
(88.49%)
📈 view plot
🚷 view threshold
34.02
(+4.40%)Baseline: 32.59
49.28
(69.03%)
📈 view plot
🚷 view threshold
248.79
(+6.44%)Baseline: 233.73
335.76
(74.10%)
📈 view plot
🚷 view threshold
357.83
(-1.84%)Baseline: 364.53
287.00
(80.21%)
/server_side_hello_world_es5: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
🚨 view alert (🔔)
29.94
(+46.43%)Baseline: 20.45
26.71
(112.11%)

📈 view plot
🚷 view threshold
🚨 view alert (🔔)
45.28
(+35.63%)Baseline: 33.38
45.19
(100.20%)

📈 view plot
🚷 view threshold
329.92
(+28.35%)Baseline: 257.05
381.26
(86.53%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
264.01
(-25.71%)Baseline: 355.38
269.79
(102.19%)

/server_side_hello_world_hooks: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.62
(+14.82%)Baseline: 19.70
24.59
(91.98%)
📈 view plot
🚷 view threshold
35.68
(+6.01%)Baseline: 33.66
44.48
(80.21%)
📈 view plot
🚷 view threshold
238.96
(+1.68%)Baseline: 235.01
345.33
(69.20%)
📈 view plot
🚷 view threshold
338.69
(-6.97%)Baseline: 364.08
283.44
(83.69%)
/server_side_hello_world_shared_store: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
27.00
(+9.58%)Baseline: 24.64
30.65
(88.08%)
📈 view plot
🚷 view threshold
36.65
(-4.97%)Baseline: 38.57
53.85
(68.06%)
📈 view plot
🚷 view threshold
280.02
(-4.40%)Baseline: 292.89
435.32
(64.32%)
📈 view plot
🚷 view threshold
298.53
(+0.59%)Baseline: 296.79
219.20
(73.43%)
/server_side_hello_world_shared_store_defer: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
29.67
(+24.40%)Baseline: 23.85
30.11
(98.52%)
📈 view plot
🚷 view threshold
37.76
(+3.25%)Baseline: 36.57
47.30
(79.83%)
📈 view plot
🚷 view threshold
186.73
(-41.00%)Baseline: 316.47
493.07
(37.87%)
📈 view plot
🚷 view threshold
296.30
(-2.85%)Baseline: 304.98
237.95
(80.31%)
/server_side_hello_world_with_options: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
🚨 view alert (🔔)
30.50
(+47.70%)Baseline: 20.65
26.48
(115.16%)

📈 view plot
🚷 view threshold
45.90
(+34.41%)Baseline: 34.15
48.43
(94.78%)
📈 view plot
🚷 view threshold
245.50
(+1.33%)Baseline: 242.27
364.23
(67.40%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
260.26
(-25.85%)Baseline: 351.00
266.52
(102.40%)

/server_side_log_throw: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.48
(+10.85%)Baseline: 20.28
25.62
(87.74%)
📈 view plot
🚷 view threshold
32.27
(-2.66%)Baseline: 33.15
46.06
(70.06%)
📈 view plot
🚷 view threshold
267.20
(+5.85%)Baseline: 252.44
363.48
(73.51%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
260.23
(-27.47%)Baseline: 358.78
281.49
(108.17%)

/server_side_log_throw_raise: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
13.73
(+33.43%)Baseline: 10.29
14.06
(97.66%)
📈 view plot
🚷 view threshold
22.23
(+29.92%)Baseline: 17.11
22.66
(98.10%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
198.09
(+53.71%)Baseline: 128.87
188.00
(105.37%)

📈 view plot
🚷 view threshold
570.63
(-18.97%)Baseline: 704.24
510.87
(89.53%)
/server_side_redux_app_cached: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.65
(+18.47%)Baseline: 19.12
23.73
(95.46%)
📈 view plot
🚷 view threshold
29.91
(-0.59%)Baseline: 30.09
40.65
(73.58%)
📈 view plot
🚷 view threshold
128.22
(-42.85%)Baseline: 224.37
321.30
(39.91%)
📈 view plot
🚷 view threshold
389.92
(+1.58%)Baseline: 383.86
302.46
(77.57%)
/ssr_shell_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
25.22
(+24.63%)Baseline: 20.24
27.73
(90.96%)
📈 view plot
🚷 view threshold
34.75
(-1.96%)Baseline: 35.44
53.57
(64.87%)
📈 view plot
🚷 view threshold
141.90
(-41.05%)Baseline: 240.73
379.21
(37.42%)
📈 view plot
🚷 view threshold
350.35
(-1.05%)Baseline: 354.06
285.51
(81.49%)
/ssr_sync_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.21
(-1.06%)Baseline: 20.43
25.66
(78.76%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
57.02
(+68.98%)Baseline: 33.74
46.17
(123.50%)

📈 view plot
🚷 view threshold
216.35
(-13.97%)Baseline: 251.49
355.81
(60.81%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
288.14
(-18.05%)Baseline: 351.59
288.42
(100.10%)

/stream_async_components: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
19.49
(-4.16%)Baseline: 20.34
26.64
(73.16%)
📈 view plot
🚷 view threshold
30.86
(-8.70%)Baseline: 33.80
49.42
(62.44%)
📈 view plot
🚷 view threshold
226.24
(-8.65%)Baseline: 247.66
349.12
(64.80%)
📈 view plot
🚷 view threshold
297.86
(-13.26%)Baseline: 343.40
272.13
(91.36%)
/stream_error_demo: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
23.87
(+17.87%)Baseline: 20.25
27.05
(88.24%)
📈 view plot
🚷 view threshold
39.11
(+13.99%)Baseline: 34.31
48.47
(80.69%)
📈 view plot
🚷 view threshold
272.56
(+9.98%)Baseline: 247.83
389.71
(69.94%)
📈 view plot
🚷 view threshold
324.77
(-6.92%)Baseline: 348.93
263.09
(81.01%)
🐰 View full continuous benchmarking report in Bencher

@justin808

Copy link
Copy Markdown
Member Author

Manual verification update for discussion with @AbanoubGhadban.

I used https://github.com/shakacode/react-on-rails-demo-marketplace-rsc as the verification target for PR #3385. This exposed a runtime blocker in the generated rscManifestPlugin.js helper path.

Summary:

  • Confidence in PR Fix Pro RSC manifests for Rspack builds #3385 as-is: low for runtime correctness.
  • The helper can generate manifests and complete a production Rspack build, but routes with RSC client boundaries fail in the browser.
  • The word "experimental" should stay for Rspack RSC runtime support until this demo-style verification is green.

What passed with the PR #3385 helper:

  • node --check config/rspack/rscManifestPlugin.js
  • bundle exec rake react_on_rails:generate_packs
  • NODE_ENV=production SHAKAPACKER_ASSETS_BUNDLER=rspack pnpm exec rspack build --config config/rspack/rspack.config.js
  • node scripts/check-rsc-chunks.mjs
  • Manifest files were emitted:
    • public/packs/react-client-manifest.json
    • ssr-generated/react-server-client-manifest.json
  • Manifest parity looked superficially OK: 38 client entries, 38 server entries, no missing counterpart entries, no empty chunk arrays.

Browser/manual results with the PR #3385 helper:

Passed:

  • /rsc
  • /blog/rsc-step1
  • /blog/rsc-step2
  • /restaurant/1/rsc

Failed:

  • /product/rsc
  • /product-search/rsc
  • /blog/rsc
  • /blog/rsc-simple
  • /blog/rsc-step3
  • /blog/rsc-step4
  • /blog/rsc-step5

Common browser errors:

  • Minified React error #419
  • ServerComponentFetchError: Minified React error #306

Node renderer error seen on failing routes:

Cannot find module './15.server-bundle.js'

Fair baseline comparison:

  • The demo's checked-in config expects react-on-rails-rsc/RspackPlugin, which is not exported by react-on-rails-rsc 19.0.4.
  • I built current shakacode/react_on_rails_rsc locally, which does export ./RspackPlugin, and pointed the demo's local .yalc/react-on-rails-rsc at it.
  • With the demo's original native RSCRspackPlugin path, the same 11 valid RSC routes all passed in Puppeteer.
  • Switching only the demo configs back to PR Fix Pro RSC manifests for Rspack builds #3385's generated helper, while keeping the same current RSC package, reproduced the 7 route failures above.

Assessment:

The automated tests added in this PR are useful, but they are not enough. They cover helper internals and generator output; they do not verify the real Rspack/Rails/Node Renderer/browser hydration path. A production build passing is also not sufficient here, because the helper-built assets fail at runtime.

Likely failure area:

  • The helper injects discovered client references through a synthetic entry and records chunk-group-level chunks in the manifest.
  • The server manifest can reference chunks such as 15 / rsc-client-references.js; the Node renderer then attempts to require a corresponding ./15.server-bundle.js, which does not exist.
  • The native RSCRspackPlugin has additional runtime-oriented behavior: async client-reference injection, skipping entry chunk groups for manifest purposes, and splitChunks handling for generated async chunks. The PR helper does not appear equivalent to that runtime behavior.

Recommended next steps:

  1. Do not merge PR Fix Pro RSC manifests for Rspack builds #3385 as production-ready in its current form.
  2. Prefer switching generated Rspack configs to the native react-on-rails-rsc/RspackPlugin once the package version exporting it is available, rather than maintaining a separate helper with divergent behavior.
  3. If this helper remains, add a real verification harness using this demo: production Rspack build, Node Renderer, Rails server, and Puppeteer checks for RSC routes with client boundaries.
  4. Keep the Rspack RSC docs marked experimental until that verification is green.
  5. Recommended PR label decision: full-ci; add benchmark too if the final fix changes Rspack chunking, bundle generation, or asset loading behavior.

@justin808

Copy link
Copy Markdown
Member Author

Status: converting to draft.

The generated rscManifestPlugin.js helper path is a confirmed runtime blocker. Controlled A/B on the marketplace demo (same locally-built react-on-rails-rsc exposing ./RspackPlugin, swapping only the config):

  • Native RSCRspackPlugin11/11 valid RSC routes pass in Puppeteer.
  • This helper → production build + valid manifests (38/38 entries, 0 missing, 0 empty chunks), but 7/11 routes fail in the browser (React #419, ServerComponentFetchError #306, renderer Cannot find module './15.server-bundle.js').

Evidence: shakacode/react-on-rails-demo-marketplace-rsc#72. Recommended path to production-ready Rspack RSC — pivot to the native plugin — tracked in #3488.

— assessment by Claude Code

justin808 added a commit that referenced this pull request Jun 1, 2026
### Summary

Documentation-only update that reframes how React on Rails' RSC support
is described, replacing the blanket "experimental/unstable" language
with what is actually true today.

In `babel-to-swc-migration.md`, Babel is now described as the
tested/reference transpiler for RSC (the Pro dummy app builds RSC with
Babel), and the doc clarifies that the `'use client'`/`'use server'`
boundary transform is performed by the `react-on-rails-rsc`
WebpackLoader before babel/swc — so RSC directive handling is
independent of transpiler choice, while SWC-based RSC builds are wired
but not yet verified end-to-end.

In `rspack-compatibility.md`, a current-status note explains that the
RSC bundle compiles and server-renders under Rspack but the RSC manifest
files are not yet emitted (in-progress fix tracked in [PR
#3385](#3385) / [issue
#1828](#1828)), and
that React on Rails uses the `react-server-dom-webpack` path via
Rspack's webpack compatibility layer rather than Rspack's native
`react-server-dom-rspack` RSC system.

### Pull Request checklist

- [x] ~Add/update test to cover these changes~ (docs-only)
- [x] Update documentation
- [x] ~Update CHANGELOG file~ (docs-only, no user-facing code change)

### Other Information

No code changes — documentation accuracy improvements only. Prettier,
trailing-newline, and markdown link checks pass via the pre-commit
hooks.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Markdown-only accuracy updates with no application code, build
scripts, or dependency changes.
> 
> **Overview**
> **Documentation-only** refresh of RSC compatibility guidance in the
Babel→SWC migration guide and the Rspack compatibility page—no runtime
or build config changes.
> 
> In **`babel-to-swc-migration.md`**, the RSC section moves from broad
“SWC + RSC is experimental” wording to a clearer split: **Babel is the
tested reference transpiler** (Pro dummy app), **`react-on-rails-rsc`’s
WebpackLoader** handles `'use client'` / `'use server'` **before**
babel/swc (transpiler choice is mostly ordinary JS/TS), and **SWC-based
RSC builds are wired but not end-to-end verified**. Recommendations and
the conclusion now say to stay on Babel for RSC unless you test heavily;
the status year is **2026**.
> 
> In **`rspack-compatibility.md`**, manifest naming is corrected to
**`react-server-client-manifest.json`** (replacing
`react-ssr-manifest.json`). A **current-status note** states Rspack
builds compile and server-render but **manifest files are not emitted
yet**, with **PR #3385** / issue **#1828** cited. **Known limitations**
now contrast Rspack v2’s native **`react-server-dom-rspack`** path with
React on Rails Pro’s **`react-on-rails-rsc` /
`react-server-dom-webpack`** approach via Rspack’s webpack compatibility
layer, plus added reference links.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
b0cdb52. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Clarified React Server Components guidance for transpilers (Babel vs
SWC) and build tools.
* Added caution that SWC-based RSC builds are wired but not end-to-end
verified; Babel remains the tested path in examples.
* Noted Rspack manifest generation status and current integration
approach, and linked related fixes and resources.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@justin808

Copy link
Copy Markdown
Member Author

Closing in favor of the native RSCRspackPlugin path tracked in #3488.

As documented in the verification update above and in #3488, the generated rscManifestPlugin.js helper in this PR is a confirmed runtime blocker. In a controlled A/B on the marketplace demo (same locally-built react-on-rails-rsc, swapping only the build config):

  • Native RSCRspackPlugin → 11/11 valid RSC routes render and hydrate.
  • This helper → production build succeeds with valid-looking manifests (38/38 entries, 0 missing), but 7/11 routes fail in the browser (React #419, ServerComponentFetchError #306, renderer Cannot find module './15.server-bundle.js').

Path forward (#3488): adopt the native RSCRspackPlugin in react-on-rails-rsc and make the demo route-hydration check a permanent CI gate (now merged as shakacode/react-on-rails-demo-marketplace-rsc#73). Rspack RSC runtime support stays documented as experimental until that gate is green. If generator wiring for the plugin is still needed, it will land as a separate, narrow generator-integration PR.

Closing rather than merging so the helper path is not shipped. The branch is left intact for reference.

@justin808 justin808 closed this Jun 3, 2026
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.

Rspack support for RSC

1 participant