Skip to content

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

@southpolesteve

Description

@southpolesteve

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

/cc @yunus25jmi1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions