| 1 | ---
|
| 2 | title: Rendering Strategies
|
| 3 | order: 4
|
| 4 | ---
|
| 5 |
|
| 6 | # Rendering Strategies
|
| 7 |
|
| 8 | [MODES: framework]
|
| 9 |
|
| 10 | ## Introduction
|
| 11 |
|
| 12 | There are three rendering strategies in React Router:
|
| 13 |
|
| 14 | - Client Side Rendering
|
| 15 | - Server Side Rendering
|
| 16 | - Static Pre-rendering
|
| 17 |
|
| 18 | ## Client Side Rendering
|
| 19 |
|
| 20 | Routes are always client side rendered as the user navigates around the app. If you're looking to build a Single Page App, disable server rendering:
|
| 21 |
|
| 22 | ```ts filename=react-router.config.ts
|
| 23 | import type { Config } from "@react-router/dev/config";
|
| 24 |
|
| 25 | export default {
|
| 26 | ssr: false,
|
| 27 | } satisfies Config;
|
| 28 | ```
|
| 29 |
|
| 30 | ## Server Side Rendering
|
| 31 |
|
| 32 | ```ts filename=react-router.config.ts
|
| 33 | import type { Config } from "@react-router/dev/config";
|
| 34 |
|
| 35 | export default {
|
| 36 | ssr: true,
|
| 37 | } satisfies Config;
|
| 38 | ```
|
| 39 |
|
| 40 | Server side rendering requires a deployment that supports it. Though it's a global setting, individual routes can still be statically pre-rendered. Routes can also use client data loading with `clientLoader` to avoid server rendering/fetching for their portion of the UI.
|
| 41 |
|
| 42 | ## Static Pre-rendering
|
| 43 |
|
| 44 | ```ts filename=react-router.config.ts
|
| 45 | import type { Config } from "@react-router/dev/config";
|
| 46 |
|
| 47 | export default {
|
| 48 | // return a list of URLs to prerender at build time
|
| 49 | async prerender() {
|
| 50 | return ["/", "/about", "/contact"];
|
| 51 | },
|
| 52 | } satisfies Config;
|
| 53 | ```
|
| 54 |
|
| 55 | Pre-rendering is a build-time operation that generates static HTML and client navigation data payloads for a list of URLs. This is useful for SEO and performance, especially for deployments without server rendering. When pre-rendering, route module loaders are used to fetch data at build time.
|
| 56 |
|
| 57 | ## API-only Mode (unstable)
|
| 58 |
|
| 59 | <docs-warning>API-only Mode is experimental and may change in minor or patch releases. It is not supported in RSC Framework Mode.</docs-warning>
|
| 60 |
|
| 61 | Set `ssr: "unstable_api-only"` to keep a runtime server for loaders, actions, and route discovery while disabling production server-side document rendering:
|
| 62 |
|
| 63 | ```ts filename=react-router.config.ts
|
| 64 | import type { Config } from "@react-router/dev/config";
|
| 65 |
|
| 66 | export default {
|
| 67 | ssr: "unstable_api-only",
|
| 68 | } satisfies Config;
|
| 69 | ```
|
| 70 |
|
| 71 | Without prerendering, the build generates a root-only `index.html` shell using the root `HydrateFallback`, like [SPA Mode](../../how-to/spa). The browser fetches server loader data as it initializes the page. Routes can use server `loader` and `action` exports without requiring `clientLoader` or `clientAction` wrappers. Lazy route discovery remains enabled by default.
|
| 72 |
|
| 73 | You can also [combine API-only Mode with prerendering](../../how-to/pre-rendering#pre-rendering-with-api-only-mode-unstable) to serve complete HTML for selected paths and a SPA fallback for other paths.
|
| 74 |
|
| 75 | Deploy both `build/client` and the runtime server build. Serve assets, prerendered documents, and the SPA fallback from the client build; send `.data` and route discovery requests (`/__manifest` by default) to the React Router request handler. The production API-only handler returns `404` for document requests. `react-router-serve` handles this routing automatically.
|
| 76 |
|
| 77 | ### Using a separate API origin
|
| 78 |
|
| 79 | By default, data and route discovery requests use the same origin as the client application. Set `unstable_apiServerOrigin` to use a separate API server:
|
| 80 |
|
| 81 | ```ts filename=react-router.config.ts
|
| 82 | import type { Config } from "@react-router/dev/config";
|
| 83 |
|
| 84 | export default {
|
| 85 | ssr: "unstable_api-only",
|
| 86 | unstable_apiServerOrigin: "https://api.example.com",
|
| 87 | } satisfies Config;
|
| 88 | ```
|
| 89 |
|
| 90 | This option applies to loader, action, and route discovery requests only in API-only Mode. Use an origin without a path, query, or hash. Configure CORS on the API server and allow the client origin via [`allowedActionOrigins`](../../api/framework-conventions/react-router.config.ts#allowedactionorigins) for cross-origin action submissions. Requests use the browser's default `same-origin` credential policy; this option does not enable sending cookies to a different origin.
|
| 91 |
|
| 92 | To customize JavaScript-issued requests with authentication headers or cross-origin credentials, see [Custom Fetch](../../how-to/custom-fetch). Native data prefetches bypass custom fetch.
|
| 93 |
|
| 94 | ---
|
| 95 |
|
| 96 | Next: [Data Loading](./data-loading)
|