Server-Side Rendering (SSR)
Server-Side Rendering (SSR)
Our web application leverages Server-Side Rendering (SSR) using React Router v7 (Framework Mode) and the Hono web framework. This provides fast initial page loads, improved SEO, and a robust foundation for server-side logic.
Core Rendering Flow (entry.server.tsx
)
When a request hits the server:
- i18n Initialization: The server determines the user's locale (
i18next.server.ts
) and initializes ani18next
instance with the necessary translations for the requested route. - React Rendering:
renderToPipeableStream
fromreact-dom/server
is used to render the React component tree defined by React Router's<ServerRouter />
. - Streaming Response: The rendering process streams the HTML response back to the client as it's generated.
onShellReady
(for regular users) sends the initial HTML shell quickly.onAllReady
(for bots) waits for all data loading to complete before sending the full HTML.
- Error Handling: Shell errors and general rendering errors are caught and handled appropriately.
Server Implementation (Hono)
We use the Hono framework for building our server-side logic:
server.node.ts
: This is the main Hono application entry point used for standard Node.js environments (including local development).- It uses
@hono/node-server
. - Mounts middleware for logging (
hono/logger
) and static file serving (@hono/node-server/serve-static
) with caching headers. - Mounts the API routes from
@repo/api
via./api.ts
at/api/v1
. - Mounts an S3 image proxy via
./s3image.ts
at/images
. - Integrates the React Router SSR handler (
createRequestHandler
) to handle rendering for application routes.
- It uses
app.server.ts
: This Hono entry seems specifically tailored for Vercel deployments, using@hono/node-server/vercel
. It primarily focuses on mounting the React Router SSR handler.api.ts
/api.vercel.ts
: Defines the Hono router for API endpoints, mounting routes from the shared@repo/api
package.api.vercel.ts
wraps it for Vercel.s3image.ts
/s3image.vercel.ts
: Defines the Hono router for proxying images from S3.s3image.vercel.ts
wraps it for Vercel.
Development Environment (viteDevPlugin.ts
)
During development (pnpm dev
):
- Our custom Vite plugin (
customHonoDevPlugin
) integrates the Hono server (server.node.ts
) into Vite's development server middleware. - It intercepts requests that aren't for static assets or Vite internals.
- It loads the Hono app using
server.ssrLoadModule
and uses@hono/node-server
'sgetRequestListener
to process the request through our Hono application, enabling SSR with HMR.
Build Process & Deployment
The build process is configured in vite.config.ts
and orchestrated by @react-router/dev
using react-router.config.ts
.
react-router.config.ts
: Definesssr: true
and utilizes presets to tailor the build for different environments:preset.node.ts
: Used for standard Node.js deployments.- It uses
buildUtils.ts
(buildEntry
) to bundle theserver.node.ts
entry point using esbuild. - Creates a minimal
package.json
in the build output with only necessary production dependencies.
- It uses
preset.vercel.ts
: Used whenVERCEL=1
is set.- Creates individual Vercel Serverless Functions (
.func
folders) for different parts of the application (e.g.,_node_root
,_node_admin_users
,_extra_api_v1
,_extra_images
). This optimizes cold starts and resource usage. - Uses
reactRouterConfig.serverBundles
to determine which server bundle serves which top-level route path (with special handling for/admin/*
). - Bundles the
app.server.ts
entry for the main application routes and specific entries (api.vercel.ts
,s3image.vercel.ts
) for extra functions (/api/v1
,/images
). - Uses
@vercel/nft
(nodeFileTrace
) to trace dependencies for each function, copying only the necessary files into the.vercel/output/functions
directory. - Generates Vercel configuration files (
.vc-config.json
,config.json
) to define runtimes, routing rules, and other deployment settings.
- Creates individual Vercel Serverless Functions (
buildUtils.ts
: Contains shared esbuild logic used by both presets for bundling server entries efficiently.
Data Loading & Actions
make-loader.ts
: A helper function to create React Router loaders. It handles authentication checks (redirecting if necessary), fetches user data, validates query parameters using Zod, and passes context to the specific loaderhandler
.make-action.ts
: A similar helper for creating React Router actions. It handles authentication/authorization, parses request data (JSON or FormData), validates data using Zod, and executes the actionhandler
.
This setup provides a performant and flexible SSR architecture optimized for both local development with Vite and deployment to Node.js or Vercel platforms.