Skip to main content

React Server Components Integration

Vinext’s App Router implementation is built on top of @vitejs/plugin-rsc, which provides the bundler transforms and runtime infrastructure for React Server Components. This guide explains how the integration works and the patterns used.

RSC Entry Point

The RSC entry (virtual:vinext-rsc-entry) is the request handler for all App Router requests. It runs in the rsc Vite environment with the react-server import condition.

Request Handler Export

From packages/vinext/src/server/app-dev-server.ts:
Key patterns:
  • All async context uses AsyncLocalStorage.run() for proper isolation
  • Headers and cookies are available via headers() and cookies() throughout the tree
  • Per-request cache state is initialized once
  • Fetch cache tracks tags for revalidation

Request Lifecycle

The _handleRequest function implements the full request lifecycle:
  1. Protocol-relative URL guard - Reject paths starting with //
  2. Base path stripping - Remove basePath prefix if configured
  3. Trailing slash normalization - Redirect to canonical form
  4. Config redirects - Apply redirects from next.config.js
  5. beforeFiles rewrites - Apply before file-system routing
  6. Middleware execution - Run middleware.ts if path matches
  7. Image optimization - Handle /_vinext/image endpoint
  8. Metadata routes - Serve sitemap.xml, robots.txt, manifest.json
  9. Server actions - Handle POST requests with x-rsc-action header
  10. afterFiles rewrites - Apply after file-system routing
  11. Route matching - Find matching App Router route
  12. fallback rewrites - Apply if no route matched
  13. Route handler execution - Run route.ts if present
  14. Page rendering - Build component tree and render to RSC stream
  15. SSR delegation - Pass RSC stream to SSR entry for HTML generation

Component Tree Rendering

Metadata Resolution

Metadata and viewport are resolved from layouts and pages before rendering:
resolveModuleMetadata() handles both static exports and generateMetadata() functions:

Thenable Params

Next.js 15+ changed params and searchParams to Promises. Vinext creates “thenable objects” for backward compatibility:
This pattern is applied to:
  • Page component props
  • Layout component props
  • generateMetadata() arguments
  • generateViewport() arguments

Boundary Components

Vinext wraps the component tree with error, loading, and not-found boundaries: Loading Boundary:
Error Boundary:
NotFound Boundary:
Boundaries are interleaved with layouts so errors propagate correctly:
This ensures errors from Layout N are caught by the boundary at Layout N-1.

Server Actions

Server actions are POST requests with the x-rsc-action header:

CSRF Protection

Vinext implements the same CSRF protection as Next.js:

Action Execution

Key details:
  • Actions support both FormData and text bodies
  • Temporary references enable streaming large payloads
  • redirect() in actions is detected via digest
  • Page is re-rendered after mutation to reflect changes
  • Cookies set during action are attached to response

SSR Delegation

After rendering the RSC stream, the RSC entry delegates to the SSR entry for HTML generation:
Why pass navigation context explicitly? The RSC and SSR environments have separate module instances. Setting setNavigationContext() in the RSC environment doesn’t affect the SSR environment. Client components rendered during SSR need pathname/searchParams/params. The SSR entry receives the context and calls its own setNavigationContext() before rendering.

Route Handlers

Route handlers (route.ts) are special-cased:

Error Handling

RSC onError Callback

Vinext provides an onError callback to preserve digests for navigation errors:
Without this, React’s default onError returns undefined and the digest is lost. Client-side error boundaries can’t identify the error type (redirect, notFound, etc.).

Error Page Rendering

When a server component throws, Vinext renders the error boundary page:
Important: Next.js returns HTTP 200 when error.tsx catches an error (the error is “handled” by the boundary). Vinext matches this behavior.

Next Steps

Architecture Deep Dive

Core architecture and design patterns

Build Pipeline

Production build pipeline details

Virtual Modules

Virtual module system and generation