Skip to Main content

Client-side vs Server side rendering

A guide to the rendering modes supported by our frontend template, including how to configure client-side and server-side rendering, when to use each, and how components are compiled and integrated with the backend.

Our frontend template supports two rendering modes: Client-side rendering (CSR) and Server-side rendering (SSR).

Client-side Rendering (CSR)

Some components can be rendered on the client side. To enable this, add the component to the clientComponents map in the client-components.tsx file.

Example:

import { lazy } from 'react';

export const clientComponents = {
  people: lazy(() => import('./organisms/people')),
  header: lazy(() => import('./organisms/header')),
};

This map is then merged into the blocks registry consumed by react-loader.tsx, which is the runtime entry point loaded by the browser. Keeping the registration in src/client-components.tsx (rather than in xpack/react-loader.tsx) means the list of CSR components stays inside src/ next to the components they reference, while the loader itself remains part of the build tooling under xpack/.

Each registered client component is lazy loaded through a dynamic import. That means the browser does not download the component's implementation up front; it only fetches the actual logic and generated files for a component on pages where that component is present and rendered.

CSR components can use React hooks like useState and useEffect. These components are not rendered by the backend; however, the backend can provide initial data or respond to API requests. For more details, refer to the Integration with Frontend documentation.

These components are still built as part of the frontend bundle so the backend can serve them to end users, but they are delivered as separate lazy-loaded chunks instead of being eagerly loaded on every page.

Server-side Rendering (SSR)

The template uses Vite's SSR capabilities with some customization and limitations. This setup enables the backend to retain control over rendering through the Razor engine wherever possible.

Components that are not listed in the above blocks variable support server-side rendering only. Their TSX code is used purely for demonstration purposes. During compilation, the template generates static HTML samples based on them.

The backend team then integrates these samples into ASP.NET Razor files as usual and replaces the placeholder data with actual data.

SSR components cannot use client-side hooks like useState or useEffect and do not support hydration. This means any logic written in their TSX files is intended only for preview or illustration. Backend logic is responsible for tasks such as null checks or deciding whether to render child elements, so the frontend can skip these checks.

Any logic defined in TSX files for SSR-only components will be discarded at compile time. If these components require client-side interaction or behavior, they should import scripts from the src/assets/scripts folder.
This folder contains all client-side scripts that are compiled and delivered to the backend to serve end users.