or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdserver-side-rendering.md

server-side-rendering.mddocs/

0

# Server-Side Rendering

1

2

Server-side rendering with React Helmet allows you to extract head data after rendering your React app to include in the final HTML document. This is essential for SEO, social media sharing, and prerendering scenarios.

3

4

## Capabilities

5

6

### Static Head Data Extraction

7

8

Extract head data after server-side rendering to include in HTML documents.

9

10

```javascript { .api }

11

/**

12

* Extract head data after server-side rendering

13

* Must be called on server after ReactDOMServer.renderToString() or renderToStaticMarkup()

14

* @returns HelmetData object containing all head elements and attributes

15

*/

16

static renderStatic(): HelmetData;

17

18

/**

19

* Legacy alias for renderStatic()

20

* @deprecated Use renderStatic() instead

21

* @returns HelmetData object containing all head elements and attributes

22

*/

23

static rewind(): HelmetData;

24

25

interface HelmetData {

26

/** Document title element */

27

title: HelmetElement;

28

/** Base element */

29

base: HelmetElement;

30

/** Meta elements */

31

meta: HelmetElement;

32

/** Link elements */

33

link: HelmetElement;

34

/** Script elements */

35

script: HelmetElement;

36

/** Style elements */

37

style: HelmetElement;

38

/** Noscript elements */

39

noscript: HelmetElement;

40

/** HTML element attributes */

41

htmlAttributes: HelmetElement;

42

/** Body element attributes */

43

bodyAttributes: HelmetElement;

44

}

45

46

interface HelmetElement {

47

/**

48

* Convert to React components for JSX rendering

49

* @returns Array of React elements

50

*/

51

toComponent(): React.ReactElement[];

52

53

/**

54

* Convert to HTML string for server-side rendering

55

* @returns HTML string representation

56

*/

57

toString(): string;

58

}

59

```

60

61

**Usage Example:**

62

63

```javascript

64

import React from "react";

65

import ReactDOMServer from "react-dom/server";

66

import { Helmet } from "react-helmet";

67

import App from "./App";

68

69

// Render your app

70

const appString = ReactDOMServer.renderToString(<App />);

71

72

// Extract head data

73

const helmet = Helmet.renderStatic();

74

75

// Generate complete HTML

76

const html = `

77

<!DOCTYPE html>

78

<html ${helmet.htmlAttributes.toString()}>

79

<head>

80

${helmet.title.toString()}

81

${helmet.meta.toString()}

82

${helmet.link.toString()}

83

${helmet.script.toString()}

84

${helmet.style.toString()}

85

</head>

86

<body ${helmet.bodyAttributes.toString()}>

87

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

88

${helmet.noscript.toString()}

89

</body>

90

</html>

91

`;

92

```

93

94

### JSX Server Rendering

95

96

When using JSX for server-side HTML generation, use the `toComponent()` method:

97

98

```javascript { .api }

99

import React from "react";

100

import ReactDOMServer from "react-dom/server";

101

import { Helmet } from "react-helmet";

102

103

function HTMLDocument() {

104

// App must be rendered first to populate Helmet state

105

const appString = ReactDOMServer.renderToString(<App />);

106

const helmet = Helmet.renderStatic();

107

108

const htmlAttrs = helmet.htmlAttributes.toComponent();

109

const bodyAttrs = helmet.bodyAttributes.toComponent();

110

111

return (

112

<html {...htmlAttrs}>

113

<head>

114

{helmet.title.toComponent()}

115

{helmet.meta.toComponent()}

116

{helmet.link.toComponent()}

117

{helmet.script.toComponent()}

118

{helmet.style.toComponent()}

119

</head>

120

<body {...bodyAttrs}>

121

<div id="root" dangerouslySetInnerHTML={{ __html: appString }} />

122

{helmet.noscript.toComponent()}

123

</body>

124

</html>

125

);

126

}

127

```

128

129

### Testing Utilities

130

131

Get current Helmet state for testing without affecting the instance stack.

132

133

```javascript { .api }

134

/**

135

* Testing utility to get current state without resetting the mounted instance stack

136

* @returns Current HelmetData state

137

* @note Only use for testing purposes

138

*/

139

static peek(): HelmetData;

140

```

141

142

**Usage in Tests:**

143

144

```javascript

145

import { Helmet } from "react-helmet";

146

import { render } from "@testing-library/react";

147

148

test("helmet sets correct title", () => {

149

render(

150

<Helmet>

151

<title>Test Title</title>

152

</Helmet>

153

);

154

155

const helmetData = Helmet.peek();

156

expect(helmetData.title.toString()).toContain("Test Title");

157

});

158

```

159

160

### Environment Control

161

162

Control DOM usage detection for server environments.

163

164

```javascript { .api }

165

/**

166

* Controls DOM usage detection

167

* Set to false in server environments where DOM is not available

168

* @param value - Boolean indicating if DOM can be used

169

*/

170

static set canUseDOM(value: boolean);

171

```

172

173

**Usage:**

174

175

```javascript

176

import { Helmet } from "react-helmet";

177

178

// In server environment

179

Helmet.canUseDOM = false;

180

181

// In browser environment (default)

182

Helmet.canUseDOM = true;

183

```

184

185

## Complete Server Example

186

187

Here's a complete Express.js server example:

188

189

```javascript

190

import express from "express";

191

import React from "react";

192

import ReactDOMServer from "react-dom/server";

193

import { Helmet } from "react-helmet";

194

import App from "./App";

195

196

const app = express();

197

198

// Configure Helmet for server environment

199

Helmet.canUseDOM = false;

200

201

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

202

// Render the app

203

const appString = ReactDOMServer.renderToString(

204

<App url={req.url} />

205

);

206

207

// Extract head data

208

const helmet = Helmet.renderStatic();

209

210

// Send complete HTML

211

res.send(`

212

<!DOCTYPE html>

213

<html ${helmet.htmlAttributes.toString()}>

214

<head>

215

<meta charset="utf-8">

216

<meta name="viewport" content="width=device-width, initial-scale=1">

217

${helmet.title.toString()}

218

${helmet.meta.toString()}

219

${helmet.link.toString()}

220

${helmet.script.toString()}

221

${helmet.style.toString()}

222

</head>

223

<body ${helmet.bodyAttributes.toString()}>

224

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

225

${helmet.noscript.toString()}

226

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

227

</body>

228

</html>

229

`);

230

});

231

232

app.listen(3000);

233

```

234

235

## Important Notes

236

237

### Memory Management

238

239

**Critical**: Always call `renderStatic()` or `rewind()` on the server to prevent memory leaks. React Helmet tracks mounted instances, and failing to extract the data will cause memory accumulation.

240

241

```javascript

242

// ❌ Memory leak - renderStatic() never called

243

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

244

const html = ReactDOMServer.renderToString(<App />);

245

res.send(`<html><body>${html}</body></html>`);

246

});

247

248

// ✅ Correct - renderStatic() extracts and clears state

249

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

250

const html = ReactDOMServer.renderToString(<App />);

251

const helmet = Helmet.renderStatic();

252

res.send(`<html><body>${html}</body></html>`);

253

});

254

```

255

256

### Webpack Externals

257

258

When using prebuilt app compilations, ensure the same react-helmet instance is used:

259

260

```javascript

261

// webpack.config.js

262

module.exports = {

263

externals: ["react-helmet"],

264

// ... other config

265

};

266

```

267

268

### Encoding Control

269

270

Control HTML entity encoding for server-side rendering:

271

272

```javascript

273

<Helmet encodeSpecialCharacters={false}>

274

<title>Title with <special> characters</title>

275

</Helmet>

276

277

// With encodeSpecialCharacters={true} (default):

278

// <title>Title with &lt;special&gt; characters</title>

279

280

// With encodeSpecialCharacters={false}:

281

// <title>Title with <special> characters</title>

282

```