CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-helmet

A document head manager for React applications enabling dynamic control of HTML head elements

Pending
Overview
Eval results
Files

server-side-rendering.mddocs/

Server-Side Rendering

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.

Capabilities

Static Head Data Extraction

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

/**
 * Extract head data after server-side rendering
 * Must be called on server after ReactDOMServer.renderToString() or renderToStaticMarkup()
 * @returns HelmetData object containing all head elements and attributes
 */
static renderStatic(): HelmetData;

/**
 * Legacy alias for renderStatic()
 * @deprecated Use renderStatic() instead
 * @returns HelmetData object containing all head elements and attributes
 */
static rewind(): HelmetData;

interface HelmetData {
  /** Document title element */
  title: HelmetElement;
  /** Base element */
  base: HelmetElement;
  /** Meta elements */
  meta: HelmetElement;
  /** Link elements */
  link: HelmetElement;
  /** Script elements */
  script: HelmetElement;
  /** Style elements */
  style: HelmetElement;
  /** Noscript elements */
  noscript: HelmetElement;
  /** HTML element attributes */
  htmlAttributes: HelmetElement;
  /** Body element attributes */
  bodyAttributes: HelmetElement;
}

interface HelmetElement {
  /**
   * Convert to React components for JSX rendering
   * @returns Array of React elements
   */
  toComponent(): React.ReactElement[];
  
  /**
   * Convert to HTML string for server-side rendering
   * @returns HTML string representation
   */
  toString(): string;
}

Usage Example:

import React from "react";
import ReactDOMServer from "react-dom/server";
import { Helmet } from "react-helmet";
import App from "./App";

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

// Extract head data
const helmet = Helmet.renderStatic();

// Generate complete HTML
const html = `
<!DOCTYPE html>
<html ${helmet.htmlAttributes.toString()}>
  <head>
    ${helmet.title.toString()}
    ${helmet.meta.toString()}
    ${helmet.link.toString()}
    ${helmet.script.toString()}
    ${helmet.style.toString()}
  </head>
  <body ${helmet.bodyAttributes.toString()}>
    <div id="root">${appString}</div>
    ${helmet.noscript.toString()}
  </body>
</html>
`;

JSX Server Rendering

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

import React from "react";
import ReactDOMServer from "react-dom/server";
import { Helmet } from "react-helmet";

function HTMLDocument() {
  // App must be rendered first to populate Helmet state
  const appString = ReactDOMServer.renderToString(<App />);
  const helmet = Helmet.renderStatic();
  
  const htmlAttrs = helmet.htmlAttributes.toComponent();
  const bodyAttrs = helmet.bodyAttributes.toComponent();

  return (
    <html {...htmlAttrs}>
      <head>
        {helmet.title.toComponent()}
        {helmet.meta.toComponent()}
        {helmet.link.toComponent()}
        {helmet.script.toComponent()}
        {helmet.style.toComponent()}
      </head>
      <body {...bodyAttrs}>
        <div id="root" dangerouslySetInnerHTML={{ __html: appString }} />
        {helmet.noscript.toComponent()}
      </body>
    </html>
  );
}

Testing Utilities

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

/**
 * Testing utility to get current state without resetting the mounted instance stack
 * @returns Current HelmetData state
 * @note Only use for testing purposes
 */
static peek(): HelmetData;

Usage in Tests:

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

test("helmet sets correct title", () => {
  render(
    <Helmet>
      <title>Test Title</title>
    </Helmet>
  );

  const helmetData = Helmet.peek();
  expect(helmetData.title.toString()).toContain("Test Title");
});

Environment Control

Control DOM usage detection for server environments.

/**
 * Controls DOM usage detection
 * Set to false in server environments where DOM is not available
 * @param value - Boolean indicating if DOM can be used
 */
static set canUseDOM(value: boolean);

Usage:

import { Helmet } from "react-helmet";

// In server environment
Helmet.canUseDOM = false;

// In browser environment (default)
Helmet.canUseDOM = true;

Complete Server Example

Here's a complete Express.js server example:

import express from "express";
import React from "react";
import ReactDOMServer from "react-dom/server";
import { Helmet } from "react-helmet";
import App from "./App";

const app = express();

// Configure Helmet for server environment
Helmet.canUseDOM = false;

app.get("*", (req, res) => {
  // Render the app
  const appString = ReactDOMServer.renderToString(
    <App url={req.url} />
  );

  // Extract head data
  const helmet = Helmet.renderStatic();

  // Send complete HTML
  res.send(`
    <!DOCTYPE html>
    <html ${helmet.htmlAttributes.toString()}>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        ${helmet.title.toString()}
        ${helmet.meta.toString()}
        ${helmet.link.toString()}
        ${helmet.script.toString()}
        ${helmet.style.toString()}
      </head>
      <body ${helmet.bodyAttributes.toString()}>
        <div id="root">${appString}</div>
        ${helmet.noscript.toString()}
        <script src="/client.js"></script>
      </body>
    </html>
  `);
});

app.listen(3000);

Important Notes

Memory Management

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.

// ❌ Memory leak - renderStatic() never called
app.get("/", (req, res) => {
  const html = ReactDOMServer.renderToString(<App />);
  res.send(`<html><body>${html}</body></html>`);
});

// ✅ Correct - renderStatic() extracts and clears state
app.get("/", (req, res) => {
  const html = ReactDOMServer.renderToString(<App />);
  const helmet = Helmet.renderStatic();
  res.send(`<html><body>${html}</body></html>`);
});

Webpack Externals

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

// webpack.config.js
module.exports = {
  externals: ["react-helmet"],
  // ... other config
};

Encoding Control

Control HTML entity encoding for server-side rendering:

<Helmet encodeSpecialCharacters={false}>
  <title>Title with <special> characters</title>
</Helmet>

// With encodeSpecialCharacters={true} (default):
// <title>Title with &lt;special&gt; characters</title>

// With encodeSpecialCharacters={false}:
// <title>Title with <special> characters</title>

Install with Tessl CLI

npx tessl i tessl/npm-react-helmet

docs

index.md

server-side-rendering.md

tile.json