This project is a port of react-helmet
to Preact, the 3kB lightweight React alternative.
This Preact component will manage all of your changes to the document head with support
for document title, meta, link, style, script, noscript, and base tags.
Inspired by:
Table of Contents generated with DocToc
import {h} from "preact"; /** @jsx h */
import Helmet from "preact-helmet";
export default function Application () {
return (
<div className="application">
<Helmet title="My Title" />
...
</div>
);
};
import {h} from "preact"; /** @jsx h */
import Helmet from "preact-helmet";
export default function Application () {
return (
<div className="application">
<Helmet
htmlAttributes={{lang: "en", amp: undefined}} // amp takes no value
title="My Title"
titleTemplate="MySite.com - %s"
defaultTitle="My Default Title"
titleAttributes={{itemprop: "name", lang: "en"}}
base={{target: "_blank", href: "http://mysite.com/"}}
meta={[
{name: "description", content: "Helmet application"},
{property: "og:type", content: "article"}
]}
link={[
{rel: "canonical", href: "http://mysite.com/example"},
{rel: "apple-touch-icon", href: "http://mysite.com/img/apple-touch-icon-57x57.png"},
{rel: "apple-touch-icon", sizes: "72x72", href: "http://mysite.com/img/apple-touch-icon-72x72.png"}
]}
script={[
{src: "http://include.com/pathtojs.js", type: "text/javascript"},
{type: "application/ld+json", innerHTML: `{ "@context": "http://schema.org" }`}
]}
noscript={[
{innerHTML: `<link rel="stylesheet" type="text/css" href="foo.css" />`}
]}
style={[
{type: "text/css", cssText: "body {background-color: blue;} p {font-size: 12px;}"}
]}
onChangeClientState={(newState) => console.log(newState)}
/>
...
</div>
);
};
title, base, meta, link, script, noscript, and style tags.html and title tags.npm install --save preact-helmet
To use on the server, call rewind() after using render from preact-render-to-string
to get the head data for use in your prerender.
Because this component keeps track of mounted instances, you have to make sure to call rewind on server, or you’ll get a memory leak.
import { render } from 'preact-render-to-string'
import Helmet from 'preact-helmet'
const markup = renderToString(<MyApp />);
const head = Helmet.rewind();
// populate some document template using `markup` and `head`
const html = `
<!doctype html>
<html>
<head>
${head.title.toString()}
${head.meta.toString()}
${head.link.toString()}
</head>
<body>
<div id="content">
${markup}
</div>
</body>
</html>
`;
head contains the following properties:
htmlAttributestitlebasemetalinkscriptnoscriptstyleEach property contains toComponent() and toString() methods. Use whichever is appropriate
for your environment. For htmlAttributes, use the JSX spread operator on the object returned
by toComponent(). E.g:
const html = `
<!doctype html>
<html ${head.htmlAttributes.toString()}>
<head>
${head.title.toString()}
${head.meta.toString()}
${head.link.toString()}
</head>
<body>
<div id="content">
${markup}
</div>
</body>
</html>
`;
If you are doing server side rendering with Preact, it may be easier to render the
document template with Preact as well:
function HTML({head}) {
const attrs = head.htmlAttributes.toComponent();
return (
<html {...attrs}>
<head>
{head.title.toComponent()}
{head.meta.toComponent()}
{head.link.toComponent()}
</head>
<body>
<div id="content">
<MyApp />
</div>
</body>
</html>
);
}
<Helmet
title="My Title"
meta={[
{"name": "description", "content": "Helmet application"}
]}
/>
<Helmet
title="Nested Title"
meta={[
{"name": "description", "content": "Nested component"}
]}
/>
Yields:
<head>
<title>Nested Title</title>
<meta name="description" content="Nested component">
</head>
<Helmet
title="My Title"
titleTemplate="%s | MyAwesomeWebsite.com"
/>
<Helmet
title="Nested Title"
/>
Yields:
<head>
<title>Nested Title | MyAwesomeWebsite.com</title>
</head>
meta and/or link tags in the same component are preserved<Helmet
link={[
{"rel": "apple-touch-icon", "href": "http://mysite.com/img/apple-touch-icon-57x57.png"},
{"rel": "apple-touch-icon", "sizes": "72x72", "href": "http://mysite.com/img/apple-touch-icon-72x72.png"}
]}
/>
Yields:
<head>
<link rel="apple-touch-icon" href="http://mysite.com/img/apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="72x72" href="http://mysite.com/img/apple-touch-icon-72x72.png">
</head>
<Helmet
link={[
{"rel": "apple-touch-icon", "href": "http://mysite.com/img/apple-touch-icon-57x57.png"},
{"rel": "apple-touch-icon", "sizes": "72x72", "href": "http://mysite.com/img/apple-touch-icon-72x72.png"}
]}
/>
<Helmet
link={[
{"rel": "apple-touch-icon", "href": "http://mysite.com/img/apple-touch-icon-180x180.png"}
]}
/>
Yields:
<head>
<link rel="apple-touch-icon" href="http://mysite.com/img/apple-touch-icon-180x180.png">
</head>
<Helmet
base={{"href": "http://mysite.com/"}}
/>
<Helmet
base={{"href": "http://mysite.com/blog"}}
/>
Yields:
<head>
<base href="http://mysite.com/blog">
</head>
<Helmet
defaultTitle="My Site"
titleTemplate="My Site - %s"
/>
Yields:
<head>
<title>My Site</title>
</head>
But a child route with a title will use the titleTemplate, giving users a way to declare a titleTemplate for their app, but not have it apply to the root.
<Helmet
defaultTitle="My Site"
titleTemplate="My Site - %s"
/>
<Helmet
title="Nested Title"
/>
Yields:
<head>
<title>My Site - Nested Title</title>
</head>
And other child route components without a Helmet will inherit the defaultTitle.
<script> tags:<Helmet
script={[{
"type": "application/ld+json",
"innerHTML": `{
"@context": "http://schema.org",
"@type": "NewsArticle"
}`
}]}
/>
Yields:
<head>
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "NewsArticle"
}
</script>
</head>
<style> tags:<Helmet
style={[{
"cssText": `
body {
background-color: green;
}
`
}]}
/>
Yields:
<head>
<style>
body {
background-color: green;
}
</style>
</head>
Please take a moment to review the guidelines for contributing.
MIT
react-helmet-example (for React, but still useful)