cloudflare / cloudflare/vinext

RSC parity gap: action redirects use hard navigation instead of soft RSC navigation

Open
#654 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.