react-helmet-async vs react-helmet vs react-document-title
React Document Head Management Libraries Comparison
1 Year
react-helmet-asyncreact-helmetreact-document-titleSimilar Packages:
What's React Document Head Management Libraries?

These libraries are designed to manage changes to the document head in React applications, allowing developers to dynamically set the title, meta tags, and other head elements based on the current state of the application. This is crucial for improving SEO, social sharing, and overall user experience. Each library offers unique features and approaches to handling document head updates, catering to different use cases and developer preferences.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
react-helmet-async2,186,8502,21586.3 kB78a year agoApache-2.0
react-helmet2,164,43317,479-2235 years agoMIT
react-document-title72,6281,863-218 years agoMIT
Feature Comparison: react-helmet-async vs react-helmet vs react-document-title

SEO Optimization

  • react-helmet-async:

    React-helmet-async builds upon the capabilities of react-helmet, adding support for asynchronous updates, which is crucial for SSR. This ensures that the document head is populated correctly before the content is sent to the client, enhancing SEO.

  • react-helmet:

    React-helmet excels in SEO optimization by enabling developers to manage not only the document title but also meta tags, link tags, and script tags. This comprehensive control allows for better search engine indexing and social media sharing.

  • react-document-title:

    This package allows for the dynamic setting of the document title, which is a fundamental aspect of SEO. However, it does not support meta tags or other head elements, limiting its SEO capabilities.

Asynchronous Support

  • react-helmet-async:

    React-helmet-async is specifically designed for asynchronous operations, allowing for head updates to be handled seamlessly in SSR environments, ensuring that the document head is correctly populated.

  • react-helmet:

    React-helmet does not natively support asynchronous updates, which can lead to issues in SSR scenarios where head elements need to be updated before rendering.

  • react-document-title:

    This package does not support asynchronous updates, making it less suitable for applications that require dynamic head changes based on asynchronous data fetching.

Ease of Use

  • react-helmet-async:

    React-helmet-async maintains a similar API to react-helmet but adds complexity due to its asynchronous capabilities. It may require a deeper understanding of React's context API for optimal use.

  • react-helmet:

    React-helmet offers a slightly more complex API due to its extensive features, but it remains user-friendly for those familiar with React. It allows for a declarative approach to managing the document head.

  • react-document-title:

    This library is very easy to use, requiring minimal setup and providing a straightforward API for managing the document title. It is perfect for developers looking for simplicity.

Community and Maintenance

  • react-helmet-async:

    React-helmet-async is gaining popularity, especially among developers using SSR. It benefits from the community around react-helmet while focusing on asynchronous capabilities.

  • react-helmet:

    React-helmet has a larger community and is widely used, ensuring better support, more frequent updates, and a wealth of resources and documentation available for developers.

  • react-document-title:

    This package has a smaller community and less frequent updates compared to the others, which may impact long-term support and feature enhancements.

Performance

  • react-helmet-async:

    React-helmet-async is optimized for performance in SSR scenarios, ensuring that head updates do not block rendering and that the document head is populated efficiently.

  • react-helmet:

    While react-helmet is efficient, it can introduce some overhead due to its comprehensive feature set. However, this is often negligible for most applications.

  • react-document-title:

    Performance is generally good for this lightweight library, as it only manages the document title without additional overhead from meta tags or other elements.

How to Choose: react-helmet-async vs react-helmet vs react-document-title
  • react-helmet-async:

    Opt for react-helmet-async when working with server-side rendering (SSR) or when you need to manage head elements asynchronously. This library is designed to handle head updates in a way that is compatible with SSR, ensuring that the document head is correctly populated before the page is rendered.

  • react-helmet:

    Select react-helmet if you need a comprehensive solution for managing the document head, including meta tags, title, and other elements. It provides a declarative API and is well-suited for larger applications that require extensive SEO features and customization.

  • react-document-title:

    Choose react-document-title for simple projects where you only need to manage the document title without complex meta tags or SEO considerations. It is lightweight and straightforward, making it ideal for small applications.

README for react-helmet-async

react-helmet-async

CircleCI

Announcement post on Times Open blog

This package is a fork of React Helmet. <Helmet> usage is synonymous, but server and client now requires <HelmetProvider> to encapsulate state per request.

react-helmet relies on react-side-effect, which is not thread-safe. If you are doing anything asynchronous on the server, you need Helmet to encapsulate data on a per-request basis, this package does just that.

Usage

New is 1.0.0: No more default export! import { Helmet } from 'react-helmet-async'

The main way that this package differs from react-helmet is that it requires using a Provider to encapsulate Helmet state for your React tree. If you use libraries like Redux or Apollo, you are already familiar with this paradigm:

import React from 'react';
import ReactDOM from 'react-dom';
import { Helmet, HelmetProvider } from 'react-helmet-async';

const app = (
  <HelmetProvider>
    <App>
      <Helmet>
        <title>Hello World</title>
        <link rel="canonical" href="https://www.tacobell.com/" />
      </Helmet>
      <h1>Hello World</h1>
    </App>
  </HelmetProvider>
);

ReactDOM.hydrate(
  app,
  document.getElementById(‘app’)
);

On the server, we will no longer use static methods to extract state. react-side-effect exposed a .rewind() method, which Helmet used when calling Helmet.renderStatic(). Instead, we are going to pass a context prop to HelmetProvider, which will hold our state specific to each request.

import React from 'react';
import { renderToString } from 'react-dom/server';
import { Helmet, HelmetProvider } from 'react-helmet-async';

const helmetContext = {};

const app = (
  <HelmetProvider context={helmetContext}>
    <App>
      <Helmet>
        <title>Hello World</title>
        <link rel="canonical" href="https://www.tacobell.com/" />
      </Helmet>
      <h1>Hello World</h1>
    </App>
  </HelmetProvider>
);

const html = renderToString(app);

const { helmet } = helmetContext;

// helmet.title.toString() etc…

Streams

This package only works with streaming if your <head> data is output outside of renderToNodeStream(). This is possible if your data hydration method already parses your React tree. Example:

import through from 'through';
import { renderToNodeStream } from 'react-dom/server';
import { getDataFromTree } from 'react-apollo';
import { Helmet, HelmetProvider } from 'react-helmet-async';
import template from 'server/template';

const helmetContext = {};

const app = (
  <HelmetProvider context={helmetContext}>
    <App>
      <Helmet>
        <title>Hello World</title>
        <link rel="canonical" href="https://www.tacobell.com/" />
      </Helmet>
      <h1>Hello World</h1>
    </App>
  </HelmetProvider>
);

await getDataFromTree(app);

const [header, footer] = template({
  helmet: helmetContext.helmet,
});

res.status(200);
res.write(header);
renderToNodeStream(app)
  .pipe(
    through(
      function write(data) {
        this.queue(data);
      },
      function end() {
        this.queue(footer);
        this.queue(null);
      }
    )
  )
  .pipe(res);

Usage in Jest

While testing in using jest, if there is a need to emulate SSR, the following string is required to have the test behave the way they are expected to.

import { HelmetProvider } from 'react-helmet-async';

HelmetProvider.canUseDOM = false;

Prioritizing tags for SEO

It is understood that in some cases for SEO, certain tags should appear earlier in the HEAD. Using the prioritizeSeoTags flag on any <Helmet> component allows the server render of react-helmet-async to expose a method for prioritizing relevant SEO tags.

In the component:

<Helmet prioritizeSeoTags>
  <title>A fancy webpage</title>
  <link rel="notImportant" href="https://www.chipotle.com" />
  <meta name="whatever" value="notImportant" />
  <link rel="canonical" href="https://www.tacobell.com" />
  <meta property="og:title" content="A very important title"/>
</Helmet>

In your server template:

<html>
  <head>
    ${helmet.title.toString()}
    ${helmet.priority.toString()}
    ${helmet.meta.toString()}
    ${helmet.link.toString()}
    ${helmet.script.toString()}
  </head>
  ...
</html>

Will result in:

<html>
  <head>
    <title>A fancy webpage</title>
    <meta property="og:title" content="A very important title"/>
    <link rel="canonical" href="https://www.tacobell.com" />
    <meta name="whatever" value="notImportant" />
    <link rel="notImportant" href="https://www.chipotle.com" />
  </head>
  ...
</html>

A list of prioritized tags and attributes can be found in constants.ts.

Usage without Context

You can optionally use <Helmet> outside a context by manually creating a stateful HelmetData instance, and passing that stateful object to each <Helmet> instance:

import React from 'react';
import { renderToString } from 'react-dom/server';
import { Helmet, HelmetProvider, HelmetData } from 'react-helmet-async';

const helmetData = new HelmetData({});

const app = (
    <App>
      <Helmet helmetData={helmetData}>
        <title>Hello World</title>
        <link rel="canonical" href="https://www.tacobell.com/" />
      </Helmet>
      <h1>Hello World</h1>
    </App>
);

const html = renderToString(app);

const { helmet } = helmetData.context;

License

Licensed under the Apache 2.0 License, Copyright © 2018 Scott Taylor