or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-loading.mderror-handling.mdindex.mdnavigation-links.mdpath-search-utils.mdreact-components.mdreact-hooks.mdroute-definition.mdrouter-creation.mdssr.md

ssr.mddocs/

0

# Server-Side Rendering

1

2

Complete SSR support with server and client components, rendering utilities, hydration, stream handling, and asset management for modern web applications.

3

4

## Capabilities

5

6

### Server-Side Rendering Functions

7

8

Functions for rendering router to string or stream on the server.

9

10

```typescript { .api }

11

/**

12

* Render router to string for SSR

13

* @param options - Server rendering options

14

* @returns Promise resolving to rendered HTML string

15

*/

16

function renderRouterToString<TRouter extends AnyRouter>(

17

options: RenderRouterToStringOptions<TRouter>

18

): Promise<string>;

19

20

/**

21

* Render router to stream for SSR with streaming

22

* @param options - Stream rendering options

23

* @returns Promise resolving to readable stream

24

*/

25

function renderRouterToStream<TRouter extends AnyRouter>(

26

options: RenderRouterToStreamOptions<TRouter>

27

): Promise<ReadableStream<Uint8Array>>;

28

29

interface RenderRouterToStringOptions<TRouter extends AnyRouter> {

30

/** Router instance */

31

router: TRouter;

32

/** Request URL */

33

url: string;

34

/** Request headers */

35

headers?: Record<string, string>;

36

/** Render handler function */

37

renderHandler?: RenderHandler;

38

/** Additional context */

39

context?: any;

40

}

41

42

interface RenderRouterToStreamOptions<TRouter extends AnyRouter> {

43

/** Router instance */

44

router: TRouter;

45

/** Request URL */

46

url: string;

47

/** Request headers */

48

headers?: Record<string, string>;

49

/** Stream handler function */

50

streamHandler?: StreamHandler;

51

/** Render handler function */

52

renderHandler?: RenderHandler;

53

/** Additional context */

54

context?: any;

55

}

56

```

57

58

**Usage Examples:**

59

60

```typescript

61

import { renderRouterToString, renderRouterToStream } from "@tanstack/react-router/ssr/server";

62

63

// Express.js server with string rendering

64

app.get("*", async (req, res) => {

65

try {

66

const html = await renderRouterToString({

67

router,

68

url: req.url,

69

headers: req.headers,

70

context: {

71

user: req.user,

72

session: req.session,

73

},

74

});

75

76

res.status(200).send(`

77

<!DOCTYPE html>

78

<html>

79

<head>

80

<meta charset="utf-8">

81

<title>My App</title>

82

</head>

83

<body>

84

<div id="root">${html}</div>

85

<script src="/client.js"></script>

86

</body>

87

</html>

88

`);

89

} catch (error) {

90

res.status(500).send("Server Error");

91

}

92

});

93

94

// Stream rendering for better performance

95

app.get("*", async (req, res) => {

96

try {

97

const stream = await renderRouterToStream({

98

router,

99

url: req.url,

100

headers: req.headers,

101

});

102

103

res.setHeader("Content-Type", "text/html");

104

res.write(`

105

<!DOCTYPE html>

106

<html>

107

<head>

108

<meta charset="utf-8">

109

<title>My App</title>

110

</head>

111

<body>

112

<div id="root">

113

`);

114

115

const reader = stream.getReader();

116

const pump = () => {

117

return reader.read().then(({ done, value }) => {

118

if (done) {

119

res.end(`

120

</div>

121

<script src="/client.js"></script>

122

</body>

123

</html>

124

`);

125

return;

126

}

127

res.write(new TextDecoder().decode(value));

128

return pump();

129

});

130

};

131

132

return pump();

133

} catch (error) {

134

res.status(500).send("Server Error");

135

}

136

});

137

```

138

139

### Server and Client Components

140

141

Specialized components for server-side and client-side routing.

142

143

```typescript { .api }

144

/**

145

* Server-side router component

146

* @param props - Server router props

147

* @returns JSX element for server rendering

148

*/

149

function RouterServer<TRouter extends AnyRouter>(

150

props: RouterServerProps<TRouter>

151

): JSX.Element;

152

153

/**

154

* Client-side router component for hydration

155

* @param props - Client router props

156

* @returns JSX element for client hydration

157

*/

158

function RouterClient<TRouter extends AnyRouter>(

159

props: RouterClientProps<TRouter>

160

): JSX.Element;

161

162

interface RouterServerProps<TRouter extends AnyRouter> {

163

/** Router instance */

164

router: TRouter;

165

/** Server context */

166

context?: any;

167

/** Dehydrated state */

168

dehydratedState?: any;

169

}

170

171

interface RouterClientProps<TRouter extends AnyRouter> {

172

/** Router instance */

173

router: TRouter;

174

/** Hydration state from server */

175

hydrationState?: any;

176

}

177

```

178

179

**Usage Examples:**

180

181

```typescript

182

// Server-side component usage

183

import { RouterServer } from "@tanstack/react-router/ssr/server";

184

185

function ServerApp({ router, context }: { router: Router; context: any }) {

186

return (

187

<RouterServer

188

router={router}

189

context={context}

190

dehydratedState={{

191

user: context.user,

192

timestamp: Date.now(),

193

}}

194

/>

195

);

196

}

197

198

// Client-side hydration

199

import { RouterClient } from "@tanstack/react-router/ssr/client";

200

201

function ClientApp({ router }: { router: Router }) {

202

const hydrationState = window.__ROUTER_HYDRATION_STATE__;

203

204

return (

205

<RouterClient

206

router={router}

207

hydrationState={hydrationState}

208

/>

209

);

210

}

211

```

212

213

### Render and Stream Handlers

214

215

Default handlers for rendering and streaming functionality.

216

217

```typescript { .api }

218

/**

219

* Default render handler for SSR

220

* @param options - Render handler options

221

* @returns Rendered content

222

*/

223

function defaultRenderHandler<TRouter extends AnyRouter>(

224

options: RenderHandlerOptions<TRouter>

225

): React.ReactElement;

226

227

/**

228

* Default stream handler for SSR streaming

229

* @param options - Stream handler options

230

* @returns Stream configuration

231

*/

232

function defaultStreamHandler<TRouter extends AnyRouter>(

233

options: StreamHandlerOptions<TRouter>

234

): StreamHandlerResult;

235

236

interface RenderHandlerOptions<TRouter extends AnyRouter> {

237

router: TRouter;

238

context?: any;

239

dehydratedState?: any;

240

}

241

242

interface StreamHandlerOptions<TRouter extends AnyRouter> {

243

router: TRouter;

244

context?: any;

245

}

246

247

interface StreamHandlerResult {

248

/** Bootstrap script */

249

bootstrapScript?: string;

250

/** Bootstrap modules */

251

bootstrapModules?: string[];

252

/** Progressive enhancement */

253

progressivelyEnhance?: boolean;

254

}

255

256

type RenderHandler = <TRouter extends AnyRouter>(

257

options: RenderHandlerOptions<TRouter>

258

) => React.ReactElement;

259

260

type StreamHandler = <TRouter extends AnyRouter>(

261

options: StreamHandlerOptions<TRouter>

262

) => StreamHandlerResult;

263

```

264

265

**Usage Examples:**

266

267

```typescript

268

import { defaultRenderHandler, defaultStreamHandler } from "@tanstack/react-router/ssr/server";

269

270

// Custom render handler

271

const customRenderHandler: RenderHandler = ({ router, context, dehydratedState }) => {

272

return (

273

<html>

274

<head>

275

<title>{context.title}</title>

276

<meta name="description" content={context.description} />

277

<HeadContent />

278

</head>

279

<body>

280

<RouterServer

281

router={router}

282

context={context}

283

dehydratedState={dehydratedState}

284

/>

285

<Scripts />

286

<script

287

dangerouslySetInnerHTML={{

288

__html: `window.__ROUTER_HYDRATION_STATE__ = ${JSON.stringify(dehydratedState)};`,

289

}}

290

/>

291

</body>

292

</html>

293

);

294

};

295

296

// Custom stream handler

297

const customStreamHandler: StreamHandler = ({ router, context }) => {

298

return {

299

bootstrapScript: "/static/js/client.js",

300

bootstrapModules: ["/static/js/hydration.js"],

301

progressivelyEnhance: true,

302

};

303

};

304

305

// Use custom handlers

306

const html = await renderRouterToString({

307

router,

308

url: req.url,

309

renderHandler: customRenderHandler,

310

context: {

311

title: "My App",

312

description: "A great application",

313

user: req.user,

314

},

315

});

316

```

317

318

### Asset Management Components

319

320

Components for managing HTML assets, scripts, and metadata in SSR.

321

322

```typescript { .api }

323

/**

324

* Renders route-specific and manifest scripts

325

* @returns JSX element with script tags

326

*/

327

function Scripts(): JSX.Element;

328

329

/**

330

* Renders various HTML assets (scripts, styles, meta, etc.)

331

* @param props - Asset configuration

332

* @returns JSX element with asset tags

333

*/

334

function Asset(props: AssetProps): JSX.Element;

335

336

/**

337

* Renders head content from route matches

338

* @returns JSX element with head content

339

*/

340

function HeadContent(): JSX.Element;

341

342

/**

343

* Ensures scripts are only rendered once

344

* @param props - Script attributes

345

* @returns JSX script element

346

*/

347

function ScriptOnce(props: React.ScriptHTMLAttributes<HTMLScriptElement>): JSX.Element;

348

349

interface AssetProps extends RouterManagedTag {

350

/** Content Security Policy nonce */

351

nonce?: string;

352

}

353

354

interface RouterManagedTag {

355

/** HTML tag type */

356

tag: "script" | "style" | "link" | "meta" | "title";

357

/** Tag attributes */

358

attrs?: Record<string, string>;

359

/** Tag content */

360

children?: string;

361

}

362

```

363

364

**Usage Examples:**

365

366

```typescript

367

import { Scripts, Asset, HeadContent, ScriptOnce } from "@tanstack/react-router";

368

369

// Complete HTML document with assets

370

function DocumentShell() {

371

return (

372

<html>

373

<head>

374

<HeadContent />

375

<Asset

376

tag="meta"

377

attrs={{ charset: "utf-8" }}

378

/>

379

<Asset

380

tag="link"

381

attrs={{

382

rel: "stylesheet",

383

href: "/static/css/app.css",

384

}}

385

/>

386

<ScriptOnce

387

src="/static/js/polyfills.js"

388

defer

389

/>

390

</head>

391

<body>

392

<div id="root">

393

<RouterServer router={router} />

394

</div>

395

<Scripts />

396

</body>

397

</html>

398

);

399

}

400

401

// Conditional asset loading

402

function ConditionalAssets({ isDevelopment }: { isDevelopment: boolean }) {

403

return (

404

<>

405

{isDevelopment && (

406

<ScriptOnce src="/static/js/devtools.js" />

407

)}

408

<Asset

409

tag="link"

410

attrs={{

411

rel: "preconnect",

412

href: "https://api.example.com",

413

}}

414

/>

415

</>

416

);

417

}

418

```

419

420

### Router Context for SSR

421

422

Utilities for accessing router context in SSR environments.

423

424

```typescript { .api }

425

/**

426

* Get router context for SSR usage

427

* @returns React context for router

428

*/

429

function getRouterContext(): React.Context<AnyRouter | undefined>;

430

```

431

432

**Usage Examples:**

433

434

```typescript

435

import { getRouterContext } from "@tanstack/react-router";

436

437

// Access router in SSR context

438

function ServerOnlyComponent() {

439

const RouterContext = getRouterContext();

440

441

return (

442

<RouterContext.Consumer>

443

{(router) => {

444

if (!router) return null;

445

446

return (

447

<div>

448

<p>Current URL: {router.state.location.pathname}</p>

449

<p>Matches: {router.state.matches.length}</p>

450

</div>

451

);

452

}}

453

</RouterContext.Consumer>

454

);

455

}

456

457

// Use with useContext

458

function useRouterSSR() {

459

const RouterContext = getRouterContext();

460

return useContext(RouterContext);

461

}

462

```

463

464

### Location Rewriting for SSR

465

466

Utilities for rewriting URLs and handling base paths in SSR.

467

468

```typescript { .api }

469

/**

470

* Create a basepath rewrite function

471

* @param basepath - Base path to rewrite

472

* @returns Location rewrite function

473

*/

474

function rewriteBasepath(basepath: string): LocationRewrite;

475

476

/**

477

* Compose multiple location rewrite functions

478

* @param rewrites - Array of rewrite functions

479

* @returns Composed rewrite function

480

*/

481

function composeRewrites(...rewrites: LocationRewrite[]): LocationRewrite;

482

483

type LocationRewrite = (location: ParsedLocation) => ParsedLocation;

484

type LocationRewriteFunction = LocationRewrite;

485

```

486

487

**Usage Examples:**

488

489

```typescript

490

import { rewriteBasepath, composeRewrites } from "@tanstack/react-router";

491

492

// Basepath rewriting

493

const basepathRewrite = rewriteBasepath("/app");

494

495

// Custom location rewrite

496

const customRewrite: LocationRewrite = (location) => ({

497

...location,

498

pathname: location.pathname.replace(/^\/old/, "/new"),

499

});

500

501

// Compose multiple rewrites

502

const composedRewrite = composeRewrites(

503

basepathRewrite,

504

customRewrite,

505

(location) => ({

506

...location,

507

search: { ...location.search, timestamp: Date.now() },

508

})

509

);

510

511

// Use in router configuration

512

const router = createRouter({

513

routeTree,

514

basepath: "/app",

515

// Apply location rewrites

516

rewrite: composedRewrite,

517

});

518

```

519

520

### Serialization for SSR

521

522

Serialization utilities for transferring data between server and client.

523

524

```typescript { .api }

525

/**

526

* Create a serialization adapter

527

* @param adapter - Serialization configuration

528

* @returns Serialization adapter

529

*/

530

function createSerializationAdapter<T>(

531

adapter: SerializationAdapter<T>

532

): SerializationAdapter<T>;

533

534

interface SerializationAdapter<T = any> {

535

/** Serialize value for transport */

536

serialize: (value: T) => string;

537

/** Deserialize value from transport */

538

deserialize: (value: string) => T;

539

}

540

541

type AnySerializationAdapter = SerializationAdapter<any>;

542

```

543

544

**Usage Examples:**

545

546

```typescript

547

import { createSerializationAdapter } from "@tanstack/react-router";

548

549

// Custom date serialization

550

const dateAdapter = createSerializationAdapter({

551

serialize: (date: Date) => date.toISOString(),

552

deserialize: (dateString: string) => new Date(dateString),

553

});

554

555

// Complex object serialization

556

const complexAdapter = createSerializationAdapter({

557

serialize: (obj) => {

558

return JSON.stringify(obj, (key, value) => {

559

if (value instanceof Date) return { __type: "Date", value: value.toISOString() };

560

if (value instanceof Map) return { __type: "Map", value: Array.from(value.entries()) };

561

return value;

562

});

563

},

564

deserialize: (str) => {

565

return JSON.parse(str, (key, value) => {

566

if (value?.__type === "Date") return new Date(value.value);

567

if (value?.__type === "Map") return new Map(value.value);

568

return value;

569

});

570

},

571

});

572

573

// Use in router

574

const router = createRouter({

575

routeTree,

576

serializationAdapter: complexAdapter,

577

});

578

```

579

580

## Types

581

582

### SSR Configuration Types

583

584

```typescript { .api }

585

interface SSROptions {

586

/** Enable server-side rendering */

587

ssr?: boolean;

588

/** Hydration strategy */

589

hydrationStrategy?: "progressive" | "immediate" | "lazy";

590

/** Stream rendering options */

591

streaming?: boolean;

592

/** Asset preloading strategy */

593

assetPreloading?: "aggressive" | "conservative" | "none";

594

}

595

596

interface HydrationState {

597

/** Router state for hydration */

598

routerState: RouterState;

599

/** Dehydrated loader data */

600

loaderData: Record<string, any>;

601

/** Timestamp of server render */

602

timestamp: number;

603

}

604

```

605

606

### Stream Types

607

608

```typescript { .api }

609

interface StreamOptions {

610

/** Bootstrap scripts */

611

bootstrapScripts?: string[];

612

/** Bootstrap modules */

613

bootstrapModules?: string[];

614

/** Progressive enhancement */

615

progressivelyEnhance?: boolean;

616

/** Identifier for the stream */

617

identifierPrefix?: string;

618

}

619

```