npm-tanstack--react-router

Description
Modern and scalable routing for React applications with built-in data fetching, caching, and state management capabilities
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/npm-tanstack--react-router@1.132.0

ssr.md docs/

1
# Server-Side Rendering
2
3
Complete SSR support with server and client components, rendering utilities, hydration, stream handling, and asset management for modern web applications.
4
5
## Capabilities
6
7
### Server-Side Rendering Functions
8
9
Functions for rendering router to string or stream on the server.
10
11
```typescript { .api }
12
/**
13
* Render router to string for SSR
14
* @param options - Server rendering options
15
* @returns Promise resolving to rendered HTML string
16
*/
17
function renderRouterToString<TRouter extends AnyRouter>(
18
options: RenderRouterToStringOptions<TRouter>
19
): Promise<string>;
20
21
/**
22
* Render router to stream for SSR with streaming
23
* @param options - Stream rendering options
24
* @returns Promise resolving to readable stream
25
*/
26
function renderRouterToStream<TRouter extends AnyRouter>(
27
options: RenderRouterToStreamOptions<TRouter>
28
): Promise<ReadableStream<Uint8Array>>;
29
30
interface RenderRouterToStringOptions<TRouter extends AnyRouter> {
31
/** Router instance */
32
router: TRouter;
33
/** Request URL */
34
url: string;
35
/** Request headers */
36
headers?: Record<string, string>;
37
/** Render handler function */
38
renderHandler?: RenderHandler;
39
/** Additional context */
40
context?: any;
41
}
42
43
interface RenderRouterToStreamOptions<TRouter extends AnyRouter> {
44
/** Router instance */
45
router: TRouter;
46
/** Request URL */
47
url: string;
48
/** Request headers */
49
headers?: Record<string, string>;
50
/** Stream handler function */
51
streamHandler?: StreamHandler;
52
/** Render handler function */
53
renderHandler?: RenderHandler;
54
/** Additional context */
55
context?: any;
56
}
57
```
58
59
**Usage Examples:**
60
61
```typescript
62
import { renderRouterToString, renderRouterToStream } from "@tanstack/react-router/ssr/server";
63
64
// Express.js server with string rendering
65
app.get("*", async (req, res) => {
66
try {
67
const html = await renderRouterToString({
68
router,
69
url: req.url,
70
headers: req.headers,
71
context: {
72
user: req.user,
73
session: req.session,
74
},
75
});
76
77
res.status(200).send(`
78
<!DOCTYPE html>
79
<html>
80
<head>
81
<meta charset="utf-8">
82
<title>My App</title>
83
</head>
84
<body>
85
<div id="root">${html}</div>
86
<script src="/client.js"></script>
87
</body>
88
</html>
89
`);
90
} catch (error) {
91
res.status(500).send("Server Error");
92
}
93
});
94
95
// Stream rendering for better performance
96
app.get("*", async (req, res) => {
97
try {
98
const stream = await renderRouterToStream({
99
router,
100
url: req.url,
101
headers: req.headers,
102
});
103
104
res.setHeader("Content-Type", "text/html");
105
res.write(`
106
<!DOCTYPE html>
107
<html>
108
<head>
109
<meta charset="utf-8">
110
<title>My App</title>
111
</head>
112
<body>
113
<div id="root">
114
`);
115
116
const reader = stream.getReader();
117
const pump = () => {
118
return reader.read().then(({ done, value }) => {
119
if (done) {
120
res.end(`
121
</div>
122
<script src="/client.js"></script>
123
</body>
124
</html>
125
`);
126
return;
127
}
128
res.write(new TextDecoder().decode(value));
129
return pump();
130
});
131
};
132
133
return pump();
134
} catch (error) {
135
res.status(500).send("Server Error");
136
}
137
});
138
```
139
140
### Server and Client Components
141
142
Specialized components for server-side and client-side routing.
143
144
```typescript { .api }
145
/**
146
* Server-side router component
147
* @param props - Server router props
148
* @returns JSX element for server rendering
149
*/
150
function RouterServer<TRouter extends AnyRouter>(
151
props: RouterServerProps<TRouter>
152
): JSX.Element;
153
154
/**
155
* Client-side router component for hydration
156
* @param props - Client router props
157
* @returns JSX element for client hydration
158
*/
159
function RouterClient<TRouter extends AnyRouter>(
160
props: RouterClientProps<TRouter>
161
): JSX.Element;
162
163
interface RouterServerProps<TRouter extends AnyRouter> {
164
/** Router instance */
165
router: TRouter;
166
/** Server context */
167
context?: any;
168
/** Dehydrated state */
169
dehydratedState?: any;
170
}
171
172
interface RouterClientProps<TRouter extends AnyRouter> {
173
/** Router instance */
174
router: TRouter;
175
/** Hydration state from server */
176
hydrationState?: any;
177
}
178
```
179
180
**Usage Examples:**
181
182
```typescript
183
// Server-side component usage
184
import { RouterServer } from "@tanstack/react-router/ssr/server";
185
186
function ServerApp({ router, context }: { router: Router; context: any }) {
187
return (
188
<RouterServer
189
router={router}
190
context={context}
191
dehydratedState={{
192
user: context.user,
193
timestamp: Date.now(),
194
}}
195
/>
196
);
197
}
198
199
// Client-side hydration
200
import { RouterClient } from "@tanstack/react-router/ssr/client";
201
202
function ClientApp({ router }: { router: Router }) {
203
const hydrationState = window.__ROUTER_HYDRATION_STATE__;
204
205
return (
206
<RouterClient
207
router={router}
208
hydrationState={hydrationState}
209
/>
210
);
211
}
212
```
213
214
### Render and Stream Handlers
215
216
Default handlers for rendering and streaming functionality.
217
218
```typescript { .api }
219
/**
220
* Default render handler for SSR
221
* @param options - Render handler options
222
* @returns Rendered content
223
*/
224
function defaultRenderHandler<TRouter extends AnyRouter>(
225
options: RenderHandlerOptions<TRouter>
226
): React.ReactElement;
227
228
/**
229
* Default stream handler for SSR streaming
230
* @param options - Stream handler options
231
* @returns Stream configuration
232
*/
233
function defaultStreamHandler<TRouter extends AnyRouter>(
234
options: StreamHandlerOptions<TRouter>
235
): StreamHandlerResult;
236
237
interface RenderHandlerOptions<TRouter extends AnyRouter> {
238
router: TRouter;
239
context?: any;
240
dehydratedState?: any;
241
}
242
243
interface StreamHandlerOptions<TRouter extends AnyRouter> {
244
router: TRouter;
245
context?: any;
246
}
247
248
interface StreamHandlerResult {
249
/** Bootstrap script */
250
bootstrapScript?: string;
251
/** Bootstrap modules */
252
bootstrapModules?: string[];
253
/** Progressive enhancement */
254
progressivelyEnhance?: boolean;
255
}
256
257
type RenderHandler = <TRouter extends AnyRouter>(
258
options: RenderHandlerOptions<TRouter>
259
) => React.ReactElement;
260
261
type StreamHandler = <TRouter extends AnyRouter>(
262
options: StreamHandlerOptions<TRouter>
263
) => StreamHandlerResult;
264
```
265
266
**Usage Examples:**
267
268
```typescript
269
import { defaultRenderHandler, defaultStreamHandler } from "@tanstack/react-router/ssr/server";
270
271
// Custom render handler
272
const customRenderHandler: RenderHandler = ({ router, context, dehydratedState }) => {
273
return (
274
<html>
275
<head>
276
<title>{context.title}</title>
277
<meta name="description" content={context.description} />
278
<HeadContent />
279
</head>
280
<body>
281
<RouterServer
282
router={router}
283
context={context}
284
dehydratedState={dehydratedState}
285
/>
286
<Scripts />
287
<script
288
dangerouslySetInnerHTML={{
289
__html: `window.__ROUTER_HYDRATION_STATE__ = ${JSON.stringify(dehydratedState)};`,
290
}}
291
/>
292
</body>
293
</html>
294
);
295
};
296
297
// Custom stream handler
298
const customStreamHandler: StreamHandler = ({ router, context }) => {
299
return {
300
bootstrapScript: "/static/js/client.js",
301
bootstrapModules: ["/static/js/hydration.js"],
302
progressivelyEnhance: true,
303
};
304
};
305
306
// Use custom handlers
307
const html = await renderRouterToString({
308
router,
309
url: req.url,
310
renderHandler: customRenderHandler,
311
context: {
312
title: "My App",
313
description: "A great application",
314
user: req.user,
315
},
316
});
317
```
318
319
### Asset Management Components
320
321
Components for managing HTML assets, scripts, and metadata in SSR.
322
323
```typescript { .api }
324
/**
325
* Renders route-specific and manifest scripts
326
* @returns JSX element with script tags
327
*/
328
function Scripts(): JSX.Element;
329
330
/**
331
* Renders various HTML assets (scripts, styles, meta, etc.)
332
* @param props - Asset configuration
333
* @returns JSX element with asset tags
334
*/
335
function Asset(props: AssetProps): JSX.Element;
336
337
/**
338
* Renders head content from route matches
339
* @returns JSX element with head content
340
*/
341
function HeadContent(): JSX.Element;
342
343
/**
344
* Ensures scripts are only rendered once
345
* @param props - Script attributes
346
* @returns JSX script element
347
*/
348
function ScriptOnce(props: React.ScriptHTMLAttributes<HTMLScriptElement>): JSX.Element;
349
350
interface AssetProps extends RouterManagedTag {
351
/** Content Security Policy nonce */
352
nonce?: string;
353
}
354
355
interface RouterManagedTag {
356
/** HTML tag type */
357
tag: "script" | "style" | "link" | "meta" | "title";
358
/** Tag attributes */
359
attrs?: Record<string, string>;
360
/** Tag content */
361
children?: string;
362
}
363
```
364
365
**Usage Examples:**
366
367
```typescript
368
import { Scripts, Asset, HeadContent, ScriptOnce } from "@tanstack/react-router";
369
370
// Complete HTML document with assets
371
function DocumentShell() {
372
return (
373
<html>
374
<head>
375
<HeadContent />
376
<Asset
377
tag="meta"
378
attrs={{ charset: "utf-8" }}
379
/>
380
<Asset
381
tag="link"
382
attrs={{
383
rel: "stylesheet",
384
href: "/static/css/app.css",
385
}}
386
/>
387
<ScriptOnce
388
src="/static/js/polyfills.js"
389
defer
390
/>
391
</head>
392
<body>
393
<div id="root">
394
<RouterServer router={router} />
395
</div>
396
<Scripts />
397
</body>
398
</html>
399
);
400
}
401
402
// Conditional asset loading
403
function ConditionalAssets({ isDevelopment }: { isDevelopment: boolean }) {
404
return (
405
<>
406
{isDevelopment && (
407
<ScriptOnce src="/static/js/devtools.js" />
408
)}
409
<Asset
410
tag="link"
411
attrs={{
412
rel: "preconnect",
413
href: "https://api.example.com",
414
}}
415
/>
416
</>
417
);
418
}
419
```
420
421
### Router Context for SSR
422
423
Utilities for accessing router context in SSR environments.
424
425
```typescript { .api }
426
/**
427
* Get router context for SSR usage
428
* @returns React context for router
429
*/
430
function getRouterContext(): React.Context<AnyRouter | undefined>;
431
```
432
433
**Usage Examples:**
434
435
```typescript
436
import { getRouterContext } from "@tanstack/react-router";
437
438
// Access router in SSR context
439
function ServerOnlyComponent() {
440
const RouterContext = getRouterContext();
441
442
return (
443
<RouterContext.Consumer>
444
{(router) => {
445
if (!router) return null;
446
447
return (
448
<div>
449
<p>Current URL: {router.state.location.pathname}</p>
450
<p>Matches: {router.state.matches.length}</p>
451
</div>
452
);
453
}}
454
</RouterContext.Consumer>
455
);
456
}
457
458
// Use with useContext
459
function useRouterSSR() {
460
const RouterContext = getRouterContext();
461
return useContext(RouterContext);
462
}
463
```
464
465
### Location Rewriting for SSR
466
467
Utilities for rewriting URLs and handling base paths in SSR.
468
469
```typescript { .api }
470
/**
471
* Create a basepath rewrite function
472
* @param basepath - Base path to rewrite
473
* @returns Location rewrite function
474
*/
475
function rewriteBasepath(basepath: string): LocationRewrite;
476
477
/**
478
* Compose multiple location rewrite functions
479
* @param rewrites - Array of rewrite functions
480
* @returns Composed rewrite function
481
*/
482
function composeRewrites(...rewrites: LocationRewrite[]): LocationRewrite;
483
484
type LocationRewrite = (location: ParsedLocation) => ParsedLocation;
485
type LocationRewriteFunction = LocationRewrite;
486
```
487
488
**Usage Examples:**
489
490
```typescript
491
import { rewriteBasepath, composeRewrites } from "@tanstack/react-router";
492
493
// Basepath rewriting
494
const basepathRewrite = rewriteBasepath("/app");
495
496
// Custom location rewrite
497
const customRewrite: LocationRewrite = (location) => ({
498
...location,
499
pathname: location.pathname.replace(/^\/old/, "/new"),
500
});
501
502
// Compose multiple rewrites
503
const composedRewrite = composeRewrites(
504
basepathRewrite,
505
customRewrite,
506
(location) => ({
507
...location,
508
search: { ...location.search, timestamp: Date.now() },
509
})
510
);
511
512
// Use in router configuration
513
const router = createRouter({
514
routeTree,
515
basepath: "/app",
516
// Apply location rewrites
517
rewrite: composedRewrite,
518
});
519
```
520
521
### Serialization for SSR
522
523
Serialization utilities for transferring data between server and client.
524
525
```typescript { .api }
526
/**
527
* Create a serialization adapter
528
* @param adapter - Serialization configuration
529
* @returns Serialization adapter
530
*/
531
function createSerializationAdapter<T>(
532
adapter: SerializationAdapter<T>
533
): SerializationAdapter<T>;
534
535
interface SerializationAdapter<T = any> {
536
/** Serialize value for transport */
537
serialize: (value: T) => string;
538
/** Deserialize value from transport */
539
deserialize: (value: string) => T;
540
}
541
542
type AnySerializationAdapter = SerializationAdapter<any>;
543
```
544
545
**Usage Examples:**
546
547
```typescript
548
import { createSerializationAdapter } from "@tanstack/react-router";
549
550
// Custom date serialization
551
const dateAdapter = createSerializationAdapter({
552
serialize: (date: Date) => date.toISOString(),
553
deserialize: (dateString: string) => new Date(dateString),
554
});
555
556
// Complex object serialization
557
const complexAdapter = createSerializationAdapter({
558
serialize: (obj) => {
559
return JSON.stringify(obj, (key, value) => {
560
if (value instanceof Date) return { __type: "Date", value: value.toISOString() };
561
if (value instanceof Map) return { __type: "Map", value: Array.from(value.entries()) };
562
return value;
563
});
564
},
565
deserialize: (str) => {
566
return JSON.parse(str, (key, value) => {
567
if (value?.__type === "Date") return new Date(value.value);
568
if (value?.__type === "Map") return new Map(value.value);
569
return value;
570
});
571
},
572
});
573
574
// Use in router
575
const router = createRouter({
576
routeTree,
577
serializationAdapter: complexAdapter,
578
});
579
```
580
581
## Types
582
583
### SSR Configuration Types
584
585
```typescript { .api }
586
interface SSROptions {
587
/** Enable server-side rendering */
588
ssr?: boolean;
589
/** Hydration strategy */
590
hydrationStrategy?: "progressive" | "immediate" | "lazy";
591
/** Stream rendering options */
592
streaming?: boolean;
593
/** Asset preloading strategy */
594
assetPreloading?: "aggressive" | "conservative" | "none";
595
}
596
597
interface HydrationState {
598
/** Router state for hydration */
599
routerState: RouterState;
600
/** Dehydrated loader data */
601
loaderData: Record<string, any>;
602
/** Timestamp of server render */
603
timestamp: number;
604
}
605
```
606
607
### Stream Types
608
609
```typescript { .api }
610
interface StreamOptions {
611
/** Bootstrap scripts */
612
bootstrapScripts?: string[];
613
/** Bootstrap modules */
614
bootstrapModules?: string[];
615
/** Progressive enhancement */
616
progressivelyEnhance?: boolean;
617
/** Identifier for the stream */
618
identifierPrefix?: string;
619
}
620
```