Skip to main content

Rspack Compatibility with React Server Components

Status: Experimental — the generator scaffolds the native Rspack plugin and the proven runtime path, but the end-to-end gate is not yet wired into this repo's CI. See issue #3488.

This page documents the compatibility status of Rspack with React on Rails Pro's React Server Components (RSC) implementation.

Overview

React on Rails Pro's RSC implementation uses a three-bundle architecture (client, server, RSC). The generator supports Rspack — when assets_bundler: rspack is detected in shakapacker.yml, all RSC config files are created in config/rspack/ instead of config/webpack/, and the server/client configs are scaffolded with the native RSCRspackPlugin instead of RSCWebpackPlugin.

The RSC implementation depends on the react-on-rails-rsc npm package, which provides bundler-specific manifest plugins plus a shared loader:

  • WebpackPlugin (react-on-rails-rsc/WebpackPlugin) — generates client/server component manifest files under webpack.
  • RspackPlugin (react-on-rails-rsc/RspackPlugin) — the rspack-native equivalent (RSCRspackPlugin). It emits the same manifest JSON schema using only standard rspack public APIs, so the RSC runtime resolves client references identically. Exported from react-on-rails-rsc 19.0.5-rc.6+ (switch to 19.0.5 stable once published).
  • WebpackLoader (react-on-rails-rsc/WebpackLoader) — transforms 'use client' files into client reference proxies in the RSC bundle. Works under both webpack and rspack.

Compatibility Matrix

ComponentRspack CompatibleNotes
RSC bundle config (rscWebpackConfig.js)YesDoes not use WebpackPlugin; only uses loader + resolve settings
WebpackLoader (react-on-rails-rsc/WebpackLoader)YesStandard loader interface (this.resourcePath, source transform)
conditionNames: ['react-server', '...']YesRspack supports conditional exports resolution
resolve.alias (react-dom/server: false)YesRspack supports alias to false
LimitChunkCountPluginYesGenerated configs use bundler-agnostic bundler.optimize.LimitChunkCountPlugin
Loader chain (SWC + Babel)YesGenerated config handles both function and Array rule.use styles
Manifest plugin (RSCRspackPlugin)YesNative rspack plugin; emits the same manifest schema (see below)
WebpackPlugin (react-on-rails-rsc/WebpackPlugin)Not used on rspackReplaced by RSCRspackPlugin under rspack; remains the webpack-only plugin
Three-bundle build (RSC_BUNDLE_ONLY, SERVER_BUNDLE_ONLY)YesEnvironment variable routing is bundler-agnostic

Manifest Plugin: Native RSCRspackPlugin

The manifest plugin is the critical compatibility question. It generates react-client-manifest.json and react-server-client-manifest.json, which map client component file paths to their chunk IDs and bundle filenames. Without these manifests, the RSC runtime cannot resolve 'use client' component references during streaming.

Under webpack, this is RSCWebpackPlugin, which wraps React's react-server-dom-webpack/plugin and depends on webpack-internal APIs (webpack/lib/dependencies/*, webpack.AsyncDependenciesBlock, compilation.chunkGraph, the processAssets/thisCompilation/make hooks, etc.).

Under rspack, the generator instead scaffolds the native RSCRspackPlugin (react-on-rails-rsc/RspackPlugin). Rather than rely on Rspack's webpack-compatibility layer for those internal APIs, the native plugin emits the same manifest JSON schema using only standard rspack public APIs. It discovers 'use client' modules with a tagging loader, injects them as named async chunks, and walks compilation.chunkGroups at processAssets. Because the output schema is identical, the RSC runtime (buildServerRenderer / buildClientRenderer) works unchanged regardless of bundler. The two plugins share the same { isServer, clientReferences } options.

note

Why native instead of the webpack plugin under Rspack's compat layer? A controlled A/B on a real app showed the webpack-plugin path producing valid-looking manifests that still failed ~7/11 RSC routes at runtime under Rspack, while the native RSCRspackPlugin rendered and hydrated every route. The native plugin is therefore the supported Rspack path. The remaining work to drop the "experimental" label — publishing a stable react-on-rails-rsc ≥ 19.0.5 and wiring the demo route-hydration gate into this repo's CI — is tracked in issue #3488 (superseding the abandoned manifest-helper approach in PR #3385).

How the RSC Bundle Avoids the Plugin

The RSC bundle config (rscWebpackConfig.js) calls serverWebpackConfig(true), which skips adding the manifest plugin (RSCRspackPlugin under rspack, RSCWebpackPlugin under webpack). The RSC bundle only uses:

  1. The WebpackLoader to transform 'use client' files into client reference proxies
  2. conditionNames: ['react-server', '...'] to resolve React's server entry points
  3. Aliases to exclude react-dom/server from the RSC bundle

The manifest plugin is only added to the server and client bundles.

Testing with Rspack

To test RSC with Rspack in your project:

  1. Ensure assets_bundler: rspack is set in config/shakapacker.yml
  2. Run the RSC generator: rails generate react_on_rails:rsc
  3. Verify configs are in config/rspack/
  4. Build all three bundles and check for:
    • rsc-bundle.js in the output
    • react-client-manifest.json and react-server-client-manifest.json (from RSCRspackPlugin)
    • No Rspack compilation errors

Known Limitations

  1. React on Rails does not use Rspack's experimental native RSC system: As of Rspack v2, Rspack ships its own built-in RSC support (driven by builtin:swc-loader and rspackExperiments.reactServerComponents). React on Rails Pro does not use that experimental path. Its RSC integration is built on the react-on-rails-rsc package: manifest generation uses the native RSCRspackPlugin (standard rspack public APIs, not Rspack's webpack-compatibility layer), while the RSC bundle still uses the react-server-dom-webpack loader and runtime.

  2. The RSC bundle still uses the react-server-dom-webpack loader: Only the manifest plugin is bundler-native. The RSC bundle transforms 'use client' files with react-on-rails-rsc/WebpackLoader (which wraps React's react-server-dom-webpack node loader) under both bundlers. This loader is compatible with rspack.

  3. No official React Rspack support: The React team has not officially tested or endorsed the react-server-dom-webpack runtime with Rspack. The native RSCRspackPlugin is maintained by ShakaCode in react-on-rails-rsc.