cloudflare / cloudflare/vinext
RSC parity gap: action redirects use hard navigation instead of soft RSC navigation
- Dominant language
- TypeScript
- Stars
- 8.8k
- Forks
- 406
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 120
Description
## Background
When a server action calls `redirect()`, the server (in `app-rsc-entry.ts`) catches the redirect and returns a response with an empty body and an `x-action-redirect` header. The client currently detects this header and performs a hard navigation (`location.assign()` / `location.replace()`) as a workaround.
This is tracked as a known parity gap, introduced in #620 which fixed #589.
## What Next.js does
Next.js pre-renders the redirect target's RSC payload as part of the action response body. The client then uses `__VINEXT_RSC_NAVIGATE__` (or equivalent) to perform a soft RSC navigation, keeping the existing page shell and only swapping the route content, without a full browser reload.
## Current vinext behavior
Full page reload on every server action redirect. This is functionally correct but:
- Causes a flash of unstyled/loading content on redirect
- Loses any in-memory client state not persisted to the URL
- Breaks the expected SPA navigation feel
- Is inconsistent with how `router.push()` and link clicks work
## What needs to change
In `app-rsc-entry.ts` (around line 2060), when a server action response catches a `NEXT_REDIRECT`, the server should:
1. Render the redirect target route to an RSC stream
2. Send that stream as the response body (instead of an empty body)
3. Set `x-action-redirect` and `x-action-redirect-type` headers as it does now
The client in `app-browser-entry.ts` can then remove the hard redirect fallback and resume using `__VINEXT_RSC_NAVIGATE__` for all same-origin action redirects.
## References
- Fixed by (workaround): #620
- Original bug report: #589
- Relevant code: `packages/vinext/src/entries/app-rsc-entry.ts` ~line 2060, `packages/vinext/src/server/app-browser-entry.ts` ~line 144
/cc @yunus25jmi1
Contributor guide
Research direction
Start in packages/vinext/src/entries/app-rsc-entry.ts around line 2060, then trace the redirect handling in packages/vinext/src/server/app-browser-entry.ts around line 144. Verify how the server action response is built and how the client handles x-action-redirect; done means same-origin redirects use an RSC stream and __VINEXT_RSC_NAVIGATE__ without a hard reload.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- full-stack
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100