Gathering detailed insights and metrics for @zudoku/react-helmet-async
Gathering detailed insights and metrics for @zudoku/react-helmet-async
Gathering detailed insights and metrics for @zudoku/react-helmet-async
Gathering detailed insights and metrics for @zudoku/react-helmet-async
Thread-safe Helmet for React 16+ and friends
npm install @zudoku/react-helmet-async
Typescript
Module System
Node Version
NPM Version
76.4
Supply Chain
99.6
Quality
81.2
Maintenance
100
Vulnerability
100
License
TypeScript (99.61%)
JavaScript (0.39%)
Built with Next.js • Fully responsive • SEO optimized • Open source ready
Total Downloads
31,328
Last Day
65
Last Week
1,523
Last Month
6,329
Last Year
31,328
Apache-2.0 License
2,242 Stars
171 Commits
175 Forks
14 Watchers
17 Branches
26 Contributors
Updated on Aug 30, 2025
Latest Version
2.0.5
Package Id
@zudoku/react-helmet-async@2.0.5
Unpacked Size
84.30 kB
Size
16.47 kB
File Count
14
NPM Version
10.8.2
Node Version
20.18.0
Published on
Dec 28, 2024
Cumulative downloads
Total Downloads
Last Day
124.1%
65
Compared to previous day
Last Week
-12.4%
1,523
Compared to previous week
Last Month
5.5%
6,329
Compared to previous month
Last Year
0%
31,328
Compared to previous year
3
1
26
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.
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:
1import React from 'react'; 2import ReactDOM from 'react-dom'; 3import { Helmet, HelmetProvider } from 'react-helmet-async'; 4 5const app = ( 6 <HelmetProvider> 7 <App> 8 <Helmet> 9 <title>Hello World</title> 10 <link rel="canonical" href="https://www.tacobell.com/" /> 11 </Helmet> 12 <h1>Hello World</h1> 13 </App> 14 </HelmetProvider> 15); 16 17ReactDOM.hydrate( 18 app, 19 document.getElementById(‘app’) 20);
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.
1import React from 'react'; 2import { renderToString } from 'react-dom/server'; 3import { Helmet, HelmetProvider } from 'react-helmet-async'; 4 5const helmetContext = {}; 6 7const app = ( 8 <HelmetProvider context={helmetContext}> 9 <App> 10 <Helmet> 11 <title>Hello World</title> 12 <link rel="canonical" href="https://www.tacobell.com/" /> 13 </Helmet> 14 <h1>Hello World</h1> 15 </App> 16 </HelmetProvider> 17); 18 19const html = renderToString(app); 20 21const { helmet } = helmetContext; 22 23// helmet.title.toString() etc…
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:
1import through from 'through'; 2import { renderToNodeStream } from 'react-dom/server'; 3import { getDataFromTree } from 'react-apollo'; 4import { Helmet, HelmetProvider } from 'react-helmet-async'; 5import template from 'server/template'; 6 7const helmetContext = {}; 8 9const app = ( 10 <HelmetProvider context={helmetContext}> 11 <App> 12 <Helmet> 13 <title>Hello World</title> 14 <link rel="canonical" href="https://www.tacobell.com/" /> 15 </Helmet> 16 <h1>Hello World</h1> 17 </App> 18 </HelmetProvider> 19); 20 21await getDataFromTree(app); 22 23const [header, footer] = template({ 24 helmet: helmetContext.helmet, 25}); 26 27res.status(200); 28res.write(header); 29renderToNodeStream(app) 30 .pipe( 31 through( 32 function write(data) { 33 this.queue(data); 34 }, 35 function end() { 36 this.queue(footer); 37 this.queue(null); 38 } 39 ) 40 ) 41 .pipe(res);
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.
1import { HelmetProvider } from 'react-helmet-async'; 2 3HelmetProvider.canUseDOM = false;
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:
1<Helmet prioritizeSeoTags> 2 <title>A fancy webpage</title> 3 <link rel="notImportant" href="https://www.chipotle.com" /> 4 <meta name="whatever" value="notImportant" /> 5 <link rel="canonical" href="https://www.tacobell.com" /> 6 <meta property="og:title" content="A very important title"/> 7</Helmet>
In your server template:
1<html> 2 <head> 3 ${helmet.title.toString()} 4 ${helmet.priority.toString()} 5 ${helmet.meta.toString()} 6 ${helmet.link.toString()} 7 ${helmet.script.toString()} 8 </head> 9 ... 10</html>
Will result in:
1<html> 2 <head> 3 <title>A fancy webpage</title> 4 <meta property="og:title" content="A very important title"/> 5 <link rel="canonical" href="https://www.tacobell.com" /> 6 <meta name="whatever" value="notImportant" /> 7 <link rel="notImportant" href="https://www.chipotle.com" /> 8 </head> 9 ... 10</html>
A list of prioritized tags and attributes can be found in constants.ts.
You can optionally use <Helmet>
outside a context by manually creating a stateful HelmetData
instance, and passing that stateful object to each <Helmet>
instance:
1import React from 'react'; 2import { renderToString } from 'react-dom/server'; 3import { Helmet, HelmetProvider, HelmetData } from 'react-helmet-async'; 4 5const helmetData = new HelmetData({}); 6 7const app = ( 8 <App> 9 <Helmet helmetData={helmetData}> 10 <title>Hello World</title> 11 <link rel="canonical" href="https://www.tacobell.com/" /> 12 </Helmet> 13 <h1>Hello World</h1> 14 </App> 15); 16 17const html = renderToString(app); 18 19const { helmet } = helmetData.context;
Licensed under the Apache 2.0 License, Copyright © 2018 Scott Taylor
No vulnerabilities found.