NexusRenderer
NexusRenderer
is a server-only component that can improve performance by delegating rendering to the client.
Core Concept: Rendering Delegation
When a user navigates between pages, they might already have fresh data for the next page in their client-side cache. In this scenario, having the server re-fetch and re-render the components is redundant work that increases Time to First Byte (TTFB) and server costs.
NexusRenderer
solves this by checking the client’s cache state before rendering on the server. If it determines the client has fresh data for the required definition
(s), it skips server-rendering the component and instead sends a lightweight placeholder, instructing the client to render it immediately using the cached data.
Import
import { NexusRenderer } from 'next-nexus/server';
How It Works
NexusRenderer
relies on client cache metadata sent with RSC requests (see NexusRuntime
). It compares the definition
(s) you provide against this metadata to check for cache freshness (based on revalidate
TTL).
- If fresh: It delegates rendering to the client.
- If stale or missing: It renders the
serverComponent
and triggers the necessary server-sidenexus
calls to hydrate the client.
Usage
You provide NexusRenderer
with both a server and a client version of a component.
serverComponent
: The component to render on the server if data is not fresh on the client.clientComponent
: The component to render on the client. This is often the same component as the server one, but re-exported from a'use client'
file.
With a Single Definition
// components/ProductListUI.tsx (can be a Server Component)
import type { Product } from '@/api/productDefinition';
const ProductListUI = ({ data, title }: { data: Product[]; title: string }) => (
<div>
<h2>{title}</h2>
<ul>{data.map(p => <li key={p.id}>{p.name}</li>)}</ul>
</div>
);
export default ProductListUI;
// components/client/ui.ts (re-export for client use)
'use client';
export { default as ProductListUIClient } from '@/components/ProductListUI';
// app/page.tsx (Server Component)
import { NexusRenderer } from 'next-nexus/server';
import { productDefinition } from '@/api/productDefinition';
import ProductListUI from '@/components/ProductListUI';
import { ProductListUIClient } from '@/components/client/ui';
export default function Page() {
return (
<NexusRenderer
definition={productDefinition.list}
serverComponent={ProductListUI}
clientComponent={ProductListUIClient}
componentProps={{ title: 'Our Products' }}
/>
);
}
With a Group of Definitions
You can also provide a map of definitions. If at least one is fresh on the client, the renderer will delegate. It will still prefetch any stale definitions in the background on the server to ensure the client has all necessary data.
<NexusRenderer
definitions={{ products: productDefinition.list, stats: statsDefinition.summary }}
serverComponent={ServerGroup}
clientComponent={ClientGroup}
componentProps={{ title: 'Overview' }}
/>
Important Considerations
- Hydration must be enabled:
NexusRenderer
requiresNexusHydrationBoundary
to be active in the component tree. - Client Component Exports: The
clientComponent
must be exported from a file that has the'use client'
directive at the top. - No Server-Only APIs: Do not use server-only APIs (like database clients or file system access) directly within a component passed to
NexusRenderer
, as it may need to render on the client. Fetch data outside the component and pass it as props.
See also