You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge remote-tracking branch 'origin/main' into jg/test-concurrent-ports
* origin/main:
docs: clarify extensible precompile ownership (#3226)
docs: fix broken Empirical-Core GitHub link in PROJECTS.md (#3326)
docs(planning): PPR implementation plan for React on Rails (#3323)
docs: plan React 19 partial pre-rendering work (#3237)
Relax Pro jwt dependency to allow 3.2.0 security fix
docs(planning): plan RSCRoute ssr=false implementation (#3317)
docs: Add PPR investigation findings (#3314)
feat(pro): Async props & incremental RSC rendering + length-prefixed streaming protocol (#2903)
fix: stale references and lost Gemfile pins after Pro migration (#3104)
Restore Metrics/ModuleLength limit to 180
Clarify RuboCop lint contract
Exclude dead project URLs from markdown link check (#3306)
Canonicalize GitHub links in docs
Reduce `react-on-rails-pro-node-renderer` package size (#3304)
fix: format stray markdown files and correct broken link breaking CI on main (#3301)
docs(planning): JSON render-request body migration plan (#3280) (#3299)
docs: experiment plan for decoupling props from JS source (#3281) (#3297)
docs: memory leakage investigation report for SSR pipeline (#3296)
docs: fix MDX-incompatible patterns blocking sc-website docs sync (#3275)
'^https://github\.com/shakacode/react_on_rails/pull/[0-9]+$', # Intermittent 5xx from GitHub PR pages in CI
119
+
'^https://github\.com/shakacode/react_on_rails/actions/workflows/pro-test-package-and-gem\.yml$', # Intermittent 502 from GitHub Actions workflow pages in CI
117
120
'^https://github\.com/shakacode/react_on_rails/issues/2766$', # Intermittent 502 from GitHub issue pages in CI
118
121
'^https://github\.com/rack/rack/blob/main/SPEC\.rdoc$', # Intermittent 502 from GitHub blob pages in CI
119
122
'^https://github\.com/shakacode/shakapacker/blob/cdf32835d3e0949952b8b4b53063807f714f9b24/package/environments/base\.js(#.*)?$', # Intermittent 502 from GitHub blob view in CI
123
+
'^https://github\.com/npm/cli/issues/6253$', # Intermittent 502 from GitHub issue pages in CI
124
+
'^https://github\.com/search\?q=gem\+react_on_rails&ref=advsearch&type=repositories&utf8=%E2%9C%93$', # Intermittent 502 from GitHub search in CI
Copy file name to clipboardExpand all lines: CHANGELOG.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,15 +36,19 @@ After a release, run `/update-changelog` in Claude Code to analyze commits, writ
36
36
#### Added
37
37
38
38
-**[Pro]****Pre-seed renderer cache for Docker builds**: New `react_on_rails_pro:pre_seed_renderer_cache` rake task copies compiled server bundles into the Node Renderer's bundle-hash cache directory structure during Docker image builds, eliminating the 410→retry cold-start latency (200ms–1s+) on the first SSR request after deployment. Supports `RENDERER_SERVER_BUNDLE_CACHE_PATH`, RSC bundles, and rolling-deploy guidance centered on current and previous bundle hashes. The legacy `pre_stage_bundle_for_node_renderer` task now stages the same cache layout via symlinks for same-filesystem workflows. **Note:**`RENDERER_BUNDLE_PATH` is now deprecated in favor of `RENDERER_SERVER_BUNDLE_CACHE_PATH` across both tasks. Existing users with `RENDERER_BUNDLE_PATH` set will see a deprecation warning on stderr. [PR 3124](https://github.com/shakacode/react_on_rails/pull/3124) by [justin808](https://github.com/justin808).
39
+
-**[Pro]****Async props with incremental React Server Component rendering**: Added the `stream_react_component_with_async_props` and `rsc_payload_react_component_with_async_props` view helpers, which accept a block to declare props that are fetched concurrently and streamed to the rendering component as each value becomes available. The React component renders its shell immediately (with `<Suspense>` fallbacks) and progressively re-renders as async prop promises resolve, dramatically improving Time to First Byte for pages with slow data fetches. Components access async props through the `getReactOnRailsAsyncProp` function injected into props (typed via the new `WithAsyncProps` TypeScript helper). Requires `config.enable_rsc_support = true`. This is an additive feature — existing `stream_react_component` and `rsc_payload_react_component` calls are unaffected. [PR 2903](https://github.com/shakacode/react_on_rails/pull/2903) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
39
40
40
41
#### Changed
41
42
42
43
- **[Pro]** **Unified renderer cache staging**: `ReactOnRailsPro::PreSeedRendererCache.call(mode: :copy | :symlink)` is now the single entry point for staging the Node Renderer cache. Both modes produce the same `<cache>/<bundleHash>/<bundleHash>.js` layout. The `react_on_rails_pro:pre_seed_renderer_cache` rake task accepts `MODE=copy` (default; Docker/image builds) or `MODE=symlink` (same-filesystem). The auto-invocation at the end of `assets:precompile` defaults to `:symlink` (preserving prior behavior) and now honors `ASSETS_PRECOMPILE_RENDERER_CACHE_MODE=copy|symlink` so Docker builds that run `rake assets:precompile` as the final asset step can opt into copy mode without invoking the rake task separately. `MODE=copy` raises a clear error when neither `RENDERER_SERVER_BUNDLE_CACHE_PATH` nor `RENDERER_BUNDLE_PATH` is set in non-dev/test environments, because the Node renderer's default lookup can differ from the Ruby side and would silently drop pre-seeded bundles in the wrong directory. The legacy `react_on_rails_pro:pre_stage_bundle_for_node_renderer` task and `ReactOnRailsPro::PrepareNodeRenderBundles` class remain as deprecated shims that emit a once-per-process warning and delegate to `mode: :symlink`. `react_on_rails:doctor` flags deploy scripts that still reference the deprecated task. **Heads-up for custom scripts:** the previous flat layout wrote `$RENDERER_BUNDLE_PATH/<renderer_bundle_file_name>`; any external scripts (health checks, renderer launchers) that read that path directly must now read `$RENDERER_SERVER_BUNDLE_CACHE_PATH/<bundleHash>/<bundleHash>.js` instead. [PR 3124](https://github.com/shakacode/react_on_rails/pull/3124) by [justin808](https://github.com/justin808).
43
44
-**[Pro]****Pro generator now creates the Node Renderer at `renderer/node-renderer.js`**: The canonical location for the Node Renderer entry point is now a dedicated top-level `renderer/` directory instead of `client/`, making it straightforward to exclude from production Docker builds that strip JS sources after bundling. Docs and Pro `spec/dummy` now use the new path consistently. Existing apps are unaffected — the generator skips files that already exist (including a legacy `client/node-renderer.js`). Fixes [Issue 3073](https://github.com/shakacode/react_on_rails/issues/3073). [PR 3165](https://github.com/shakacode/react_on_rails/pull/3165) by [justin808](https://github.com/justin808).
44
45
-**[Pro] Documentation standardized on `REACT_RENDERER_URL` env var name**: The configuration example in `docs/oss/configuration/configuration-pro.md` now shows `ENV["REACT_RENDERER_URL"]` instead of the older `ENV["RENDERER_URL"]`, aligning with the rest of the docs and the generator template. Existing apps that read `ENV["RENDERER_URL"]` in their initializer continue to work — the Pro `renderer_url` config is whichever env var the user reads in their initializer; no gem code reads either name directly. Rename the env var in your infrastructure configs (and update the initializer to match) if you want to align with the new convention. `bin/dev` now also warns when `RENDERER_URL` is set without `REACT_RENDERER_URL` so the rename doesn't silently fall back to the default renderer URL. [PR 3142](https://github.com/shakacode/react_on_rails/pull/3142) by [justin808](https://github.com/justin808).
46
+
-**Length-prefixed streaming wire protocol**: The internal protocol between the Rails gems and the Node renderer (and the in-process bundle for the OSS non-streaming path) now uses a length-prefixed framing — `<metadata JSON>\t<content byte length hex>\n<raw content bytes>` — instead of wrapping every HTML chunk in a JSON envelope, eliminating ~30% serialize/escape overhead on streamed HTML and correctly handling multibyte content and chunk boundaries. This is an internal transport detail: React on Rails always ships the `react_on_rails`/`react_on_rails_pro` gems, the `react-on-rails`/`react-on-rails-pro` npm packages, and the `react-on-rails-pro-node-renderer` as a matched version set, and the Ruby parser also auto-detects the legacy JSON format, so no application action is required when upgrading all artifacts together. [PR 2903](https://github.com/shakacode/react_on_rails/pull/2903) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
45
47
46
48
#### Fixed
47
49
50
+
-**[Pro]****Allow patched ruby-jwt releases**: React on Rails Pro now requires `jwt >= 3.2.0`, removing the previous `~> 2.7` cap so applications can resolve the patched ruby-jwt release for the empty-key HMAC advisory. [PR 3322](https://github.com/shakacode/react_on_rails/pull/3322) by [ihabadham](https://github.com/ihabadham).
51
+
-**[Pro]****Pro migration generator rewrites all base-package references and preserves Gemfile pins**: `rails generate react_on_rails:pro` now rewrites Jest/Vitest mock helpers (`jest.mock`, `vi.mock`, `requireActual`/`importActual`, and the rest) and TypeScript `declare module 'react-on-rails'` blocks alongside its existing `import`/`require`/dynamic-import handling, and the Gemfile swap now preserves the user's existing version pin (and other gem options) instead of overwriting them with the running gem's version. `react_on_rails:doctor` is widened to match: it also flags stale side-effect imports (`import 'react-on-rails';`), Jest/Vitest mock helpers, and `declare module` blocks, and the new side-effect-import pattern keeps the doctor a superset of the rewriter so anything the rewriter doesn't reach gets surfaced. Closes [Issue 3104](https://github.com/shakacode/react_on_rails/issues/3104). [PR 3232](https://github.com/shakacode/react_on_rails/pull/3232) by [justin808](https://github.com/justin808).
48
52
-**Doctor now honors nested JavaScript package roots**: `react_on_rails:doctor` now checks package-manager lockfiles, `package.json`, and installed React from the configured `node_modules_location`, reducing false diagnostics for legacy apps that keep dependencies under `client/`. The Vite migration guide now documents the supported thin-wrapper pattern for those layouts. Note: a missing `package.json` at the configured `node_modules_location` now emits a warning instead of being silently skipped, so apps misconfigured against a nonexistent path will see new diagnostics on upgrade. Fixes [Issue 3205](https://github.com/shakacode/react_on_rails/issues/3205). [PR 3220](https://github.com/shakacode/react_on_rails/pull/3220) by [justin808](https://github.com/justin808).
49
53
-**Generated pack regeneration is now serialized**: `generate_packs_if_stale` now uses a Rails `tmp/` lock file, re-checks staleness after waiting, and avoids concurrent cleanup/regeneration races when multiple processes trigger auto-bundling at the same time. Fixes [Issue 1627](https://github.com/shakacode/react_on_rails/issues/1627). [PR 3231](https://github.com/shakacode/react_on_rails/pull/3231) by [justin808](https://github.com/justin808).
50
54
-**Install generator validates the selected JavaScript package manager**: The install generator now checks the manager selected from `REACT_ON_RAILS_PACKAGE_MANAGER`, the `packageManager` field in `package.json`, or a lockfile on disk — instead of passing when any JavaScript package manager is installed. When the selected command is missing, the error names the selected manager, the source that selected it, and the available alternatives. The generator also warns when `REACT_ON_RAILS_PACKAGE_MANAGER` is set to a value outside the supported set (`npm`, `pnpm`, `yarn`, `bun`). Addresses package manager validation from [Issue 1958](https://github.com/shakacode/react_on_rails/issues/1958). [PR 3229](https://github.com/shakacode/react_on_rails/pull/3229) by [justin808](https://github.com/justin808).
@@ -55,6 +59,10 @@ After a release, run `/update-changelog` in Claude Code to analyze commits, writ
55
59
-**Client startup now recovers if initialization begins during `interactive` after `DOMContentLoaded` already fired**: React on Rails now still initializes the page when the client bundle starts in the browser timing window after `DOMContentLoaded` but before the document reaches `complete`. Fixes [Issue 3150](https://github.com/shakacode/react_on_rails/issues/3150). [PR 3151](https://github.com/shakacode/react_on_rails/pull/3151) by [ihabadham](https://github.com/ihabadham).
56
60
-**Doctor accepts TypeScript server bundle entrypoints**: `react_on_rails:doctor` now resolves common source entrypoint suffixes (`.js`, `.jsx`, `.ts`, `.tsx`, `.mjs`, `.cjs`) before warning that the server bundle is missing, preventing false positives when apps use `server-bundle.ts`. [PR 3111](https://github.com/shakacode/react_on_rails/pull/3111) by [justin808](https://github.com/justin808).
57
61
-**Doctor no longer fails custom projects for a missing generated `bin/dev`**: `react_on_rails:doctor` now downgrades a missing official React on Rails `bin/dev` launcher from an error to a warning and adds explicit guidance when a custom `./dev` script is detected, so custom projects can pass diagnostics when their development setup is intentional. Fixes [Issue 3103](https://github.com/shakacode/react_on_rails/issues/3103). [PR 3117](https://github.com/shakacode/react_on_rails/pull/3117) by [justin808](https://github.com/justin808).
62
+
-**[Pro]****Reduced `react-on-rails-pro-node-renderer` published package size**: added a `files` whitelist to `package.json` so `pnpm pack` no longer includes `src/`, `tests/` fixtures, `*.map`, and `lib/tsconfig.tsbuildinfo` — matching the convention used by the sibling packages. Also marked `react_on_rails_pro/spec/dummy` as `private` so it can never be accidentally published. [PR 3304](https://github.com/shakacode/react_on_rails/pull/3304) by [alexeyr-ci2](https://github.com/alexeyr-ci2).
63
+
-**[Pro]****HTTPX bidirectional streaming reliability**: Fixed streaming request timeouts when using HTTPX with both the `:stream` and `:stream_bidi` plugins. The request now uses the `build_request` pattern with an explicit `request.close` so the HTTP/2 `END_STREAM` flag is sent, and a temporary monkey-patch (`httpx_stream_bidi_patch.rb`) works around an upstream `:stream_bidi` retry bug that left stale body callbacks registered and crashed retried requests with `protocol_error`. The patch is scoped and will be removed once fixed upstream. [PR 2903](https://github.com/shakacode/react_on_rails/pull/2903) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
64
+
-**[Pro]****Progressive RSC streaming flush granularity**: RSC streaming now flushes on React's per-render-cycle `flush()` signal instead of `setTimeout(flush, 0)`, so the shell and each resolved `<Suspense>` boundary stream as separate chunks rather than being merged into one large first message. This restores progressive streaming (and fixes worse-than-SSR First Contentful Paint) on pages with fast queries, and eliminates partial-HTML-tag chunks. Fixes [Issue 3194](https://github.com/shakacode/react_on_rails/issues/3194). [PR 2903](https://github.com/shakacode/react_on_rails/pull/2903) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
65
+
-**[Pro]****Node renderer graceful shutdown after stream timeouts**: Fixed workers taking 30+ seconds to shut down after a `StreamChunkTimeoutError` during streaming. `handleGracefulShutdown` now also decrements the active-request count on `onRequestAbort`/`onTimeout`, the `PassThrough` wrapper is destroyed when the source render stream errors, and the HTTP response is closed on chunk timeout so connections to Rails no longer hang. Fixes [Issue 2270](https://github.com/shakacode/react_on_rails/issues/2270) and [Issue 2308](https://github.com/shakacode/react_on_rails/issues/2308). [PR 2903](https://github.com/shakacode/react_on_rails/pull/2903) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -54,9 +54,9 @@ It's critical to configure your IDE/editor to ignore certain directories. Otherw
54
54
55
55
# Example apps
56
56
57
-
The [`react_on_rails/spec/dummy` app](https://github.com/shakacode/react_on_rails/blob/main/react_on_rails/spec/dummy) is an example of the various setup techniques you can use with the gem.
57
+
The [`react_on_rails/spec/dummy` app](https://github.com/shakacode/react_on_rails/tree/main/react_on_rails/spec/dummy) is an example of the various setup techniques you can use with the gem.
58
58
59
-
There are also two such apps for React on Rails Pro: [one using the Node renderer](https://github.com/shakacode/react_on_rails/blob/main/react_on_rails_pro/spec/dummy) and [one using ExecJS](https://github.com/shakacode/react_on_rails/blob/main/react_on_rails_pro/spec/execjs-compatible-dummy).
59
+
There are also two such apps for React on Rails Pro: [one using the Node renderer](https://github.com/shakacode/react_on_rails/tree/main/react_on_rails_pro/spec/dummy) and [one using ExecJS](https://github.com/shakacode/react_on_rails/tree/main/react_on_rails_pro/spec/execjs-compatible-dummy).
60
60
61
61
When you add a new feature, consider adding an example demonstrating it to the example apps.
Copy file name to clipboardExpand all lines: PROJECTS.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,7 +37,7 @@ _Please support the project by [emailing Justin Gordon](mailto:justin@shakacode.
37
37
38
38
## Open Source Projects Live
39
39
40
-
-[github.com/empirical-org/Empirical-Core](https://github.com/empirical-org/Empirical-Core): [Quill.org](https://quill.org/) Provides free tools to make your students better writers.
40
+
-**[Quill.org](https://quill.org/)**: Provides free tools to make your students better writers.
41
41
-**[Coderwall](https://coderwall.com/)**: The latest development and design tips, tools, and projects from our developer community. Source at [github.com/coderwall/coderwall-next](https://github.com/coderwall/coderwall-next)
0 commit comments