Skip to content

RSCWebpackPlugin defaults to scanning project root and can bundle vendor gem templates #3201

@justin808

Description

@justin808

Problem

While fixing CI for the Hacker News RSC demo, the webpack build failed only on GitHub Actions because RSCWebpackPlugin defaults clientReferences to { directory: ".", recursive: true, include: /\.(js|ts|jsx|tsx)$/ }.

In CI, ruby/setup-ruby installs gems under vendor/bundle. That means the RSC plugin scans the vendored react_on_rails gem, sees "use client" example/template files under lib/generators/react_on_rails/templates/rsc/base/..., and adds them as client references for the app bundle. Webpack then tries to compile generator template files as application modules.

Evidence

Demo PR: shakacode/react-on-rails-demo-hacker-news-rsc#13

Failed CI run: https://github.com/shakacode/react-on-rails-demo-hacker-news-rsc/actions/runs/24822632175

Earlier failing logs showed imports from:

./vendor/bundle/ruby/3.4.0/gems/react_on_rails-16.4.0.rc.5/lib/generators/react_on_rails/templates/rsc/base/app/javascript/src/HelloServer/components/LikeButton.jsx
./vendor/bundle/ruby/3.4.0/gems/react_on_rails-16.4.0.rc.5/lib/generators/react_on_rails/templates/rsc/base/app/javascript/src/HelloServer/components/LikeButton.tsx

Import trace went through react-on-rails-pro/registerServerComponent/client and react-on-rails-rsc/dist/react-server-dom-webpack/client.browser.js, then into generated packs such as app/javascript/packs/generated/HNItemPage.js.

Local workaround

The demo fixes this by explicitly scoping client-reference discovery to Shakapacker application source:

const { config } = require("shakapacker");
const { resolve } = require("path");

const rscClientReferences = {
  directory: resolve(config.source_path),
  recursive: true,
  include: /\.(js|ts|jsx|tsx)$/,
};

new RSCWebpackPlugin({ isServer: false, clientReferences: rscClientReferences });
new RSCWebpackPlugin({ isServer: true, clientReferences: rscClientReferences });

A targeted guard check also passed locally: adding a temporary "use client" JSX file outside app/javascript no longer affects the app webpack build once the plugin is scoped.

Suggested product improvement

React on Rails / React on Rails Pro should avoid requiring every app to know about this footgun. Possible fixes:

  • Default generated RSC webpack config to clientReferences: { directory: resolve(config.source_path), recursive: true, include: /\.(js|ts|jsx|tsx)$/ } instead of relying on the plugin root default.
  • Document the required clientReferences scoping in the RSC setup guide.
  • Consider wrapping RSCWebpackPlugin with a React on Rails helper that uses Shakapacker source_path automatically.

Why it matters

This failure is CI-specific for many Rails apps because local development often uses globally installed gems, while GitHub Actions commonly installs bundled gems into vendor/bundle. That makes the default behavior hard to reproduce locally and confusing for demo users.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Target this sprintbugruntime-fixUser-facing behavior fix

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions