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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions