Create a <Head> component for Frontity Framework

Description

When developers use Frontity, the framework controls how the app is rendered (on both client and server).

This gives us the opportunity to render the whole <html> element with react and not just the <body> of the document.

Currently, Frontity is using react-helmet to manage the <head> of the document. This library comes with some extra bytes on top of the frontity framework (obviously) and it dynamically injects content into the <head> of the document outside of the React lifecycle.

Motivation

By creating our own <Head> component we could save some bytes from the Frontity bundle and manage the injection of elements into the <head> within pure react by leveraging React Context.

Examples

I have created a very simple demo of the concept: https://codesandbox.io/s/manage-document-head-with-pure-react-jz2hd

Yeah, we could create our own <Head> component and save the bytes of the code that react-helmet has to extract the content of the context for the HTML template because that would end up being rendered in React.

And maybe even have a way to pass strings and avoid having to parse them with Html2React (using dangeourslySetInnerHtml maybe?).

Good thing we are proxying react-helmet within a "frontity" import so we can do those types of things in the future without breaking backward compatibility :slightly_smiling_face:

I’ve been playing with this.

It seems like we cannot do <Fragment dangerouslySetInnerHTML={ { __html: HTML } } /> to add a string to the <head>.

I’ve been reading about this in the React repo:

There are a lot of people that want to do this, but it seems a bit stuck for now.

The only trick I found was to do:

<script
  dangerouslySetInnerHTML={{
    __html: `</script> <title>TEST</title> <script>`,
  }}
/>

which is super clever because the inner HTML closes the script opened by React and then opens a new one for the closing tag, ending with this valid markup:

<script></script>
<title>TEST</title>
<script></script>

I tried in CodeSandbox (CRA) and it doesn’t work until you flush the head with: document.head.innerHTML = document.head.innerHTML;. I don’t know about SSR. I tried with Frontity and it didn’t work. I think react-helmet may be filtering it out.