Skip to content

docs: RSC + Rspack plugin implementation plan and findings (#3141)#3147

Open
AbanoubGhadban wants to merge 1 commit intomainfrom
claude/practical-haibt
Open

docs: RSC + Rspack plugin implementation plan and findings (#3141)#3147
AbanoubGhadban wants to merge 1 commit intomainfrom
claude/practical-haibt

Conversation

@AbanoubGhadban
Copy link
Copy Markdown
Collaborator

@AbanoubGhadban AbanoubGhadban commented Apr 15, 2026

Summary

Captures the investigation of #3141 and a concrete plan for implementing rspack support in the RSC plugin. Docs only — no code changes. Adds three documents under .claude/docs/ that together answer: what rspack's RSC story looks like today, which parts of react-on-rails-rsc are already compatible, and exactly how to make the remaining part (the plugin) work.

Key findings

  • Only RSCWebpackPlugin needs rewriting. The other four components in react-on-rails-rscWebpackLoader, server.node, client.node, client.browser — work with rspack as-is. Proven empirically by a 31-test suite on shakacode/react_on_rails_rsc#test/rspack-compatibility including a full encode→decode round trip with both sides bundled by rspack.
  • We will NOT adopt rspack's built-in RSC system (rspackExperiments.reactServerComponents + experiments.rsc.createPlugins() + react-server-dom-rspack). It's too coupled to rspack's experimental Layers + Rsbuild path. Instead, write our own plugin using standard bundler-compatible APIs.
  • Runtime compatibility is solid. Rspack emits __webpack_require__, __webpack_chunk_load__, and a mutable __webpack_require__.u — the three globals React's Flight client relies on — with identical semantics.
  • Manifest schema stays unchanged. Rspack's native manifest is nearly identical to RoR's (minor field name differences, one extra async field). Our rspack plugin emits RoR's existing schema; no changes to server.node.ts, client.node.ts, or client.browser.ts.
  • One known risk: react-server-dom-rspack@0.0.2 ships a 394-line chunk-cache patch over react-server-dom-webpack. May or may not affect RoR — decide in prototype.

Documents added

  1. rspack-rsc-support-state.md (533 lines) — state of official rspack RSC support as of 2026-04-14: verified react-server-dom-rspack exists, rspack v2 built-in RSC is live (PR web-infra-dev/rspack#12012), working pure-rspack demo built and validated.

  2. rsc-rspack-implementation-plan.md (46KB, 8 sections) — original high-level investigation: current architecture, compatibility matrix, 7 critical discussion points, 6 refactoring opportunities, 4-phase plan, 14-row risk matrix.

  3. rsc-rspack-plugin-implementation.md (NEW, 618 lines) — focused plugin plan; the decision doc for implementation. Covers:

    • What we verified empirically (31-test suite + pure-rspack demo)
    • Why only the plugin needs changing
    • Manifest schema comparison
    • Architecture decision (dual-path behind existing facade)
    • Discovery technique (loader-tag + module graph walk, not FS walk)
    • Chunk-splitting technique (AsyncDependenciesBlock without custom dep subclass)
    • Runtime compatibility risks (the chunk-cache patch)
    • 6-phase implementation plan
    • 7 known unknowns to validate in prototype

Why this is docs-only

The implementation work itself is blocked on Phase 0 (prototype) to validate seven specific unknowns (rspack dep-type for AsyncDependenciesBlock.addDependency, the chunk-cache issue, module ID formats, etc.). Rather than guess at these, the plan commits them to a short prototype and defers implementation until we have answers.

Test plan

Next steps after merge

  1. Start Phase 0 (prototype) from the plan in rsc-rspack-plugin-implementation.md
  2. Validate the seven open unknowns
  3. Proceed with phases 1-6 (webpack refactor → rspack plugin → optional chunk-cache patch → generator → tests → docs)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added three comprehensive planning documents detailing React Server Components support with rspack, including architecture analysis, compatibility assessment, implementation phases, configuration guidance, and risk evaluation for future development.

Investigation of issue #3141 (revise Rspack support and plan RSC + Rspack
compatibility). Three docs captured under .claude/docs/:

1. rspack-rsc-support-state.md — state of official Rspack RSC support
   as of 2026-04-14. Rspack v2 shipped built-in RSC (PR #12012); we
   decide NOT to adopt it for React on Rails (too coupled to their
   experiments flag + Layers + rsbuild-plugin-rsc path).

2. rsc-rspack-implementation-plan.md — original high-level investigation
   plan: current architecture, compatibility analysis, 7 critical
   discussion points, 6 refactoring opportunities, phased plan with
   risk matrix.

3. rsc-rspack-plugin-implementation.md — focused plugin plan (this is
   the decision doc for implementation):
   - Only RSCWebpackPlugin needs rewriting; the other 4 components
     (WebpackLoader, server.node, client.node, client.browser) are
     rspack-compatible as-is (proven by 31-test suite on
     shakacode/react_on_rails_rsc#test/rspack-compatibility).
   - Dual-path plugin (webpack path unchanged, rspack path new) behind
     the existing RSCWebpackPlugin facade.
   - Rspack path uses standard bundler APIs only — no
     rspackExperiments.reactServerComponents flag, no
     rspack.experiments.rsc.createPlugins(), no Layers machinery.
   - Better discovery technique than current FS walk: loader tags
     "use client" modules during parse, plugin walks the module graph
     via compilation.hooks.finishModules.
   - Known risk: react-server-dom-rspack ships a 394-line chunk-cache
     patch over react-server-dom-webpack. Need to validate in
     prototype whether RoR hits the same bug.
   - Six-phase implementation: prototype → webpack refactor → rspack
     plugin → optional chunk-cache patch → generator → tests → docs.

Companion assets:
- shakacode/react_on_rails_rsc#test/rspack-compatibility — 31 runtime
  compatibility tests for the 4 non-plugin components
- /mnt/ssd/demos/rspack-rsc-pure — working pure-rspack RSC demo
  (no React on Rails, validates the stack is viable today)

These docs replace the need for further investigation. Implementation
can start from Phase 0 (prototype) in the plugin doc.

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

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

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: e9559d0d51

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


### 1.3 Webpack internals the plugin reaches into

From `packages/react-on-rails-rsc/src/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js` (vendored copy inside the `react-on-rails-rsc` repo at `/mnt/ssd/react-on-rails-rsc/src/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js:12-19`, 409 lines total):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Replace machine-local paths with repository links

This plan documents evidence using absolute paths like /mnt/ssd/..., which are only valid on the author’s machine; collaborators cannot open these references, so key verification points in the investigation become non-reproducible. Please switch these citations to repo-relative paths or GitHub permalinks so the documented findings can be checked by anyone reviewing or implementing the plan.

Useful? React with 👍 / 👎.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 15, 2026

Greptile Summary

Docs-only PR adding three .claude/docs/ files that capture the full investigation of RSC + rspack compatibility and lay out a concrete implementation plan. The research is thorough, empirically grounded (31-test suite, working pure-rspack demo), and the plugin architecture decision (dual-path single facade, module-graph discovery, AsyncDependenciesBlock without custom dep subclass) is well-reasoned. All findings are P2 style/consistency issues in the supporting documents.

Confidence Score: 5/5

Safe to merge — docs-only, no code changes, all findings are P2 consistency/clarity issues.

No code changes. All remaining findings are P2: a stale claim in the older investigation doc (contradicted and superseded by companion docs in the same PR), machine-local /mnt/ssd/ paths in references sections, and a missing "partially superseded" banner. None affect the correctness of the implementation plan itself.

.claude/docs/rsc-rspack-implementation-plan.md — stale §3.2.c claim and machine-local paths in §8 are the only items worth a follow-up edit.

Important Files Changed

Filename Overview
.claude/docs/rsc-rspack-implementation-plan.md Original high-level investigation doc (644 lines); contains a factually stale claim (§3.2.c says react-server-dom-rspack doesn't exist, contradicted by the companion state doc), unexported /mnt/ssd/ machine-local paths in §8, and no "superseded" banner despite being partially replaced by the plugin-implementation doc.
.claude/docs/rsc-rspack-plugin-implementation.md Focused plugin decision doc (618 lines); well-structured with clear empirical backing (31-test suite), dual-path architecture decision, manifest schema comparison, 6-phase plan, and 7 known unknowns. Minor issue: local /mnt/ssd/ paths in §11 prototype references.
.claude/docs/rspack-rsc-support-state.md Thorough, well-cited state-of-the-art survey (533 lines) of rspack RSC support as of 2026-04-14; covers official packages, release timelines, community context, and known limitations with no identified issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["RSCWebpackPlugin constructor\n(facade — unchanged export)"] --> B{"bundler.rspackVersion\nis a string?"}
    B -->|Yes — rspack| C["RSCRspackPlugin path\n(new file)"]
    B -->|No — webpack| D["Existing webpack path\n(unchanged)"]

    C --> E["Tiny loader: detect\n'use client' directive\nRecord in shared Set"]
    E --> F["compilation.hooks.finishModules\nCollect all tagged modules"]
    F --> G["AsyncDependenciesBlock\nper tagged module\n(no custom dep subclass)"]
    G --> H["processAssets STAGE_REPORT\nWalk chunkGraph → emit JSON"]

    D --> I["FS walk + acorn-loose parse\n(current behavior)"]
    I --> J["ClientReferenceDependency\nextends ModuleDependency"]
    J --> K["AsyncDependenciesBlock\nper 'use client' file"]
    K --> L["processAssets STAGE_REPORT\nWalk chunkGraph → emit JSON"]

    H --> M["react-client-manifest.json\n+ react-ssr-manifest.json\n(identical schema for both paths)"]
    L --> M
Loading

Reviews (1): Last reviewed commit: "docs: Add RSC + Rspack plugin implementa..." | Re-trigger Greptile


- **3.2.a — It works.** Runtime test passes; manifests generate correctly. Minimal work required; update docs only.
- **3.2.b — Build-time plugin fails, runtime works.** We need to write a replacement manifest plugin using rspack-native APIs (`Compilation.PROCESS_ASSETS_STAGE_REPORT` + `sources.RawSource` are supported). The replacement must produce identical JSON shape so `buildServerRenderer` / `buildClientRenderer` keep working unchanged.
- **3.2.c — Runtime breaks too.** We need to either (i) use a bundled `react-server-dom-rspack` if/when it exists, or (ii) wait for rspack's built-in RSC support. There's no evidence a `react-server-dom-rspack` package exists as of 2026-04.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Stale claim contradicts companion doc

This line states react-server-dom-rspack doesn't exist "as of 2026-04", but rspack-rsc-support-state.md (added in this same PR) documents that react-server-dom-rspack@0.0.2 was published on 2026-03-14 and is available on npm. A developer reading only this document would get a factually incorrect picture of the fallback options. Since rsc-rspack-plugin-implementation.md deliberately decided not to use it (§3.3), the stale claim in this contingency branch should be corrected to reflect reality.

Suggested change
- **3.2.c — Runtime breaks too.** We need to either (i) use a bundled `react-server-dom-rspack` if/when it exists, or (ii) wait for rspack's built-in RSC support. There's no evidence a `react-server-dom-rspack` package exists as of 2026-04.
**3.2.c — Runtime breaks too.** We need to either (i) use `react-server-dom-rspack` (now exists at `0.0.2`, maintained by SyMind/ByteDance — but we're NOT adopting it; see `rsc-rspack-plugin-implementation.md` §3 for rationale) or (ii) wait for rspack's built-in RSC support.

Comment on lines +614 to +621

- `/mnt/ssd/react-on-rails-rsc/src/WebpackPlugin.ts` — `RSCWebpackPlugin` wrapper
- `/mnt/ssd/react-on-rails-rsc/src/WebpackLoader.ts` — the `use client` transform loader
- `/mnt/ssd/react-on-rails-rsc/src/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js` — **the critical 409-line vendored React plugin** using all the webpack internals
- `/mnt/ssd/react-on-rails-rsc/src/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js:58-112` — proof that runtime uses `__webpack_require__` et al
- `/mnt/ssd/react-on-rails-rsc/src/{client.node,client.browser,server.node}.ts` — the shakacode-owned API surface on top of React's internals
- `/mnt/ssd/shakacode-related/shakapacker/package/plugins/rspack.ts`, `rules/rspack.ts` — reference for how shakapacker wires rspack today
- `/mnt/ssd/shakacode-related/shakapacker/package.json:54-55, 102-103` — rspack peer-dep `^1.0.0` (needs bump for v2)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Local machine paths not accessible to other developers

The "External source files" section and the companion plugin-implementation doc (§11 "Working prototype") embed /mnt/ssd/... absolute paths that only exist on the original author's machine. Any developer (or future Claude Code agent) following up on this investigation to start Phase 0 will hit dead-ends on these references. The same pattern appears in rsc-rspack-plugin-implementation.md lines 58 and 608–610.

Consider replacing each /mnt/ssd/... path with the corresponding public URL (GitHub branch/repo) where one exists, or annotating them explicitly as "author-local, not reproducible" so readers know to substitute their own clones.

Comment on lines +1 to +14
# RSC + Rspack Implementation Plan

Planning/investigation doc for issue [shakacode/react_on_rails#3141](https://github.com/shakacode/react_on_rails/issues/3141).

**Audience:** React on Rails + Shakapacker maintainer with strong webpack knowledge and no deep rspack internals experience.

**Goal:** Drive a decision on _how_ to make React Server Components (RSC) run end-to-end under rspack before a single line of production code is written.

**Status tags used in this doc:**
- **VERIFIED** — confirmed by source reading in this repo
- **NEEDS VERIFICATION** — plausible but not runtime-tested
- **UNKNOWN** — open question
- **ASSUMED** — working assumption; flag before committing

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Missing "partially superseded" status banner

rsc-rspack-plugin-implementation.md explicitly calls this document "superseded by this doc for plugin specifics" in its companion-docs header. However, this document carries no equivalent notice — it still presents open questions (§3.2, §3.4, §6 Q1–Q13) that have since been answered by the two companion docs. A reader discovering this file first will spend time on resolved questions without realising they're stale.

Consider adding a status notice at the top, e.g.:

> **Status note (2026-04-14):** The plugin-specific findings in this document have been superseded by [`rsc-rspack-plugin-implementation.md`](./rsc-rspack-plugin-implementation.md). The architecture overview (§1–§2) and risk matrix (§7) remain valid as background context. See that doc for the final decisions on all critical discussion points in §3.

Comment on lines +56 to +63
### 1.2 A working pure-rspack RSC demo (no React on Rails)

Location: `/mnt/ssd/demos/rspack-rsc-pure`. Runs at http://localhost:3000. Produces full HTML server-side with embedded Flight payload. Uses:
- `@rspack/core@2.0.0-rc.2` (released 2026-04-14)
- `react-server-dom-rspack@0.0.2` (maintained by SyMind / ByteDance)
- `react@19.2.0` + Express 5 + `worker_threads`

This proves RSC is buildable with rspack end-to-end today, outside React on Rails.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Local machine demo path not reproducible

/mnt/ssd/demos/rspack-rsc-pure/ and http://localhost:3000 reference an environment specific to the original author's machine. When a developer (or future Claude agent) picks up Phase 0, these references provide no actionable way to inspect or reproduce the demo. The same issue applies to /mnt/ssd/demos/ror-rspack-demo/ and /mnt/ssd/react-on-rails-rsc/ in §11.

If the pure-rspack demo was derived from rstackjs/rspack-rsc-examples (already cited in §11), that URL is the correct public pointer. Replace the local path with a link to the repo/commit used, or note which example was the starting point.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 15, 2026

Review

Overall: well-researched, ready to merge with one required fix and a few follow-up suggestions. The three docs together provide a solid grounding for the RSC + rspack implementation — the empirical 31-test suite is strong evidence, the risk matrix is thorough, and the phased plan correctly defers production code until the prototype resolves the seven known unknowns.


Required before merge

CLAUDE.md is not updated.

The three new files are not listed in CLAUDE.md's ## Claude-Specific Workflow section, which is the index Claude Code agents read to know which docs to consult. Without that listing, agents working on RSC/rspack tasks won't know these docs exist — which defeats the purpose of storing them in .claude/docs/.

Add entries for all three:

```md

  • `.claude/docs/rspack-rsc-support-state.md`
  • `.claude/docs/rsc-rspack-implementation-plan.md`
  • `.claude/docs/rsc-rspack-plugin-implementation.md`
    ```

Should address (follow-up acceptable)

Local /mnt/ssd/ paths throughout both planning docs. Several sections cite /mnt/ssd/react-on-rails-rsc/..., /mnt/ssd/demos/rspack-rsc-pure/, etc. as source references. These are dev-machine-specific paths that don't exist for any other contributor. Inline comments call out the specific locations. Each should be replaced with its corresponding GitHub URL or removed.

Overlap between the two planning docs is potentially confusing. rsc-rspack-implementation-plan.md contains three unresolved scenarios for §3.2 (a/b/c: does the plugin work? does it fail? does runtime fail too?). rsc-rspack-plugin-implementation.md resolves all three — scenario (b) is confirmed, runtime is fine, only the plugin needs rewriting. A reader who encounters the high-level plan first will see outdated uncertainty. Consider adding a callout near the top of rsc-rspack-implementation-plan.md:

```md

Note (2026-04-14): The scenarios in §3.2 have been resolved by empirical testing. See
rsc-rspack-plugin-implementation.md for current findings and the active decision doc.
```


Minor

File naming inconsistency. Two docs are named rsc-rspack-*; one is rspack-rsc-*. This affects alphabetic sort and discoverability. Consider renaming rspack-rsc-support-state.mdrsc-rspack-support-state.md.

Document freshness. rspack-rsc-support-state.md has a Research date: 2026-04-14 header — helpful for calibrating version-specific claims. The other two docs don't carry a date. Adding a **Last updated:** line to those would help future maintainers judge which sections need revisiting.


Technical accuracy check

No issues found. The compatibility scorecard (§2 in the plugin plan), the manifest schema comparison (§4), and the runtime ABI table (§1.3) are internally consistent with the empirical data from the test suite. The decision to avoid rspack's built-in RSC system is well-justified given the tight coupling to rspackExperiments + Layers + Rsbuild. The rspackVersion detection heuristic is reasonable — see inline comment for a documentation suggestion.


### 1.3 Webpack internals the plugin reaches into

From `packages/react-on-rails-rsc/src/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js` (vendored copy inside the `react-on-rails-rsc` repo at `/mnt/ssd/react-on-rails-rsc/src/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js:12-19`, 409 lines total):
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.

This cites /mnt/ssd/react-on-rails-rsc/... as the source for the table of webpack internals. That path is a dev-machine-specific local clone and won't exist for any other contributor.

Replace with the GitHub path, e.g.:

From `packages/react-on-rails-rsc/src/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js:12-19`
(in the `shakacode/react_on_rails_rsc` repo — branch `test/rspack-compatibility` or main)

Comment on lines +613 to +626
### External source files (outside this repo)

- `/mnt/ssd/react-on-rails-rsc/src/WebpackPlugin.ts` — `RSCWebpackPlugin` wrapper
- `/mnt/ssd/react-on-rails-rsc/src/WebpackLoader.ts` — the `use client` transform loader
- `/mnt/ssd/react-on-rails-rsc/src/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js` — **the critical 409-line vendored React plugin** using all the webpack internals
- `/mnt/ssd/react-on-rails-rsc/src/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js:58-112` — proof that runtime uses `__webpack_require__` et al
- `/mnt/ssd/react-on-rails-rsc/src/{client.node,client.browser,server.node}.ts` — the shakacode-owned API surface on top of React's internals
- `/mnt/ssd/shakacode-related/shakapacker/package/plugins/rspack.ts`, `rules/rspack.ts` — reference for how shakapacker wires rspack today
- `/mnt/ssd/shakacode-related/shakapacker/package.json:54-55, 102-103` — rspack peer-dep `^1.0.0` (needs bump for v2)

### Rspack references

- Rspack docs: https://rspack.dev/
- Rspack webpack API compatibility: https://rspack.dev/guide/migration/webpack-compat
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.

This whole "External source files" block lists /mnt/ssd/... dev-machine paths. They're meaningless to anyone else and will mislead a future agent trying to follow these references.

Each entry has a corresponding GitHub location:

  • react-on-rails-rsc files → https://github.com/shakacode/react_on_rails_rsc/blob/<branch>/src/...
  • shakapacker files → https://github.com/shakacode/shakapacker/blob/main/package/...

Either replace with the GitHub URLs or drop this section and rely on the repo link in §8's "Tracking issues and PRs".

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cf2d2134-229c-44a7-bf97-e36310086ffc

📥 Commits

Reviewing files that changed from the base of the PR and between de5b53a and e9559d0.

📒 Files selected for processing (3)
  • .claude/docs/rsc-rspack-implementation-plan.md
  • .claude/docs/rsc-rspack-plugin-implementation.md
  • .claude/docs/rspack-rsc-support-state.md

Walkthrough

Three new planning and investigation documents have been added to the .claude/docs/ directory, detailing React Server Components (RSC) support implementation for rspack. The documents outline the current RSC architecture, build-time compatibility analysis, a dual-path implementation strategy, and the current state of native rspack RSC support.

Changes

Cohort / File(s) Summary
RSC and Rspack Documentation
.claude/docs/rsc-rspack-implementation-plan.md, .claude/docs/rsc-rspack-plugin-implementation.md, .claude/docs/rspack-rsc-support-state.md
Added three planning documents: an end-to-end implementation approach for RSC under rspack with phased roadmap; a detailed dual-path plugin strategy distinguishing webpack vs. rspack paths; and a consolidated status of native rspack RSC support (v1 vs. v2, configuration guidance, limitations, and references).

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐰 Three scrolls of wisdom, carefully penned,
Mapping RSC's rspack bend,
From planning to phase, we chart the way,
With strategies wise and risks held at bay!
Hop onward, brave bundlers, let's build it all,
Tomorrow brings code to answer the call! 📜✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'docs: RSC + Rspack plugin implementation plan and findings' accurately reflects the changeset: three documentation files detailing RSC-rspack compatibility investigation, implementation strategy, and findings.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/practical-haibt

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


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.

constructor(options: Options) {
const bundler = options.bundler || require('webpack');
const isRspack = typeof bundler.rspackVersion === 'string';

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 rspackVersion property used here as a discriminator is not part of rspack's documented public API. Before shipping this, confirm it's stable across rspack versions by checking @rspack/core's main export (node_modules/@rspack/core/dist/index.js).

If it is present and stable, add a comment explaining the heuristic so a future maintainer doesn't silently break it:

// rspack exposes `rspackVersion` on its top-level export; webpack does not.
// This is our bundler-detection heuristic — verify it exists in @rspack/core ≥ 1.x.
const isRspack = typeof bundler.rspackVersion === 'string';

If it turns out to be undocumented, a more robust alternative is checking the module ID:

const isRspack = require.resolve('@rspack/core') === require.resolve(bundler) ||
                 typeof bundler.rspackVersion === 'string';

Comment on lines +606 to +609

### Working prototype (for reference during Phase 0)
- `/mnt/ssd/demos/rspack-rsc-pure/` — running pure-rspack RSC app
- `/mnt/ssd/demos/ror-rspack-demo/` — React on Rails + rspack + no RSC (from earlier in this investigation)
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 issue as the implementation plan's "External source files" section: these are dev-machine local paths (/mnt/ssd/...) that won't exist for another contributor or a CI agent following this plan.

Replace with GitHub links:

  • rspack-rsc-pure demo → link to the rstackjs/rspack-rsc-examples repo cited in §11 References (already there)
  • react-on-rails-rsc test branch → https://github.com/shakacode/react_on_rails_rsc/tree/test/rspack-compatibility (already cited in §1.1)

This section can probably just be dropped since the GitHub links appear in §11 already.

AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 15, 2026
Implements the rspack equivalent of RSCWebpackPlugin, producing the same
manifest JSON schema React on Rails already consumes. Zero dependencies
on rspack's experimental RSC system (rspackExperiments.reactServerComponents,
experiments.rsc.createPlugins, react-server-dom-rspack). Uses only
standard bundler-compatible public APIs, so it works on both rspack and
webpack 5.

Architecture (follows plan in shakacode/react_on_rails#3147):

- loader.ts — tiny "use client" detector. Checks for a directive at the
  top of each source (single/double quote, optional semicolon, allows
  leading whitespace/BOM/shebang). Records tagged module's resource path
  on the compilation object.

- shared.ts — single string constant for the loader↔plugin channel key.

- plugin.ts — the main plugin. On apply():
    1. Injects the loader rule at position 0 with `enforce: 'pre'` so it
       runs before transpilers and sees original source.
    2. Hooks `compilation.hooks.processAssets` at PROCESS_ASSETS_STAGE_REPORT
       to walk tagged modules, look up their chunks via
       `compilation.chunkGraph.getModuleChunks(module)`, and emit the
       manifest JSON via `compilation.emitAsset`.
    3. Resolves bundler namespace automatically (compiler.rspack or
       compiler.webpack); falls back to require('@rspack/core') or
       require('webpack').

Key design choices:

- Module graph walk instead of FS walk. Dead code is automatically
  excluded (unreachable "use client" files aren't parsed → not tagged).
  Verified by tests/rspack-plugin/fixtures/dead-code.

- No custom ModuleDependency subclass. Avoids the webpack-internal API
  that rspack doesn't expose. Relies on chunk-graph walking instead.

- Manifest schema unchanged from the webpack plugin:
    { moduleLoading: { prefix, crossOrigin },
      filePathToModuleMetadata: { "file:///...": { id, chunks, name } } }
  so server.node.ts / client.node.ts / client.browser.ts work unchanged.

- No chunk force-splitting in initial impl. Manifest is still correct
  (chunks point to whatever chunks actually contain the tagged modules).
  AsyncDependenciesBlock-based splitting can be added later as an
  optimization without breaking the schema.

Testing (tests/rspack-plugin/ — 29 tests, all passing):

- manifest emission (5 tests) — default filenames for client vs. server,
  custom filename, valid JSON, deterministic.

- top-level shape (7 tests) — exact keys, moduleLoading.prefix reflects
  publicPath, crossOrigin handles all three values (false/anonymous/
  use-credentials).

- client-module detection (5 tests) — includes "use client" files,
  excludes non-"use client" files, handles nested files, excludes dead
  code (unreachable files), produces empty manifest when no clients.

- directive edge cases (7 tests) — single/double quote, with/without
  semicolon, leading whitespace, rejects directive in comment, rejects
  directive after an import (must be first statement).

- per-entry shape (5 tests) — keys are file:// URLs, entries have
  id/chunks/name, name is "*", id is non-empty string, chunks is a flat
  pair-array of [id, filename, ...].

- option validation — throws on missing or non-boolean isServer.

Tests follow rspack-manifest-plugin's pattern: fixture-per-scenario,
helper compile() function that spawns rspack in a child process,
assertions on parsed manifest JSON. Total suite runtime: ~8s.

Exports added via package.json:
  react-on-rails-rsc/RspackPlugin  — the plugin class
  react-on-rails-rsc/RspackLoader  — the loader (for users who need it
                                     directly; the plugin injects it
                                     automatically)

Related:
- shakacode/react_on_rails#3147 — design doc and investigation
- shakacode/react_on_rails#3141 — parent issue
- test/rspack-compatibility branch — 31 tests proving the other 4
  components of react-on-rails-rsc are rspack-compatible unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant