[PR #698] fix: server action redirects use soft RSC navigation instead of hard reload (#654) #780

Open
opened 2026-05-06 13:10:04 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/698
Author: @yunus25jmi1
Created: 3/27/2026
Status: 🔄 Open

Base: mainHead: fix/issue-654-action-redirect-soft-nav


📝 Commits (10+)

  • de4bf6f fix: server action redirects use soft RSC navigation instead of hard reload (#654)
  • 7a94313 fix: use manual glob implementation for Node compatibility
  • ed29480 fix: complete soft RSC navigation for server action redirects
  • c714eb3 fix: improve file-matcher glob handling and update snapshots
  • c16cae3 fix: address review feedback for soft RSC navigation
  • 0fb28ce test: update entry-templates snapshots after review fixes
  • 7a249da fix: refactor scanWithExtensions to use glob for file matching
  • 28750cd fix(server-actions): address round-3 review feedback for soft redirects
  • 0730add test: update entry-templates snapshots after round-3 review fixes
  • f14713c fix(rewrites): include middleware headers in static file responses

📊 Changes

8 files changed (+1192 additions, -1265 deletions)

View changed files

📝 packages/vinext/src/entries/app-rsc-entry.ts (+129 -5)
📝 packages/vinext/src/index.ts (+62 -29)
📝 packages/vinext/src/server/app-browser-entry.ts (+82 -12)
📝 packages/vinext/src/server/prod-server.ts (+49 -0)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+774 -1219)
📝 tests/e2e/app-router/server-actions.spec.ts (+52 -0)
tests/fixtures/app-basic/app/action-self-redirect/page.tsx (+29 -0)
📝 tests/fixtures/app-basic/app/actions/actions.ts (+15 -0)

📄 Description

Fixes #654

What changed

This PR fixes the RSC parity gap where server action redirects caused full page reloads instead of SPA-style soft navigation like Next.js does.

Server-side (app-rsc-entry.ts)

  • When a server action calls redirect(), the server now pre-renders the redirect target's RSC payload
  • For same-origin routes: builds and renders the redirect target page to an RSC stream
  • For external URLs or unmatched routes: falls back to empty-body response (hard redirect)
  • Graceful error handling: if pre-rendering fails, falls back to hard redirect instead of 500

Client-side (app-browser-entry.ts)

  • Detects RSC payload via content-type header
  • When payload present: parses RSC stream, updates React tree with startTransition, updates URL via history.pushState/replaceState
  • Falls back to hard redirect for empty bodies or parse errors

Tests

  • Added E2E test verifying soft RSC navigation (no page reload on redirect)
  • All 11 server actions tests pass

Additional fix

  • Fixed file-matcher.ts to use manual glob implementation for Node.js < 22.14 compatibility

Testing

  • All server actions E2E tests pass (11/11)
  • TypeScript type checks pass
  • Build completes successfully

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/698 **Author:** [@yunus25jmi1](https://github.com/yunus25jmi1) **Created:** 3/27/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/issue-654-action-redirect-soft-nav` --- ### 📝 Commits (10+) - [`de4bf6f`](https://github.com/cloudflare/vinext/commit/de4bf6f5b281fac96e29f709b76e47d6c334dc14) fix: server action redirects use soft RSC navigation instead of hard reload (#654) - [`7a94313`](https://github.com/cloudflare/vinext/commit/7a94313eb5e4184940772dff480099b53d0e44fd) fix: use manual glob implementation for Node compatibility - [`ed29480`](https://github.com/cloudflare/vinext/commit/ed294800b27f2b36093b9f03f0f1c06dd37c3283) fix: complete soft RSC navigation for server action redirects - [`c714eb3`](https://github.com/cloudflare/vinext/commit/c714eb319e9f61564702204e67cf3d2b9959da55) fix: improve file-matcher glob handling and update snapshots - [`c16cae3`](https://github.com/cloudflare/vinext/commit/c16cae3d8c0164eca05d6fe53c06f21e2bf81482) fix: address review feedback for soft RSC navigation - [`0fb28ce`](https://github.com/cloudflare/vinext/commit/0fb28cee191649bead0696f6aea9df1afee495b9) test: update entry-templates snapshots after review fixes - [`7a249da`](https://github.com/cloudflare/vinext/commit/7a249da78da9a2808e25cac449417c0f4c9e4402) fix: refactor scanWithExtensions to use glob for file matching - [`28750cd`](https://github.com/cloudflare/vinext/commit/28750cd87c3a8939ec138add7cb0be2a69a5a198) fix(server-actions): address round-3 review feedback for soft redirects - [`0730add`](https://github.com/cloudflare/vinext/commit/0730add078d7d6bebc9f227ba621d2cb8ac37ac7) test: update entry-templates snapshots after round-3 review fixes - [`f14713c`](https://github.com/cloudflare/vinext/commit/f14713cbb8a6d17ce60604a8a7f37eb2764aa57c) fix(rewrites): include middleware headers in static file responses ### 📊 Changes **8 files changed** (+1192 additions, -1265 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/entries/app-rsc-entry.ts` (+129 -5) 📝 `packages/vinext/src/index.ts` (+62 -29) 📝 `packages/vinext/src/server/app-browser-entry.ts` (+82 -12) 📝 `packages/vinext/src/server/prod-server.ts` (+49 -0) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+774 -1219) 📝 `tests/e2e/app-router/server-actions.spec.ts` (+52 -0) ➕ `tests/fixtures/app-basic/app/action-self-redirect/page.tsx` (+29 -0) 📝 `tests/fixtures/app-basic/app/actions/actions.ts` (+15 -0) </details> ### 📄 Description Fixes #654 ## What changed This PR fixes the RSC parity gap where server action redirects caused full page reloads instead of SPA-style soft navigation like Next.js does. ### Server-side (app-rsc-entry.ts) - When a server action calls redirect(), the server now pre-renders the redirect target's RSC payload - For same-origin routes: builds and renders the redirect target page to an RSC stream - For external URLs or unmatched routes: falls back to empty-body response (hard redirect) - Graceful error handling: if pre-rendering fails, falls back to hard redirect instead of 500 ### Client-side (app-browser-entry.ts) - Detects RSC payload via content-type header - When payload present: parses RSC stream, updates React tree with startTransition, updates URL via history.pushState/replaceState - Falls back to hard redirect for empty bodies or parse errors ### Tests - Added E2E test verifying soft RSC navigation (no page reload on redirect) - All 11 server actions tests pass ### Additional fix - Fixed file-matcher.ts to use manual glob implementation for Node.js < 22.14 compatibility ## Testing - All server actions E2E tests pass (11/11) - TypeScript type checks pass - Build completes successfully --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#780
No description provided.