react-helmet-async
TypeScript icon, indicating that this package has built-in type declarations

2.0.5 • Public • Published

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

Versions

Current Tags

VersionDownloads (Last 7 Days)Tag
2.0.5463,786latest
2.0.5-next0next
2.0.5-beta0beta
2.0.5-alpha0alpha

Version History

VersionDownloads (Last 7 Days)Published
2.0.5-alpha0
2.0.5-beta0
2.0.5-next0
2.0.5463,786
2.0.454,815
2.0.4-alpha0
2.0.4-next0
2.0.4-beta0
2.0.3-beta0
2.0.38,438
2.0.3-alpha0
2.0.3-next26
2.0.2-next1
2.0.2157
2.0.15,748
2.0.08,828
2.0.0-beta.10
2.0.0-next.10
2.0.0-next1
2.0.0-beta0
2.0.1-alpha2
2.0.0-alpha0
1.3.0974,581
1.2.330,062
1.2.229,724
1.2.11,114
1.2.0150
1.1.239,974
1.1.17
1.1.0350
1.0.993,537
1.0.8135
1.0.721,526
1.0.612,155
1.0.5797
1.0.414,424
1.0.3948
1.0.28,883
1.0.11
1.0.01
1.0.0-beta.10
1.0.0-beta.01
0.3.0-beta.30
0.3.0-beta.20
0.3.0-beta.10
0.3.0-beta.02
0.2.1-025
0.2.06,899
0.2.0-beta.11
0.2.0-beta.01
0.1.0-alpha0
0.1.0312
0.0.546
0.0.41
0.0.31
0.0.21
0.0.11

Package Sidebar

Install

npm i react-helmet-async

Weekly Downloads

1,777,462

Version

2.0.5

License

Apache-2.0

Unpacked Size

86.3 kB

Total Files

14

Last publish

Collaborators

  • wonderboymusic