Skip to main content

Rendering

Choose how each page reaches the browser with adjacent page.config.ts. Pages without rendering configuration use client-side rendering (CSR).

Choose a rendering mode

Start with the simplest mode that meets the page's needs:

ModeChoose it whenServer required at request time?Browser JavaScript
CSRContent is app-like, user-specific, or loaded after navigationNoRenders the page
SSRThe first response needs page HTML or request dataYesOptional hydration
SSGThe same HTML can be created during the buildNoOptional hydration
PPRA stable shell can be built ahead while regions resolve laterYesNo page-level hydration
RSCThe page is rendered through React Server ComponentsYesClient components only

Rendering is independent from route discovery: the page stays in the same directory and keeps the same URL.

Client-side rendering

CSR is the default. You can omit page.config.ts entirely or state the choice explicitly:

src/pages/dashboard/page.config.ts
import { definePageConfig } from "@evjs/ev";

export default definePageConfig({
render: "csr",
});

Do not set hydrate for CSR. The browser creates the React tree rather than hydrating server-created markup.

Use CSR when the page does not need meaningful HTML before JavaScript runs.

Server-side rendering

SSR renders the page for each document request:

src/pages/account/page.config.ts
import { definePageConfig } from "@evjs/ev";

export default definePageConfig({
render: "ssr",
hydrate: "load",
});

hydrate: "load" makes the server-rendered page interactive after the client bundle loads. Use hydrate: "none" for HTML that should remain non-interactive at page level.

SSR requires a server-capable deployment target.

Static generation

SSG creates page HTML during ev build:

src/pages/about/page.config.ts
import { definePageConfig } from "@evjs/ev";

export default definePageConfig({
render: "ssg",
hydrate: "none",
});

Use hydrate: "load" when the generated page becomes interactive in the browser. SSG defaults to no hydration when hydrate is omitted.

Static output can be served without a request-time renderer. In SPA mode, static pages are emitted at their semantic paths: /report becomes report/index.html.

Partial prerendering

PPR builds a reusable page shell and resolves dynamic regions at request time:

src/pages/feed/page.config.ts
import { definePageConfig } from "@evjs/ev";

export default definePageConfig({
render: "ssr",
hydrate: "none",
prerender: { partial: true },
});

PPR uses SSR delivery, requires a compatible bundler and a server-capable deployment target, and cannot be combined with RSC on the same page.

React Server Components

Enable RSC for a page with rsc: true:

src/pages/catalog/page.config.ts
import { definePageConfig } from "@evjs/ev";

export default definePageConfig({
render: "ssr",
hydrate: "none",
rsc: true,
});

RSC pages use request-time server rendering. They require a compatible bundler and a server-capable deployment target. Page-level hydration remains disabled; interactive client components manage their own browser behavior.

Supported combinations

renderhydrateAdditional fieldResult
omitted or "csr"omittedBrowser-rendered page
"ssr""load" or omittedRequest-time HTML, then hydration
"ssr""none"Request-time HTML without page hydration
"ssg""load"Build-time HTML, then hydration
"ssg""none" or omittedBuild-time HTML without page hydration
"ssr""none" or omittedprerender: { partial: true }PPR
"ssr""none" or omittedrsc: trueRSC

evjs reports unsupported combinations during ev inspect and ev build.

Add page metadata

Rendering settings can share the same file with static page metadata:

src/pages/pricing/page.config.ts
import { definePageConfig } from "@evjs/ev";

export default definePageConfig({
title: "Pricing",
meta: {
description: "Compare plans and features.",
viewport: "width=device-width, initial-scale=1",
},
render: "ssg",
hydrate: "load",
});

meta creates <meta name="..." content="..."> entries. It does not provide a general head-element API. A page-specific HTML template can provide other static tags when needed.

SPA and MPA behavior

SPA and MPA use the same page rendering fields, with different document ownership:

  • SPA normally has a shared application document. Static SSG pages also emit HTML at their route paths.
  • MPA creates one document for every static page route. A colocated index.html can customize that page's template.
  • MPA does not support dynamic page paths, splats, or browser-router-only boundaries.

Rendering a page on the server does not automatically make an MPA application, and choosing MPA does not automatically select SSR.

Verify the result

Run these commands before deployment:

ev inspect
ev build

ev inspect reports the resolved rendering choice and capability errors. After ev build, check dist/client for browser assets and static HTML, and dist/server when request-time rendering is required.

Continue with Build or compare hosting options in Deployment.