diff --git a/gatsby-config.js b/gatsby-config.js
index d2031822..5cfd4ad9 100644
--- a/gatsby-config.js
+++ b/gatsby-config.js
@@ -74,7 +74,9 @@ module.exports = {
],
},
},
- `gatsby-plugin-react-helmet-async`,
+ {
+ resolve: `./gatsby/plugin/helmet-async`,
+ },
{
resolve: `gatsby-source-filesystem`,
options: {
diff --git a/gatsby/plugin/helmet-async/gatsby-browser.tsx b/gatsby/plugin/helmet-async/gatsby-browser.tsx
new file mode 100644
index 00000000..6f9c2e5b
--- /dev/null
+++ b/gatsby/plugin/helmet-async/gatsby-browser.tsx
@@ -0,0 +1,9 @@
+import { GatsbyBrowser, WrapRootElementBrowserArgs } from "gatsby";
+import React from "react";
+import { HelmetProvider } from "react-helmet-async";
+
+export const wrapRootElement: GatsbyBrowser["wrapRootElement"] = ({
+ element,
+}: WrapRootElementBrowserArgs): React.ReactElement => (
+ {element}
+);
diff --git a/gatsby/plugin/helmet-async/gatsby-ssr.tsx b/gatsby/plugin/helmet-async/gatsby-ssr.tsx
new file mode 100644
index 00000000..eaf71852
--- /dev/null
+++ b/gatsby/plugin/helmet-async/gatsby-ssr.tsx
@@ -0,0 +1,55 @@
+import {
+ GatsbySSR,
+ PreRenderHTMLArgs,
+ RenderBodyArgs,
+ WrapRootElementNodeArgs,
+} from "gatsby";
+import React from "react";
+import { HelmetProvider, HelmetServerState } from "react-helmet-async";
+
+const context: {
+ [pathname: string]: { helmet?: HelmetServerState } | undefined,
+} = {};
+
+export const onRenderBody: GatsbySSR["onRenderBody"] = ({
+ pathname,
+ setHeadComponents,
+ setHtmlAttributes,
+ setBodyAttributes,
+}: RenderBodyArgs): void => {
+ const { helmet } = context[pathname] ?? {};
+
+ if (helmet) {
+ const baseComponent = helmet.base.toComponent();
+ const titleComponent = helmet.title.toComponent();
+ const components = [
+ helmet.priority.toComponent(),
+ helmet.meta.toComponent(),
+ helmet.link.toComponent(),
+ helmet.style.toComponent(),
+ helmet.script.toComponent(),
+ helmet.noscript.toComponent(),
+ ];
+
+ setHeadComponents(
+ titleComponent[0]?.props.children
+ ? [baseComponent, titleComponent, ...components]
+ : [baseComponent, ...components]
+ );
+
+ setHtmlAttributes(helmet.htmlAttributes.toComponent());
+ setBodyAttributes(helmet.bodyAttributes.toComponent());
+ }
+};
+
+export const onPreRenderHTML = ({ pathname }: PreRenderHTMLArgs) => {
+ context[pathname] = undefined;
+};
+
+export const wrapRootElement: GatsbySSR["wrapRootElement"] = ({
+ pathname,
+ element,
+}: WrapRootElementNodeArgs): React.ReactElement => {
+ context[pathname] = {};
+ return {element};
+};
diff --git a/gatsby/plugin/helmet-async/package.json b/gatsby/plugin/helmet-async/package.json
new file mode 100644
index 00000000..ff66a6a8
--- /dev/null
+++ b/gatsby/plugin/helmet-async/package.json
@@ -0,0 +1,54 @@
+{
+ "name": "gatsby-plugin-react-helmet-async",
+ "version": "0.0.1",
+ "description": "Use react-helmet-async with Gatsby",
+ "keywords": [
+ "gatsby",
+ "gatsby-plugin",
+ "react",
+ "react-helmet",
+ "react-helmet-async"
+ ],
+ "license": "Apache-2.0",
+ "main": "index.js",
+ "scripts": {
+ "prepublish": "yarn build",
+ "build": "tsc --build",
+ "clean": "rm gatsby-browser.d.ts gatsby-browser.js gatsby-ssr.d.ts gatsby-ssr.js",
+ "lint": "eslint src --ext ts,tsx --fix",
+ "test": "echo \"Error: no tests specified\" && exit 1"
+ },
+ "devDependencies": {
+ "@types/react": "^17",
+ "@types/react-dom": "^17",
+ "@typescript-eslint/eslint-plugin": "^5.42.1",
+ "@typescript-eslint/parser": "^5.42.1",
+ "eslint": "^8.27.0",
+ "eslint-config-prettier": "^8.5.0",
+ "eslint-config-standard-react": "^12.0.0",
+ "eslint-config-standard-with-typescript": "^23.0.0",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-node": "^11.1.0",
+ "eslint-plugin-prettier": "^4.2.1",
+ "eslint-plugin-promise": "^6.1.1",
+ "eslint-plugin-react": "^7.31.10",
+ "gatsby": "^3.8.0",
+ "prettier": "^2.7.1",
+ "prettier-eslint": "^15.0.1",
+ "react": "^17.0.2",
+ "react-dom": "^17.0.2",
+ "react-helmet-async": "^1.3.0",
+ "typescript": "^4.8.4"
+ },
+ "peerDependencies": {
+ "gatsby": ">=2",
+ "react": "^16.6.0 || ^17 || ^18",
+ "react-dom": "^16.6.0 || ^17 || ^18",
+ "react-helmet-async": "1.x"
+ },
+ "resolutions": {
+ "@types/react": "^17",
+ "@types/react-dom": "^17"
+ }
+}
diff --git a/package.json b/package.json
index eee7241d..3a15ac59 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,6 @@
"gatsby-plugin-meta-redirect": "^1.1.1",
"gatsby-plugin-postcss": "^5.21.0",
"gatsby-plugin-purgecss": "^6.1.0",
- "gatsby-plugin-react-helmet-async": "^1.2.1",
"gatsby-plugin-react-i18next": "^1.2.2",
"gatsby-plugin-react-svg": "^3.3.0",
"gatsby-plugin-remove-serviceworker": "^1.0.0",
diff --git a/yarn.lock b/yarn.lock
index ad674ff2..7dc8c967 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7352,11 +7352,6 @@ gatsby-plugin-purgecss@^6.1.0:
merge-anything "^5.0.2"
purgecss "^4.1.3"
-gatsby-plugin-react-helmet-async@^1.2.1:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet-async/-/gatsby-plugin-react-helmet-async-1.2.3.tgz#28d38b1cfc80edb140abbdb43e93258b0604ce57"
- integrity sha512-fA/FGZbJlZuqeZvaGc3intLWfsPclhY2EAtdHqarwde8D8RlanVn2nVUxrvLEhzwq8n4OpTfj/DChAVmr0D+yA==
-
gatsby-plugin-react-i18next@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/gatsby-plugin-react-i18next/-/gatsby-plugin-react-i18next-1.2.3.tgz#ae13bc1c6189e0179913fce83ef537a193cfd1f4"
@@ -11770,15 +11765,20 @@ react-error-overlay@^6.0.11:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"
integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==
-react-fast-compare@^3.1.1, react-fast-compare@^3.2.0:
+react-fast-compare@^3.1.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
+react-fast-compare@^3.2.0:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
+ integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
+
react-helmet-async@^1.2.2:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.2.3.tgz#57326a69304ea3293036eafb49475e9ba454cb37"
- integrity sha512-mCk2silF53Tq/YaYdkl2sB+/tDoPnaxN7dFS/6ZLJb/rhUY2EWGI5Xj2b4jHppScMqY45MbgPSwTxDchKpZ5Kw==
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.3.0.tgz#7bd5bf8c5c69ea9f02f6083f14ce33ef545c222e"
+ integrity sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==
dependencies:
"@babel/runtime" "^7.12.5"
invariant "^2.2.4"