Skip to content

fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366)#3368

Merged
justin808 merged 4 commits into
mainfrom
jg-conductor/3366-fix-issue
May 24, 2026
Merged

fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366)#3368
justin808 merged 4 commits into
mainfrom
jg-conductor/3366-fix-issue

Conversation

@justin808
Copy link
Copy Markdown
Member

@justin808 justin808 commented May 23, 2026

Summary

Fixes #3366 — a 16.7.0-rc.0 regression where the RSC client manifest (react-client-manifest.json) is silently dropped from the Pro Node Renderer upload, breaking server-component rendering with ENOENT on the renderer side.

  • Add a side-effect import of react-on-rails-rsc/client.browser at the top of wrapServerComponentRenderer/client.tsx. RSCWebpackPlugin scans every parsed module's resource path for an exact match against require.resolve("../client.browser.js") and only emits react-client-manifest.json when it finds one. Previously the client runtime was reachable only through a three-level transitive chain (wrapServerComponentRenderer/clientgetReactServerComponent.clientreact-on-rails-rsc/client.browser); any tooling that severed a link in that chain silently dropped the manifest and produced the misleading Client runtime at react-on-rails-rsc/client was not found warning. The direct import keeps the runtime resource in the client module graph regardless of how downstream tooling handles transitive default imports.
  • Add a structural regression test that fails if the side-effect import is removed from either the source or the compiled lib output.
  • Add a webpack-level regression test that compiles wrapServerComponentRenderer/client.tsx with the old transitive getReactServerComponent.client edge replaced by a stub, then asserts RSCWebpackPlugin still emits react-client-manifest.json. This proves the direct import itself preserves the manifest.

Why

Issue #3366 reports that the warning + missing manifest first appears when the consuming app upgrades to react_on_rails_pro / react-on-rails-pro / react-on-rails-pro-node-renderer 16.7.0-rc.0 from 16.6.0, even with react-on-rails-rsc@19.0.4 and shakapacker@10.0.0 unchanged. The actual chain in source/lib is intact between both versions, and the issue does not reproduce on the in-tree dummy app or a clean clone of the tutorial PR — but the user's environment clearly does see clientFileNameFound = false from the upstream RSC plugin. The defensive direct import removes that fragility: even if a future transpiler/tree-shaker decides getReactServerComponent.client is "unused" or rewrites the path, the side-effect import keeps client.browser in the graph and the plugin always emits the manifest.

Evaluation

Confirmed the fix addresses the bug mechanism. The RSC plugin decides whether to write react-client-manifest.json by seeing the react-on-rails-rsc/client.browser module in the client compilation. The direct side-effect import is an appropriate fix because it changes build graph visibility without changing renderer runtime behavior.

I verified the new behavior test is meaningful by temporarily removing the direct import: with the old transitive helper path stubbed out, webpack emitted the expected Client runtime at react-on-rails-rsc/client was not found warning and the test failed. Restoring the import made the same test pass and emit react-client-manifest.json. The Pro dummy build also emits both react-client-manifest.json and react-server-client-manifest.json successfully.

Test plan

  • pnpm --filter react-on-rails-pro exec jest tests/wrapServerComponentRenderer.client.manifest.test.js --runInBand passes
  • Red check: temporarily removing import 'react-on-rails-rsc/client.browser'; makes the new manifest test fail with the upstream missing-client-runtime warning
  • pnpm --filter react-on-rails-pro exec jest tests/wrapServerComponentRenderer.client.manifest.test.js tests/wrapServerComponentRenderer.client.imports.test.ts --runInBand passes
  • pnpm --filter react-on-rails-pro exec jest tests/createReactOnRailsPro.test.ts --runInBand passes
  • pnpm --filter react-on-rails-pro run test:non-rsc passes: 7 suites, 58 tests
  • pnpm --filter react-on-rails-pro run type-check passes
  • pnpm run lint passes
  • (cd react_on_rails && bundle exec rubocop) passes
  • (cd react_on_rails_pro && bundle exec rubocop --ignore-parent-exclusion) passes; RuboCop prints deprecation warnings from dependencies but reports no offenses
  • pnpm exec prettier --check packages/react-on-rails-pro/tests/wrapServerComponentRenderer.client.manifest.test.js packages/react-on-rails-pro/tests/fixtures/rsc-manifest/getReactServerComponent.client.stub.ts passes
  • RAILS_ENV=test NODE_ENV=development bundle exec bin/shakapacker from react_on_rails_pro/spec/dummy passes and emits react-client-manifest.json plus react-server-client-manifest.json
  • git diff --check passes
  • Pre-commit and pre-push hooks passed while committing and pushing 3013f9d90
  • Full-repo pnpm start format.listDifferent is blocked by an existing ignored .context/plans/issue-3366-reproduction-plan.md formatting issue; the PR files pass direct Prettier checks
  • Verify CI passes on this PR
  • Verify shakacode/react-webpack-rails-tutorial#740 unblocks once a new RC build with this fix is published

🤖 Generated with Claude Code


Note

Medium Risk
Touches Pro RSC client entrypoint bundling to force inclusion of the RSC client runtime, which can affect build output and hydration behavior if misconfigured. Added tests reduce regression risk, but changes are in a critical RSC packaging path.

Overview
Restores reliable React Server Components hydration for Pro by adding a top-level side-effect import of react-on-rails-rsc/client.browser in wrapServerComponentRenderer/client.tsx, ensuring RSCWebpackPlugin consistently emits react-client-manifest.json even when transitive imports are disrupted.

Adds regression coverage: a structural test that enforces the presence of the side-effect import (source and built lib when available) and a webpack-level test that stubs getReactServerComponent.client to prove manifest emission still occurs. Updates knip.ts to ignore dynamically referenced test fixtures and records the fix in CHANGELOG.md.

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

Summary by CodeRabbit

  • Bug Fixes

    • Restored inclusion of the client runtime so the client manifest is emitted, preventing React Server Components hydration failures in certain build setups.
  • Tests

    • Added regression tests to ensure the client runtime import is preserved and the client manifest is emitted during bundling.
  • Documentation

    • Updated CHANGELOG with the fix.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 23, 2026

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

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: ecb36623-8300-4622-bb8c-a5bf4684f1a1

📥 Commits

Reviewing files that changed from the base of the PR and between 8952812 and 1bb24cc.

📒 Files selected for processing (1)
  • knip.ts

Walkthrough

Adds a top-level side-effect import of react-on-rails-rsc/client.browser to the Pro client bundle, a Jest regression test verifying that import in source and compiled output, an in-memory webpack test ensuring react-client-manifest.json is emitted, a small RSC stub fixture, and a changelog entry documenting the fix.

Changes

Pro RSC Client Manifest Restoration

Layer / File(s) Summary
Client runtime side-effect import and regression test
packages/react-on-rails-pro/src/wrapServerComponentRenderer/client.tsx, packages/react-on-rails-pro/tests/wrapServerComponentRenderer.client.imports.test.ts, CHANGELOG.md
Adds a top-level side-effect import of react-on-rails-rsc/client.browser to keep the client runtime in the webpack module graph so RSCWebpackPlugin emits react-client-manifest.json. Adds a Jest test that asserts the side-effect import exists in source and (when present) compiled output, and updates CHANGELOG.md with the fix.
Manifest emission harness and RSC stub fixture
packages/react-on-rails-pro/tests/wrapServerComponentRenderer.client.manifest.test.js, packages/react-on-rails-pro/tests/fixtures/rsc-manifest/getReactServerComponent.client.stub.ts
Adds an in-memory webpack test that runs RSCWebpackPlugin in client mode (injecting a stub RSC via NormalModuleReplacementPlugin), asserts no runtime-missing warning, and verifies react-client-manifest.json is emitted; includes the stub fixture used by the test.

Sequence Diagram

sequenceDiagram
  participant ProClient as wrapServerComponentRenderer.client
  participant Webpack
  participant RSCPlugin as RSCWebpackPlugin
  participant FS as Filesystem
  ProClient->>Webpack: include side-effect import 'react-on-rails-rsc/client.browser'
  Webpack->>RSCPlugin: client runtime present in module graph
  RSCPlugin->>FS: emit react-client-manifest.json
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🐰 A missing manifest once caused a frown,
One hop, one import, and the graph sticks around,
Webpack sings, the plugin writes the file,
Hydration returns and testers smile,
Hooray — the client-runtime's found! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a top-level side-effect import to preserve the react-on-rails-rsc/client.browser module in the client bundle to fix manifest generation.
Linked Issues check ✅ Passed All code changes directly address the primary objective from #3366: ensuring react-client-manifest.json is emitted by preserving the client runtime in the module graph via a top-level side-effect import and adding regression tests.
Out of Scope Changes check ✅ Passed All changes are within scope: the source code fix, structural regression test, webpack-level regression test, test fixture stub, and knip configuration update directly support the fix for issue #3366.

✏️ 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/3366-fix-issue

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

knip.ts

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.


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.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 23, 2026

Code Review

Overview

Minimal, targeted fix for a real regression (#3366). The root cause analysis is solid: RSCWebpackPlugin does an exact-path scan of each parsed module rather than a full transitive-graph walk, so a three-level transitive import can silently disappear under tree-shaking or custom webpack transformations. Adding a direct side-effect import is the correct surgical fix.

Strengths

  • The change is one line and hard to misapply.
  • The comment in client.tsx captures the why clearly enough to prevent someone from removing the import thinking it is unused.
  • A regression test was included, which is the right instinct.
  • CHANGELOG entry is thorough.

Issues

1. Test silently passes when lib/ is absent (high priority)

wrapServerComponentRenderer.client.imports.test.ts line 39 uses a bare return; to exit the test body when the compiled lib/ directory is missing. In Jest a test that returns without making any assertions is counted as a pass — it does not appear as skipped, pending, or inconclusive. This means:

  • On a fresh checkout (no prior build) CI always marks this test green, even if the compiled output is broken or the import was stripped.
  • Future refactors that accidentally drop the import from the compiled output will go undetected until a full build + manual run.

The right idiom is a conditional registration at the describe level:

const libExists = fs.existsSync(libPath);
(libExists ? it : it.skip)('keeps the same runtime present in the compiled lib output', () => {
  const compiled = fs.readFileSync(libPath, 'utf8');
  expect(compiled).toMatch(/import\s+['"]react-on-rails-rsc\/client\.browser['"]\s*;?/);
});

This shows explicitly as "skipped" in the test report when lib is absent, rather than silently green.

2. Source-file test is intrinsically fragile

The first test reads client.tsx from disk and regex-matches its content. This works, but it will silently start failing if the test is run from a different cwd, or if __dirname resolution changes (e.g., with moduleDirectories or path-aliasing in a future Jest config). A comment noting that this is an intentional structural guard (not a unit test) would help future readers understand why an fs.readFileSync appears in a test suite.

3. Minor: comment length in source file

The 10-line block comment in client.tsx is well-reasoned, but the project style guide discourages multi-line comment blocks. Consider condensing to 2-3 lines that capture the essential non-obvious constraint (why this exact import is required by RSCWebpackPlugin's scan strategy), deferring detail to the linked issue.

Summary

The fix itself is correct and safe to merge. The main actionable item before merging is resolving the silent-pass test (issue 1 above) so the regression guard actually provides meaningful CI signal.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 23, 2026

size-limit report 📦

Path Size
react-on-rails/client bundled (gzip) 62.83 KB (0%)
react-on-rails/client bundled (gzip) (time) 62.83 KB (0%)
react-on-rails/client bundled (brotli) 53.9 KB (0%)
react-on-rails/client bundled (brotli) (time) 53.9 KB (0%)
react-on-rails-pro/client bundled (gzip) 63.77 KB (0%)
react-on-rails-pro/client bundled (gzip) (time) 63.77 KB (0%)
react-on-rails-pro/client bundled (brotli) 54.81 KB (0%)
react-on-rails-pro/client bundled (brotli) (time) 54.81 KB (0%)
registerServerComponent/client bundled (gzip) 127.95 KB (0%)
registerServerComponent/client bundled (gzip) (time) 127.95 KB (0%)
registerServerComponent/client bundled (brotli) 62.06 KB (+0.05% 🔺)
registerServerComponent/client bundled (brotli) (time) 62.06 KB (+0.05% 🔺)
wrapServerComponentRenderer/client bundled (gzip) 122.37 KB (+0.01% 🔺)
wrapServerComponentRenderer/client bundled (gzip) (time) 122.37 KB (+0.01% 🔺)
wrapServerComponentRenderer/client bundled (brotli) 57.09 KB (+0.06% 🔺)
wrapServerComponentRenderer/client bundled (brotli) (time) 57.09 KB (+0.06% 🔺)

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 23, 2026

Greptile Summary

This PR fixes a 16.7.0-rc.0 regression where RSCWebpackPlugin silently dropped react-client-manifest.json because it could not detect the client runtime through a three-level transitive import chain that downstream tooling could sever.

  • wrapServerComponentRenderer/client.tsx: Adds a direct top-level side-effect import of react-on-rails-rsc/client.browser, ensuring the module always appears in the webpack client-bundle graph regardless of how intermediate imports are handled by tree-shakers or transpilers.
  • New regression test: Statically verifies via fs.readFileSync + regex that the side-effect import is present in both the TypeScript source and the compiled lib output, preventing silent future regressions.

Confidence Score: 4/5

Safe to merge; the change is a one-line side-effect import with thorough comments and a new regression test.

The fix is minimal and well-understood: a single side-effect import that makes the module graph more robust. The only rough edge is in the new test — the second it block silently passes when the compiled lib is absent, which could mask a missing build step in CI rather than surface it as a skipped test.

The test file wrapServerComponentRenderer.client.imports.test.ts warrants a quick look at the conditional return in the second test case.

Important Files Changed

Filename Overview
packages/react-on-rails-pro/src/wrapServerComponentRenderer/client.tsx Adds a top-level side-effect import of react-on-rails-rsc/client.browser with a detailed comment explaining why; a targeted, correct fix for the missing manifest regression.
packages/react-on-rails-pro/tests/wrapServerComponentRenderer.client.imports.test.ts New regression test verifying the side-effect import exists in source and compiled output; second test silently passes (returns without assertion) when lib is unbuilt instead of using it.skip.
CHANGELOG.md Adds a detailed [Unreleased] Fixed entry documenting the RSC client manifest regression and its root cause.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["wrapServerComponentRenderer/client.tsx"] -->|"side-effect import (NEW)"| B["react-on-rails-rsc/client.browser"]
    A -->|transitive chain| C["getReactServerComponent.client.ts"]
    C -->|transitive| B
    B --> D["RSCWebpackPlugin\nscans module graph for\nclient.browser.js resource"]
    D -->|"clientFileNameFound = true"| E["emits react-client-manifest.json ✅"]
    D -->|"clientFileNameFound = false\n(if chain severed)"| F["manifest silently dropped ❌\nNode Renderer → ENOENT"]
Loading

Reviews (1): Last reviewed commit: "fix(pro): preserve react-on-rails-rsc/cl..." | Re-trigger Greptile

justin808 added a commit that referenced this pull request May 23, 2026
Address PR #3368 review feedback: the previous early `return` caused
Jest to count the lib-output regression test as passing (not skipped)
when `lib/` had not been built, providing no CI signal. Use conditional
`it`/`it.skip` registration so the report shows the test as explicitly
skipped on a fresh checkout.

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

Review feedback addressed

Both review threads (from @claude and @greptile-apps) flagged the same issue: the if (!fs.existsSync(libPath)) return; early-exit in wrapServerComponentRenderer.client.imports.test.ts caused Jest to count the lib-output regression check as passing (not skipped) on a fresh checkout — so the guard provided no signal if a CI build step were silently dropped.

Fix (f895ff5): I (Claude Code) switched to conditional registration (libExists ? it : it.skip), exactly as suggested. The test now shows as an explicit ○ skipped in the Jest report when lib/ is absent, and runs normally after pnpm run build.

Verified locally: the suite still passes (Tests: 2 passed, 2 total) against a freshly-built lib/.

const libExists = fs.existsSync(libPath);
// lib is only built before publish or after `pnpm run build`. When absent the
// test is explicitly skipped (visible in the report) rather than silently green.
(libExists ? it : it.skip)('keeps the same runtime present in the compiled lib output', () => {
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 libExists branch will always be skipped in CI because lib/ is built only at publish time and isn't committed. That means the CI pipeline gets zero coverage of whether the TypeScript compiler preserves the import in the compiled output — the test silently passes (as a skip) even if the tsc step strips the side-effect import.

Two options worth considering:

  1. Add a pnpm run build && <this test> step to CI so the lib test actually runs at least once before a release. The full-ci label on this PR suggests a broad CI matrix is already in play — could be the right place to add it.

  2. Remove the lib test entirely if a build step isn't feasible, and rely on the src test + the published package's pre-release smoke test. An always-skipped test provides false assurance — it appears in the report but catches nothing.

Comment on lines +15 to +24
// Side-effect import: keeps `react-on-rails-rsc/client.browser` in the webpack
// module graph for the client bundle so RSCWebpackPlugin (which scans every
// parsed module for this exact resource) can detect the client runtime and
// emit `react-client-manifest.json`. Without this direct import, the plugin
// relies on a 3-level transitive chain
// (`wrapServerComponentRenderer/client` → `getReactServerComponent.client`
// → `react-on-rails-rsc/client.browser`). Any tooling that severs that chain
// (tree-shaking, transpilers, NormalModuleReplacement, custom externals)
// silently drops the manifest and breaks RSC hydration on the renderer.
import 'react-on-rails-rsc/client.browser';
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 comment is warranted (the WHY here is genuinely non-obvious), but it's duplicated almost verbatim in three places: here, in the test file's describe block, and in the PR description/CHANGELOG. The source comment is the most load-bearing location; the test comment can just point back to the issue number.

Suggested condensed version:

Suggested change
// Side-effect import: keeps `react-on-rails-rsc/client.browser` in the webpack
// module graph for the client bundle so RSCWebpackPlugin (which scans every
// parsed module for this exact resource) can detect the client runtime and
// emit `react-client-manifest.json`. Without this direct import, the plugin
// relies on a 3-level transitive chain
// (`wrapServerComponentRenderer/client` → `getReactServerComponent.client`
// → `react-on-rails-rsc/client.browser`). Any tooling that severs that chain
// (tree-shaking, transpilers, NormalModuleReplacement, custom externals)
// silently drops the manifest and breaks RSC hydration on the renderer.
import 'react-on-rails-rsc/client.browser';
// Side-effect import: RSCWebpackPlugin only emits react-client-manifest.json when it finds
// react-on-rails-rsc/client.browser in the parsed module graph. A direct import here
// guarantees that regardless of how downstream tooling handles transitive chains. See #3366.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 23, 2026

Review: fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366)

Summary

Targeted, well-reasoned fix. The root cause is clear (RSCWebpackPlugin's module-graph scan requires a direct-import path to client.browser, not just a transitive one), the change is minimal (one import line), and the regression test is a creative guard against silent removal. A few concerns worth addressing.


Correctness of the fix ✅

Adding import 'react-on-rails-rsc/client.browser' directly to wrapServerComponentRenderer/client.tsx is the right approach. It collapses the fragile 3-level transitive chain to a guaranteed single-hop that RSCWebpackPlugin will always detect. Since registerServerComponent/client.tsx directly imports wrapServerComponentRenderer/client.tsx (line 19), both pack entry-points are covered by this one change.


registerServerComponent/client.tsx — consider a defensive import there too

Even after this fix, if a user's pack entry is registerServerComponent/client, the manifest still depends on a 2-level chain: registerServerComponent/client → wrapServerComponentRenderer/client → client.browser. That is far more robust than the original 3-level chain and is likely sufficient. But if a future refactor or module-federation configuration severs the wrapServerComponentRenderer link, the manifest silently disappears again. Adding the same side-effect import to registerServerComponent/client.tsx would make both entry-points independently robust. Low priority, but worth a follow-up issue.


Test approach ⚠️

The source-file string scan is a legitimate and pragmatic regression guard — it protects against the exact failure mode of accidentally removing the import. Two concerns:

  1. The lib test is always skipped in CI (see inline comment on line 38). It provides no CI-time protection. Either hook a build step to make it run, or remove it to avoid misleading skips.
  2. The src regex allows an optional semicolon (?). Since the project enforces semicolons, tightening to require it would make the test slightly more precise — minor nit.

Comment verbosity ⚠️

The 9-line block in client.tsx is repeated almost verbatim in the test file and again in the CHANGELOG. See inline suggestion for a condensed 3-line version that retains all the important context in the source file.


Overall

Approve with the lib-test concern as the main actionable item before merge. The fix itself is correct and the regression test (src half) is valuable.

*/

import { createRequire } from 'module';

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 file uses ESM import syntax at the top but then relies on __filename, which is a CJS-only global. It works today because ts-jest's createJsWithTsPreset transforms the ESM import to require before running, making __filename available — but it would silently break if the Jest config ever switches to native ESM (--experimental-vm-modules / extensionsToTreatAsEsm).

Pick one style consistently:

Suggested change
const { createRequire } = require('module');
const nodeRequire = createRequire(__filename);

or, if you want pure ESM:

import { createRequire } from 'module';
const nodeRequire = createRequire(import.meta.url);

};

describe('wrapServerComponentRenderer client manifest emission', () => {
it('keeps the RSC client runtime visible to RSCWebpackPlugin', async () => {
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.

No explicit timeout is set for this test. Jest's default async test timeout is 5 seconds, and a cold webpack compilation (no cache, first CI run) can easily exceed that, causing a spurious timeout failure on slow runners.

Add a suite-level override at the top of the describe block (or before it):

jest.setTimeout(30_000);

Or pass the timeout as the third it argument:

Suggested change
it('keeps the RSC client runtime visible to RSCWebpackPlugin', async () => {
it('keeps the RSC client runtime visible to RSCWebpackPlugin', async () => {

it('keeps the RSC client runtime visible to RSCWebpackPlugin', async () => { ... }, 30_000);

Comment on lines +15 to +22
// Side-effect import: keeps `react-on-rails-rsc/client.browser` in the webpack
// module graph for the client bundle so RSCWebpackPlugin (which scans every
// parsed module for this exact resource) can detect the client runtime and
// emit `react-client-manifest.json`. Without this direct import, the plugin
// relies on a 3-level transitive chain
// (`wrapServerComponentRenderer/client` → `getReactServerComponent.client`
// → `react-on-rails-rsc/client.browser`). Any tooling that severs that chain
// (tree-shaking, transpilers, NormalModuleReplacement, custom externals)
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 9-line comment restates information that's already in the regression test's header comment and the PR description. The project convention is to comment only on the non-obvious WHY; a shorter version keeps the signal without the noise:

Suggested change
// Side-effect import: keeps `react-on-rails-rsc/client.browser` in the webpack
// module graph for the client bundle so RSCWebpackPlugin (which scans every
// parsed module for this exact resource) can detect the client runtime and
// emit `react-client-manifest.json`. Without this direct import, the plugin
// relies on a 3-level transitive chain
// (`wrapServerComponentRenderer/client` → `getReactServerComponent.client`
// → `react-on-rails-rsc/client.browser`). Any tooling that severs that chain
// (tree-shaking, transpilers, NormalModuleReplacement, custom externals)
// Side-effect import required: RSCWebpackPlugin only emits react-client-manifest.json when it
// finds this module in the client graph. A transitive chain is not reliable under tree-shaking.
import 'react-on-rails-rsc/client.browser';

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 23, 2026

Code Review

Overview

This PR fixes a fragile transitive dependency on react-on-rails-rsc/client.browser that could be silently dropped from the webpack module graph, causing RSCWebpackPlugin to skip emitting react-client-manifest.json and breaking RSC hydration on the Pro Node Renderer. The fix is a one-line direct side-effect import; two regression tests guard against it regressing again.

The fix is correct and well-targeted. RSCWebpackPlugin scans the client bundle's parsed module graph for this exact resource path, so a direct import is the right solution.


Issues (see inline comments)

  1. Missing Jest timeoutwrapServerComponentRenderer.client.manifest.test.js runs a full webpack compilation with no explicit timeout. Jest's default 5-second async timeout can be exceeded by a cold webpack run on slow CI runners, causing spurious flaky failures. Add jest.setTimeout(30_000) at the suite level.

  2. ESM import mixed with __filename — the same test file uses top-level ESM import alongside the CJS-only __filename global. Works today via ts-jest's transform, but would break under native ESM. Pick one style consistently (pure CJS require or pure ESM import.meta.url).

  3. Overly verbose comment in client.tsx — the 9-line block comment restates what's already in the regression test header and the PR description. Two lines covering the non-obvious invariant is enough.


What's Good

  • The one-line fix is minimal and correctly targets the plugin's detection mechanism.
  • The webpack-level test is exactly the right kind of test here — it exercises the actual plugin path rather than mocking around it.
  • The conditional it.skip for the lib/ check avoids false-green tests when the package hasn't been built yet.
  • The NormalModuleReplacementPlugin stub cleanly simulates the transitive-chain-severed scenario that triggered the bug.
  • CHANGELOG entry is thorough and links to the issue.

Verdict

Core fix and test strategy are solid. Address the Jest timeout before merging to avoid CI flakiness on slow runners. The ESM/CJS mixing is low-risk under the current transform setup but worth cleaning up for future-proofing.

justin808 and others added 3 commits May 23, 2026 12:07
Add a side-effect import of `react-on-rails-rsc/client.browser` at the
top of `wrapServerComponentRenderer/client.tsx`. RSCWebpackPlugin scans
every parsed module's resource path for an exact match against
`require.resolve("../client.browser.js")` and only emits
`react-client-manifest.json` when it finds one. Previously the client
runtime was reachable only through a three-level transitive chain
(`wrapServerComponentRenderer/client` → `getReactServerComponent.client`
→ `react-on-rails-rsc/client.browser`); any tooling that severed a link
in that chain silently dropped the manifest and broke RSC hydration on
the Pro Node Renderer with a misleading "Client runtime ... was not
found" warning.

Add a structural regression test that fails if the side-effect import
is removed from either the source or the compiled lib output.

Fixes #3366

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address PR #3368 review feedback: the previous early `return` caused
Jest to count the lib-output regression test as passing (not skipped)
when `lib/` had not been built, providing no CI signal. Use conditional
`it`/`it.skip` registration so the report shows the test as explicitly
skipped on a fresh checkout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@justin808 justin808 force-pushed the jg-conductor/3366-fix-issue branch from 3013f9d to 8952812 Compare May 23, 2026 22:07
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 23, 2026

Code Review

Overall: Solid, targeted fix with thorough regression tests. Two minor issues noted below.

What this PR does

Adds a direct side-effect import of react-on-rails-rsc/client.browser to wrapServerComponentRenderer/client.tsx so RSCWebpackPlugin can always detect the client runtime in the webpack module graph and emit react-client-manifest.json. Previously the runtime was only reachable through a three-level transitive chain that any tooling could silently sever.

Correctness

The fix is correct and minimal. RSCWebpackPlugin scans each parsed module's resource path for an exact match against the client browser runtime; a direct import guarantees it's in the graph regardless of what happens to transitive dependencies. The NormalModuleReplacement trick in the webpack test cleanly proves the direct import alone is sufficient.

Test quality

Two-pronged coverage is appropriate here:

  • The structural test (client.imports.test.ts) prevents silent removal of the import — the regex correctly requires a real import statement (not a comment) by anchoring on ^\s*import\s+
  • The webpack build test (client.manifest.test.js) provides end-to-end confidence by actually running webpack with the transitive path stubbed out

The conditional it.skip pattern for the lib check is a nice touch — explicit skip in the test report is better than a silent green.

Minor issues

  1. createRequire(__filename) in ESM context (manifest test, line 7): __filename is a CJS-only global. It works today because ts-jest transforms the file to CJS before Jest runs it, but if the project ever migrates to true ESM Jest (--experimental-vm-modules), this will throw a ReferenceError. The ESM-idiomatic form is createRequire(import.meta.url) — no __filename needed.

  2. No explicit timeout on the webpack build test (manifest test, line 113): Webpack compilation in a test process can occasionally spike past Jest's default 5 s timeout on loaded CI runners. A one-liner guard (jest.setTimeout(30_000) at the top of the describe block, or passing a timeout as a third arg to it) would prevent flaky timeouts without changing the logic.

Non-blocking notes

  • The 8-line comment block in client.tsx is fully justified — this is exactly the "hidden constraint" case where a reader would otherwise delete the import as "unused". No issue there.
  • CHANGELOG entry is accurate and detailed.
  • The stub fixture is clean and minimal.


import { createRequire } from 'module';

const nodeRequire = createRequire(__filename);
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.

ESM portability: __filename is a CommonJS-only global. This works today because ts-jest transforms the file to CJS before running it, but would throw ReferenceError: __filename is not defined if the project ever moves to true ESM Jest (--experimental-vm-modules).

The ESM-native equivalent needs no __filename at all:

Suggested change
const nodeRequire = createRequire(__filename);
const nodeRequire = createRequire(import.meta.url);

};

describe('wrapServerComponentRenderer client manifest emission', () => {
it('keeps the RSC client runtime visible to RSCWebpackPlugin', async () => {
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.

Webpack compilation can occasionally exceed Jest's default 5 s timeout on loaded CI runners, causing a flaky failure. Consider adding an explicit timeout:

Suggested change
it('keeps the RSC client runtime visible to RSCWebpackPlugin', async () => {
it('keeps the RSC client runtime visible to RSCWebpackPlugin', async () => {

…with either jest.setTimeout(30_000) at the top of the describe block, or a third argument }, 30_000) at the closing of this it call.

The wrapServerComponentRenderer client manifest test uses webpack's
NormalModuleReplacementPlugin to swap in a stub fixture via a runtime
path string, which knip cannot trace statically. Mirror the existing
ignore pattern from the pro-node-renderer workspace so the fixture
isn't flagged as unused.

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

claude Bot commented May 23, 2026

Code Review

Overview

This PR fixes a regression in 16.7.0-rc.0 where react-client-manifest.json could be silently omitted from the Pro Node Renderer build. Root cause: RSCWebpackPlugin only emits the manifest when it finds react-on-rails-rsc/client.browser directly in the webpack module graph; relying on a three-level transitive import chain left that detection vulnerable to tree-shaking, transpiler quirks, or any NormalModuleReplacement that breaks the chain. The fix — a direct side-effect import — is minimal, targeted, and correctly reasoned.

What's Good

  • Fix is correct and minimal. One import line resolves the fragility without touching any runtime logic.
  • Comment justification. The 8-line comment in client.tsx is exactly the right call here — the import's purpose is entirely non-obvious without it.
  • Test strategy is solid. Two complementary regression tests: a structural one (grep the source/lib for the import) and a behavioral one (run webpack with the transitive chain stubbed out, assert manifest is emitted).
  • NormalModuleReplacementPlugin regex is correct. The import in client.tsx uses an explicit .ts extension (import ... from '../getReactServerComponent.client.ts'), so the pattern /getReactServerComponent\.client\.ts$/ matches reliably.

Issues

Medium: Missing Jest timeout in webpack compilation test

The manifest test (wrapServerComponentRenderer.client.manifest.test.js) runs a full webpack compilation (entry → swc-loader → RSCWebpackPlugin → memfs output). The base jest.config.base.js sets no custom timeout, leaving the default at 5 000 ms. On slow CI runners (or with cold node_modules) a real webpack compile can easily exceed that, producing a flaky Exceeded timeout of 5000 ms failure unrelated to the fix. Add jest.setTimeout(30_000) at the top of the test file, or pass timeout: 30_000 as a third argument to the it() call.

Minor: Stub return type is loose

getReactServerComponent.client.stub.ts types the return as () => Promise<null>. The real module returns a React component (ReactNode | Promise<ReactNode>). The stub is only used by webpack at build time (never executed by Jest), so this causes no failure today. But if a future test ever imports the stub for a unit assertion, the loose type could mask a mismatch. Acceptable as-is; worth a one-line comment noting the stub is build-only.

Nit: Skipped lib test is only as fresh as the last build

The it.skip branch for the compiled lib in wrapServerComponentRenderer.client.imports.test.ts will show as "skipped" when lib/ is absent, which is correct. But if lib/ is present and stale (e.g., from a partial build), the test asserts the old compiled output. The current logic is fine for the common case — just worth noting in the PR that the lib check is only as fresh as the last pnpm run build.

Summary

The fix is correct and well-tested. The Jest timeout is the only real risk — webpack compilations in CI have caused flakiness in other projects when left at the default 5 s. Everything else is minor.

Comment on lines +107 to +108
});
});
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.

A full webpack compilation with swc-loader can easily exceed Jest's default 5 000 ms timeout on slower CI runners, producing a flaky Exceeded timeout failure unrelated to the actual fix. Consider bumping the timeout:

Suggested change
});
});
describe('wrapServerComponentRenderer client manifest emission', () => {
it('keeps the RSC client runtime visible to RSCWebpackPlugin', async () => {

Either add jest.setTimeout(30_000); above this describe block, or pass a third timeout argument to the it() call:

it('keeps the RSC client runtime visible to RSCWebpackPlugin', async () => { ... }, 30_000);

@@ -0,0 +1,3 @@
export default function getReactServerComponent() {
return () => Promise.resolve(null);
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 return type here (() => Promise<null>) doesn't match the real module's signature (which returns a React component). This is fine because the stub is only used at webpack build time and never executed by Jest — but a short comment would make that clear to a future reader who wonders why the types don't align:

Suggested change
return () => Promise.resolve(null);
// Build-only stub: webpack replaces the real module via NormalModuleReplacementPlugin.
// This function is never executed; only its presence in the module graph matters.
return () => Promise.resolve(null);

@justin808 justin808 merged commit 6c46ee3 into main May 24, 2026
50 checks passed
@justin808 justin808 deleted the jg-conductor/3366-fix-issue branch May 24, 2026 00:04
justin808 added a commit that referenced this pull request May 24, 2026
…-maintenance-doc

* origin/main:
  docs: document RSC node renderer globals (#3221)
  fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366) (#3368)
  Allow Pro 16.7 to keep jwt 2.x compatibility (#3344)
  Plan: flagship 2026 React on Rails starter kit (#3357) (#3364)
  docs: clarify coupled gem/npm/lockfile upgrade for React on Rails Pro (#3369)
  chore(deps): bump fastify from 5.8.3 to 5.8.5 in the npm-security group across 1 directory (#3152)
  docs: clarify initial security triage ownership in SECURITY.md (#3337)
  docs: consolidate node renderer probe settings (#3257) (#3348)
  chore(ci): remove obsolete setup-node-with-retry action (#3352)
  chore: remove completed planning/analysis docs (#3361)
  test: stub stable VERSION in --pro install spec to unblock CI (#3363)
  docs(specs): add RC testing plan design spec (#3350)
  docs: point users at bin/shakapacker-config --doctor for bundler-config debugging (#3359)
  docs: polish RSC node renderer test recipe (#3273) (#3339)
  test: replace call_count stub pattern with and_return sequence (#2157) (#3353)
  docs: call out Inertia's incompatibility with client-side routers (#3356)
  docs: replace personal email with contact URL in Pro README (#3347)

# Conflicts:
#	react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
justin808 added a commit that referenced this pull request May 24, 2026
* origin/main:
  fix: add reactDomClientWarning helper for React 16/17 (#3137) (#3358)
  docs: document RSC node renderer globals (#3221)
  fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366) (#3368)
  Allow Pro 16.7 to keep jwt 2.x compatibility (#3344)
  Plan: flagship 2026 React on Rails starter kit (#3357) (#3364)
  docs: clarify coupled gem/npm/lockfile upgrade for React on Rails Pro (#3369)
  chore(deps): bump fastify from 5.8.3 to 5.8.5 in the npm-security group across 1 directory (#3152)
  docs: clarify initial security triage ownership in SECURITY.md (#3337)
  docs: consolidate node renderer probe settings (#3257) (#3348)
  chore(ci): remove obsolete setup-node-with-retry action (#3352)
  chore: remove completed planning/analysis docs (#3361)
  test: stub stable VERSION in --pro install spec to unblock CI (#3363)
  docs(specs): add RC testing plan design spec (#3350)
  docs: point users at bin/shakapacker-config --doctor for bundler-config debugging (#3359)
  docs: polish RSC node renderer test recipe (#3273) (#3339)
  test: replace call_count stub pattern with and_return sequence (#2157) (#3353)
  docs: call out Inertia's incompatibility with client-side routers (#3356)

# Conflicts:
#	.github/workflows/pro-lint.yml
justin808 added a commit that referenced this pull request May 24, 2026
…#3366) (#3368)

## Summary

Fixes [#3366](#3366) —
a 16.7.0-rc.0 regression where the RSC client manifest
(`react-client-manifest.json`) is silently dropped from the Pro Node
Renderer upload, breaking server-component rendering with `ENOENT` on
the renderer side.

- Add a side-effect import of `react-on-rails-rsc/client.browser` at the
top of `wrapServerComponentRenderer/client.tsx`. RSCWebpackPlugin scans
every parsed module's resource path for an exact match against
`require.resolve("../client.browser.js")` and only emits
`react-client-manifest.json` when it finds one. Previously the client
runtime was reachable only through a three-level transitive chain
(`wrapServerComponentRenderer/client` → `getReactServerComponent.client`
→ `react-on-rails-rsc/client.browser`); any tooling that severed a link
in that chain silently dropped the manifest and produced the misleading
`Client runtime at react-on-rails-rsc/client was not found` warning. The
direct import keeps the runtime resource in the client module graph
regardless of how downstream tooling handles transitive default imports.
- Add a structural regression test that fails if the side-effect import
is removed from either the source or the compiled lib output.
- Add a webpack-level regression test that compiles
`wrapServerComponentRenderer/client.tsx` with the old transitive
`getReactServerComponent.client` edge replaced by a stub, then asserts
`RSCWebpackPlugin` still emits `react-client-manifest.json`. This proves
the direct import itself preserves the manifest.

## Why

Issue #3366 reports that the warning + missing manifest first appears
when the consuming app upgrades to `react_on_rails_pro` /
`react-on-rails-pro` / `react-on-rails-pro-node-renderer` `16.7.0-rc.0`
from `16.6.0`, even with `react-on-rails-rsc@19.0.4` and
`shakapacker@10.0.0` unchanged. The actual chain in source/lib is intact
between both versions, and the issue does not reproduce on the in-tree
dummy app or a clean clone of the tutorial PR — but the user's
environment clearly does see `clientFileNameFound = false` from the
upstream RSC plugin. The defensive direct import removes that fragility:
even if a future transpiler/tree-shaker decides
`getReactServerComponent.client` is "unused" or rewrites the path, the
side-effect import keeps `client.browser` in the graph and the plugin
always emits the manifest.

## Evaluation

Confirmed the fix addresses the bug mechanism. The RSC plugin decides
whether to write `react-client-manifest.json` by seeing the
`react-on-rails-rsc/client.browser` module in the client compilation.
The direct side-effect import is an appropriate fix because it changes
build graph visibility without changing renderer runtime behavior.

I verified the new behavior test is meaningful by temporarily removing
the direct import: with the old transitive helper path stubbed out,
webpack emitted the expected `Client runtime at
react-on-rails-rsc/client was not found` warning and the test failed.
Restoring the import made the same test pass and emit
`react-client-manifest.json`. The Pro dummy build also emits both
`react-client-manifest.json` and `react-server-client-manifest.json`
successfully.

## Test plan

- [x] `pnpm --filter react-on-rails-pro exec jest
tests/wrapServerComponentRenderer.client.manifest.test.js --runInBand`
passes
- [x] Red check: temporarily removing `import
'react-on-rails-rsc/client.browser';` makes the new manifest test fail
with the upstream missing-client-runtime warning
- [x] `pnpm --filter react-on-rails-pro exec jest
tests/wrapServerComponentRenderer.client.manifest.test.js
tests/wrapServerComponentRenderer.client.imports.test.ts --runInBand`
passes
- [x] `pnpm --filter react-on-rails-pro exec jest
tests/createReactOnRailsPro.test.ts --runInBand` passes
- [x] `pnpm --filter react-on-rails-pro run test:non-rsc` passes: 7
suites, 58 tests
- [x] `pnpm --filter react-on-rails-pro run type-check` passes
- [x] `pnpm run lint` passes
- [x] `(cd react_on_rails && bundle exec rubocop)` passes
- [x] `(cd react_on_rails_pro && bundle exec rubocop
--ignore-parent-exclusion)` passes; RuboCop prints deprecation warnings
from dependencies but reports no offenses
- [x] `pnpm exec prettier --check
packages/react-on-rails-pro/tests/wrapServerComponentRenderer.client.manifest.test.js
packages/react-on-rails-pro/tests/fixtures/rsc-manifest/getReactServerComponent.client.stub.ts`
passes
- [x] `RAILS_ENV=test NODE_ENV=development bundle exec bin/shakapacker`
from `react_on_rails_pro/spec/dummy` passes and emits
`react-client-manifest.json` plus `react-server-client-manifest.json`
- [x] `git diff --check` passes
- [x] Pre-commit and pre-push hooks passed while committing and pushing
`3013f9d90`
- [ ] Full-repo `pnpm start format.listDifferent` is blocked by an
existing ignored `.context/plans/issue-3366-reproduction-plan.md`
formatting issue; the PR files pass direct Prettier checks
- [ ] Verify CI passes on this PR
- [ ] Verify
[shakacode/react-webpack-rails-tutorial#740](shakacode/react-webpack-rails-tutorial#740)
unblocks once a new RC build with this fix is published

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches Pro RSC client entrypoint bundling to force inclusion of the
RSC client runtime, which can affect build output and hydration behavior
if misconfigured. Added tests reduce regression risk, but changes are in
a critical RSC packaging path.
> 
> **Overview**
> Restores reliable React Server Components hydration for Pro by adding
a **top-level side-effect import** of
`react-on-rails-rsc/client.browser` in
`wrapServerComponentRenderer/client.tsx`, ensuring `RSCWebpackPlugin`
consistently emits `react-client-manifest.json` even when transitive
imports are disrupted.
> 
> Adds regression coverage: a structural test that enforces the presence
of the side-effect import (source and built `lib` when available) and a
webpack-level test that stubs `getReactServerComponent.client` to prove
manifest emission still occurs. Updates `knip.ts` to ignore dynamically
referenced test fixtures and records the fix in `CHANGELOG.md`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1bb24cc. 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

* **Bug Fixes**
* Restored inclusion of the client runtime so the client manifest is
emitted, preventing React Server Components hydration failures in
certain build setups.

* **Tests**
* Added regression tests to ensure the client runtime import is
preserved and the client manifest is emitted during bundling.

* **Documentation**
  * Updated CHANGELOG with the fix.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/shakacode/react_on_rails/pull/3368?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
justin808 added a commit that referenced this pull request May 25, 2026
* origin/main: (54 commits)
  Bump version to 16.7.0.rc.1
  [codex] Prepare 16.7.0.rc.1 changelog (#3384)
  fix(tanstack-router): remove Suspense gate around RouterProvider during hydration (#3213)
  chore(deps): bump the npm-security group across 1 directory with 3 updates (#3370)
  fix: add reactDomClientWarning helper for React 16/17 (#3137) (#3358)
  docs: document RSC node renderer globals (#3221)
  fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366) (#3368)
  Allow Pro 16.7 to keep jwt 2.x compatibility (#3344)
  Plan: flagship 2026 React on Rails starter kit (#3357) (#3364)
  docs: clarify coupled gem/npm/lockfile upgrade for React on Rails Pro (#3369)
  chore(deps): bump fastify from 5.8.3 to 5.8.5 in the npm-security group across 1 directory (#3152)
  docs: clarify initial security triage ownership in SECURITY.md (#3337)
  docs: consolidate node renderer probe settings (#3257) (#3348)
  chore(ci): remove obsolete setup-node-with-retry action (#3352)
  chore: remove completed planning/analysis docs (#3361)
  test: stub stable VERSION in --pro install spec to unblock CI (#3363)
  docs(specs): add RC testing plan design spec (#3350)
  docs: point users at bin/shakapacker-config --doctor for bundler-config debugging (#3359)
  docs: polish RSC node renderer test recipe (#3273) (#3339)
  test: replace call_count stub pattern with and_return sequence (#2157) (#3353)
  ...
justin808 added a commit that referenced this pull request May 25, 2026
* origin/main: (54 commits)
  Bump version to 16.7.0.rc.1
  [codex] Prepare 16.7.0.rc.1 changelog (#3384)
  fix(tanstack-router): remove Suspense gate around RouterProvider during hydration (#3213)
  chore(deps): bump the npm-security group across 1 directory with 3 updates (#3370)
  fix: add reactDomClientWarning helper for React 16/17 (#3137) (#3358)
  docs: document RSC node renderer globals (#3221)
  fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366) (#3368)
  Allow Pro 16.7 to keep jwt 2.x compatibility (#3344)
  Plan: flagship 2026 React on Rails starter kit (#3357) (#3364)
  docs: clarify coupled gem/npm/lockfile upgrade for React on Rails Pro (#3369)
  chore(deps): bump fastify from 5.8.3 to 5.8.5 in the npm-security group across 1 directory (#3152)
  docs: clarify initial security triage ownership in SECURITY.md (#3337)
  docs: consolidate node renderer probe settings (#3257) (#3348)
  chore(ci): remove obsolete setup-node-with-retry action (#3352)
  chore: remove completed planning/analysis docs (#3361)
  test: stub stable VERSION in --pro install spec to unblock CI (#3363)
  docs(specs): add RC testing plan design spec (#3350)
  docs: point users at bin/shakapacker-config --doctor for bundler-config debugging (#3359)
  docs: polish RSC node renderer test recipe (#3273) (#3339)
  test: replace call_count stub pattern with and_return sequence (#2157) (#3353)
  ...

# Conflicts:
#	docs/oss/core-concepts/performance-benchmarks.md
justin808 added a commit that referenced this pull request May 25, 2026
* origin/main:
  Bump version to 16.7.0.rc.1
  [codex] Prepare 16.7.0.rc.1 changelog (#3384)
  fix(tanstack-router): remove Suspense gate around RouterProvider during hydration (#3213)
  chore(deps): bump the npm-security group across 1 directory with 3 updates (#3370)
  fix: add reactDomClientWarning helper for React 16/17 (#3137) (#3358)
  docs: document RSC node renderer globals (#3221)
  fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366) (#3368)
  Allow Pro 16.7 to keep jwt 2.x compatibility (#3344)
  Plan: flagship 2026 React on Rails starter kit (#3357) (#3364)
  docs: clarify coupled gem/npm/lockfile upgrade for React on Rails Pro (#3369)
  chore(deps): bump fastify from 5.8.3 to 5.8.5 in the npm-security group across 1 directory (#3152)
  docs: clarify initial security triage ownership in SECURITY.md (#3337)
  docs: consolidate node renderer probe settings (#3257) (#3348)
  chore(ci): remove obsolete setup-node-with-retry action (#3352)
  chore: remove completed planning/analysis docs (#3361)
justin808 added a commit that referenced this pull request May 25, 2026
* origin/main: (26 commits)
  docs: define security-supported versions policy (#3261) (#3341)
  Bump version to 16.7.0.rc.2
  Update CHANGELOG.md for 16.7.0.rc.2 (#3393)
  Fail release on unverifiable or Yarn-incompatible npm packages (#3387)
  Bump version to 16.7.0.rc.1
  [codex] Prepare 16.7.0.rc.1 changelog (#3384)
  fix(tanstack-router): remove Suspense gate around RouterProvider during hydration (#3213)
  chore(deps): bump the npm-security group across 1 directory with 3 updates (#3370)
  fix: add reactDomClientWarning helper for React 16/17 (#3137) (#3358)
  docs: document RSC node renderer globals (#3221)
  fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366) (#3368)
  Allow Pro 16.7 to keep jwt 2.x compatibility (#3344)
  Plan: flagship 2026 React on Rails starter kit (#3357) (#3364)
  docs: clarify coupled gem/npm/lockfile upgrade for React on Rails Pro (#3369)
  chore(deps): bump fastify from 5.8.3 to 5.8.5 in the npm-security group across 1 directory (#3152)
  docs: clarify initial security triage ownership in SECURITY.md (#3337)
  docs: consolidate node renderer probe settings (#3257) (#3348)
  chore(ci): remove obsolete setup-node-with-retry action (#3352)
  chore: remove completed planning/analysis docs (#3361)
  test: stub stable VERSION in --pro install spec to unblock CI (#3363)
  ...
justin808 added a commit that referenced this pull request May 25, 2026
* origin/main: (31 commits)
  More precise heading in CHANGELOG (#3402)
  Update `pino` dependency range (#3401)
  Upgrade to latest pnpm v10 (#3400)
  docs: track CI_PNPM_FALLBACK_VERSION bumps in CONTRIBUTING (#3264) (#3346)
  docs(generator): record pnpm fallback bump policy and last-checked date (#3248) (#3328)
  docs: define security-supported versions policy (#3261) (#3341)
  Bump version to 16.7.0.rc.2
  Update CHANGELOG.md for 16.7.0.rc.2 (#3393)
  Fail release on unverifiable or Yarn-incompatible npm packages (#3387)
  Bump version to 16.7.0.rc.1
  [codex] Prepare 16.7.0.rc.1 changelog (#3384)
  fix(tanstack-router): remove Suspense gate around RouterProvider during hydration (#3213)
  chore(deps): bump the npm-security group across 1 directory with 3 updates (#3370)
  fix: add reactDomClientWarning helper for React 16/17 (#3137) (#3358)
  docs: document RSC node renderer globals (#3221)
  fix(pro): preserve react-on-rails-rsc/client.browser in client bundle (#3366) (#3368)
  Allow Pro 16.7 to keep jwt 2.x compatibility (#3344)
  Plan: flagship 2026 React on Rails starter kit (#3357) (#3364)
  docs: clarify coupled gem/npm/lockfile upgrade for React on Rails Pro (#3369)
  chore(deps): bump fastify from 5.8.3 to 5.8.5 in the npm-security group across 1 directory (#3152)
  ...

# Conflicts:
#	CHANGELOG.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

16.7.0.rc.0 regression: RSC client manifest is not uploaded to Pro Node Renderer

1 participant