Add rspack migration with 7.6x faster builds#68
Conversation
Move both Ruby gems (react_on_rails, react_on_rails_pro) to the feat/async-http-with-async-props branch and JS packages to the matching react-on-rails-builds commit adcff279. The Pro gem's HTTP transport migrates from HTTPX to async-http, so the httpx pin is no longer needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This initializer was a workaround for the HTTPX H2 pool-leak bug (react_on_rails#3295). The async-http migration in this PR's gem version makes HTTP clients request-scoped — no shared pool to leak — so the workaround is no longer needed. It is also incompatible with the new gem: it patches StreamRequest#initialize with the old single-block signature, which now triggers "wrong number of arguments (given 1, expected 0)" on the first streaming render. Verified by running the app against the new gem and confirming that every page (incl. /restaurant/:id/rsc, /product/rsc, /blog/rsc*) renders cleanly with no SSR or hydration errors, and an idle-then-RSC request (150s wait) completes without the old GOAWAY hang. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Includes rspack config files, bundle/asset measurement scripts, migration documentation, and rspack npm dependencies. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rspack/core v2 requires Node.js 22.12.0+. Adding .node-version and .nvmrc so version managers (fnm, nvm, volta) pick up the requirement automatically. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Warning Review limit reached
Your plan includes 1 review of capacity. Refill in 30 minutes and 48 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (18)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis PR adds a complete Rspack 2 build configuration mirroring the existing webpack setup, achieving a 7.6x build speed improvement. It also switches the React on Rails gem dependencies to the
Confidence Score: 3/5The rspack config itself is well-structured and tested, but two issues prevent this from being runnable by any other contributor: the react-on-rails-rsc dependency points to a gitignored local yalc directory, and both measurement shell scripts embed an absolute path to the author's SSD. The rspack configs, optimization fixes, and plugin wiring are solid and match the described test plan. However, package.json references react-on-rails-rsc as file:.yalc/react-on-rails-rsc — a directory that is explicitly listed in .gitignore and will not exist on any other machine — causing pnpm install to fail immediately after clone. The measurement scripts additionally hard-code an absolute SSD path, silently producing zeroes for every file check. These two issues need to be resolved before the branch is usable for CI or other team members. package.json (broken yalc dependency), scripts/measure-gzip-assets.sh and scripts/measure-page-assets.sh (hard-coded absolute paths) Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["rspack.config.js\n(entry point)"] --> B{"NODE_ENV"}
B -->|development| C["development.js"]
B -->|production| D["production.js"]
B -->|test| E["test.js"]
C --> F["ServerClientOrBoth(envSpecific)"]
D --> F
E --> F
F --> G["commonRspackConfig()\ngenerateRspackConfig() + merge"]
G --> H["clientRspackConfig()\nRSCRspackPlugin isServer:false\nsplitChunks.chunks=all\nruntimeChunk=single"]
G --> I["serverRspackConfig()\nRSCRspackPlugin isServer:true\nLimitChunkCountPlugin maxChunks:1\ntarget:node"]
G --> J["rscRspackConfig()\nserverRspackConfig(rscBundle=true)\nWebpackLoader enforce:post\nconditionNames:react-server"]
F --> K{"Bundle env var?"}
K -->|CLIENT_BUNDLE_ONLY| H
K -->|SERVER_BUNDLE_ONLY| I
K -->|RSC_BUNDLE_ONLY| J
K -->|none| L["[clientConfig, serverConfig, rscConfig]"]
H --> M["public/packs/\nclient bundle + manifests"]
I --> N["ssr-generated/\nserver-bundle.js"]
J --> O["ssr-generated/\nrsc-bundle.js"]
Reviews (1): Last reviewed commit: "Add Node.js 22.12.0 version files for rs..." | Re-trigger Greptile |
| "react-on-rails-rsc": "github:shakacode/react_on_rails_rsc#update-rsc-19.0.3-fouc-runtime-chunk-fixes", | ||
| "react-on-rails-pro": "github:shakacode/react-on-rails-builds#adcff279edd06ad986d0122197abe9e932ed888a&path:react-on-rails-pro", | ||
| "react-on-rails-pro-node-renderer": "github:shakacode/react-on-rails-builds#adcff279edd06ad986d0122197abe9e932ed888a&path:react-on-rails-pro-node-renderer", | ||
| "react-on-rails-rsc": "file:.yalc/react-on-rails-rsc", |
There was a problem hiding this comment.
Local yalc path breaks
pnpm install for all other contributors
file:.yalc/react-on-rails-rsc references a directory that is listed in .gitignore, so it is never committed to the repo. Anyone who clones this repository and runs pnpm install will get an error because .yalc/react-on-rails-rsc does not exist on their machine. The intent appears to be to land the upstream rspack-plugin bug fixes and then reference the published or tagged commit, but the yalc dev-loop reference slipped in. The specifier should be replaced with the upstream GitHub commit/branch once the fixes land (e.g. github:shakacode/react_on_rails_rsc#<sha>).
|
|
||
| LABEL="${1:-unknown}" | ||
| BASE="http://localhost:3000" | ||
| PACKS_DIR="/mnt/ssd/shakacode-related/localhub-demo/public" |
There was a problem hiding this comment.
Hard-coded absolute path breaks the script for any machine other than the author's
PACKS_DIR is set to an absolute path that only exists on the developer's local SSD. Any other contributor who runs this script will silently get 0 KB for every file size because all the [ -f "$fpath" ] checks fail. The path should be derived dynamically from the repo root.
| PACKS_DIR="/mnt/ssd/shakacode-related/localhub-demo/public" | |
| PACKS_DIR="${PACKS_DIR:-$(git rev-parse --show-toplevel)/public}" |
|
|
||
| LABEL="${1:-unknown}" | ||
| BASE="http://localhost:3000" | ||
| PACKS_DIR="/mnt/ssd/shakacode-related/localhub-demo/public" |
There was a problem hiding this comment.
Same hard-coded absolute path as in
measure-gzip-assets.sh — will silently produce zero-byte results on any machine that is not the original author's. Should be derived from the repo root dynamically.
| PACKS_DIR="/mnt/ssd/shakacode-related/localhub-demo/public" | |
| PACKS_DIR="${PACKS_DIR:-$(git rev-parse --show-toplevel)/public}" |
| console.log('[React on Rails] Creating only the RSC bundle (rspack).'); | ||
| result = rscConfig; | ||
| } else { | ||
| console.log('[React on Rails] Creating both client and server bundles (rspack).'); |
There was a problem hiding this comment.
Log message says "both client and server bundles" but actually exports three configs — client, server, and RSC. Misleading when tailing build logs.
| console.log('[React on Rails] Creating both client and server bundles (rspack).'); | |
| console.log('[React on Rails] Creating all three bundles: client, server, and RSC (rspack).'); |
| @@ -0,0 +1,20 @@ | |||
| process.env.NODE_ENV = process.env.NODE_ENV || 'development'; | |||
|
|
|||
| const { devServer, inliningCss } = require('shakapacker/rspack'); | |||
There was a problem hiding this comment.
Unused import —
devServer is destructured from shakapacker/rspack but never used in this file. The webpack equivalent uses it for sockPort, but the rspack ReactRefreshPlugin is instantiated with no options here.
| const { devServer, inliningCss } = require('shakapacker/rspack'); | |
| const { inliningCss } = require('shakapacker/rspack'); |
| const isHMR = process.env.HMR; | ||
|
|
||
| const overrideCssModulesConfig = (config) => { |
There was a problem hiding this comment.
Unused variable —
isHMR is declared but never referenced anywhere in this file. Carried over from the webpack equivalent (clientWebpackConfig.js) but never wired to any config path.
| const isHMR = process.env.HMR; | |
| const overrideCssModulesConfig = (config) => { | |
| const overrideCssModulesConfig = (config) => { |
Summary
config/rspack/) mirroring the existing webpack config, withRSCRspackPluginfor RSC manifest generation@rspack/core,@rspack/cli,@rspack/plugin-react-refresh, andrspack-manifest-plugindependenciesgenerateRspackConfig():splitChunks.chunks = 'all'andruntimeChunk = 'single'@rspack/corev2)scripts/measure-*.sh)RSPACK_MIGRATION.mdBuild performance
Bundle size (production, gzip)
All RSC and SSR pages are at parity or slightly smaller than webpack. Example:
RSCRspackPlugin bug fixes
Three bugs were found in
react-on-rails-rsc's RSCRspackPlugin and fixed upstream in shakacode/react_on_rails_rsc#36:beforeCompileonly ran discovery forisServer: false'use client'files absent from server manifest causedcreateSSRManifest()to throwPage status
@loadable/webpack-pluginnot included (known rspack v2 incompatibility)Verified in both development and production rspack builds with zero console errors.
How to switch bundlers
Known issues
@loadable/webpack-pluginnot included — Client pages fail (rspack v2 incompatibility)__dirnamemocked warnings from 4.server.tsxfiles (harmless)@rspack/core ^1.0.0, we use v2.0.3Closes #64
Test plan
rspack buildsucceeds in dev mode (3 bundles, 4.7s)rspack buildsucceeds in production mode (3 bundles, 3.6s)🤖 Generated with Claude Code