導入
先日、Gatsby.jsのバージョンを上げたところ、以下のような警告が出るようになりました。
warn gatsby-plugin-react-helmet: Gatsby now has built-in support for modyfing the document head. Learn more at https://gatsby.dev/gatsby-head
まだ警告の段階なので問題はありませんが、非推奨になる予定なのでやがて使えなくなる可能性があります。
react-helmet自体も2年以上更新されていないため、今後依存関係で問題が生じる可能性があります。
そこで、今回はreact-helmetから、その代わりに公式が出したAPIであるGatsby Head APIに書き換える方法を紹介します。
この記事の前提として、私はgatsby-starter-blogというテンプレートを使っています。
ですが、それ以外のテンプレートを使っているGatsby.jsユーザーの方にも役立つと思うので、ぜひ記事を読んでいただけると嬉しいです。
スポンサードリンク
Gatsby Head APIとは
Gatsby Head APIとは、Gatsby 4.19.0から追加されたreact-helmetに代わる<head>
タグに情報を追加できるAPIです。
Gatsby自体に組み込まれているため、バージョンが4.19.0以降であれば特にプラグインを追加することなく利用できます。
利用方法についてもそこまで難しくなく、react-helmetと比べて以下の利点があります。
- バンドルサイズの低下
- パフォーマンス向上
- ページごとに動的に
<head>
タグを書き換え可能
なので、Gatsbyをこれからも使っていくのであれば、ぜひ利用することをお勧めします。
Gatsby Head APIの使い方
Gatsby Head APIの使い方を、react-helmetと比較しながら説明します。
事前準備
react-helmetからGatsby Head APIに書き換えるには事前準備が必要です。
具体的には、以下の2つの手順が必要です。
- react-helmetのアンインストール
- gatsby-config.jsからプラグインを削除
この手順をしないと、似た機能を持つ2つが競合して、意図しない動作になります。
react-helmetのアンインストール
まず、ターミナルで以下のコマンドを入力し、 react-helmet と gatsby-plugin-react-helmet の2つのパッケージをアンインストールします。
npmの場合
npm uninstall react-helmet gatsby-plugin-react-helmet
yarnの場合
yarn remove react-helmet gatsby-plugin-react-helmet
gatsby-config.jsからプラグインを削除
次に、gatsby-config.jsのpluginsにあるgatsby-plugin-react-helmetを削除します。
これで事前準備は完了です。
module.exports = { // 途中省略 plugins: [ // 途中省略- `gatsby-plugin-react-helmet`, //この行を削除 // 途中省略 ] }
基本的な使い方
それでは、Gatsby Head APIの基本的な使い方について紹介します。
react-helmetでは<Helmet>
タグを書き、その中に<head>
タグに追加するHTMLを書いていました。
import * as React from "react" import { Helmet } from "react-helmet" const Example = () => { return ( // この部分 <Helmet> <title>Gatsby Head API</title> <meta name="description" content="Gatsby Head API Example" /> </Helmet> <div>Example</div> ) }
export default Example
Gatsby Head APIでは代わりに各ページにHead
という関数を定義し、その中に<head>
タグに追加するHTMLを書きます。
具体的には、以下のような形です。
import * as React from "react" const Example = () => { return ( <div>Example</div> ) }
export default Example
// この部分 export const Head = () => { <> <title>Gatsby Head API</title> <meta name="description" content="Gatsby Head API Example" /> </> }
このように、<head>
タグに追加したいページにHead
関数を定義し、その中にjsx記法で追加した いタグを書きます。
jsx記法なので、追加したいタグが2つ以上ある場合は、<></>
(React Fragment)で囲う必要があります。
スポンサードリンク
書き換えの具体的な手順
次に、<head>
の部分をコンポーネント化している場合の書き換え方法を紹介します。
今回は、gatsby-starter-blogにあるSeoコンポーネントを例にとって説明します。
他のコンポーネントの場合は、自分のコンポーネントに置き換えて見てもらえると嬉しいです。
gatsby-starter-blogのSeoコンポーネントは、以下の実装になっています。
import { Helmet } from "react-helmet"
const Seo = ({ description, lang, meta, title, ogpImgPath }) => { // 途中省略 return ( <Helmet htmlAttributes={{ lang, }} title={title} titleTemplate={titleTemplate} meta={[ { name: `description`, content: metaDescription, }, { property: `og:title`, content: title, }, { property: `og:description`, content: metaDescription, }, { property: `og:type`, content: type, }, { property: `og:site_name`, content: defaultTitle, }, { property: `og:image`, content: `${site.siteMetadata?.siteUrl}${imgPath}`, }, { name: `twitter:card`, content: `summary_large_image`, }, { name: `twitter:creator`, content: site.siteMetadata?.social?.twitter || ``, }, { name: `twitter:title`, content: title, }, { name: `twitter:description`, content: metaDescription, }, ].concat(meta)} link={[ { rel: `preconnect`, href: `https://fonts.googleapis.com`, }, { rel: `preconnect`, href: `https://fonts.gstatic.com/`, crossorigin: "", }, { rel: `stylesheet`, href: `https://fonts.googleapis.com/css?family=Noto+Sans+JP:wght@400;700&display=swap`, }, ]} /> ) }
これは、以下の書き方と同じ意味です。
import { Helmet } from "react-helmet"
const Seo = ({ description, lang, meta, title, ogpImgPath }) => { // 途中省略 return ( <Helmet> <html lang={lang} /> <title>{titleTemplate}</title> <meta name="description" content={metaDescription} /> <meta property="og:title" content={title} /> <meta property="og:description" content={metaDescription} /> <meta property="og:type" content={type} /> <meta property="og:site_name" content={defaultTitle} /> <meta property="og:image" content={`${site.siteMetadata?.siteUrl}${imgPath}`} /> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:creator" content={site.siteMetadata?.social?.twitter || ``} /> <meta name="twitter:title" content={title} /> <meta name="twitter:description" content={metaDescription} /> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" /> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+Sans+JP:wght@400;700&display=swap" /> </Helmet> ) }
Gatsby Head APIに書き換えるうえで、後者の書き方のほうがわかりやすいので、今回は後者の書き方と比較し、書き換えていきます。
書き換えに必要なステップは以下の3つです。
- Seoコンポーネントの書き換え
- lang属性の書き換え
- 各ページの書き換え
それでは 順に紹介していきます。
Seoコンポーネントの書き換え
Seoコンポーネントの書き換えは簡単です。
基本的には、<Helmet>
タグを<>
(React Fragment)に書き換え、react-helmetのインポート部分を削除するだけです。
ただし、1つ注意点があります。
Gatsby Head APIでは、<head>
タグ内の書き換えしかできないため、それ以外の書き換え部分は取り除かなければいけません。
先ほどの例ですと、<html lang={lang} />
がそれに当たります。
なので、この部分と関連する部分を取り除きます。
// react-helmetのimport部分を削除
const Seo = ({ description, /*langを削除*/ meta, title, ogpImgPath }) => { // 途中省略 return ( <> {/*langを削除*/} <title>{titleTemplate}</title> <meta name="description" content={metaDescription} /> <meta property="og:title" content={title} /> <meta property="og:description" content={metaDescription} /> <meta property="og:type" content={type} /> <meta property="og:site_name" content={defaultTitle} /> <meta property="og:image" content={`${site.siteMetadata?.siteUrl}${imgPath}`} /> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:creator" content={site.siteMetadata?.social?.twitter || ``} /> <meta name="twitter:title" content={title} /> <meta name="twitter:description" content={metaDescription} /> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" /> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+Sans+JP:wght@400;700&display=swap" /> </> ) }
Seo.defaultProps = {- lang: `ja`, //この行を削除 meta: [], description: ``, ogpImgPath: null, }
Seo.propTypes = { description: PropTypes.string,- lang: PropTypes.string, //この行を削除 meta: PropTypes.arrayOf(PropTypes.object), title: PropTypes.string.isRequired, ogpImgPath: PropTypes.string, }
追加で、各ページごとに<head>
タグに追加できるようにしたい場合は、childrenという変数を使い、最後に追加します。
これにより、Seoコンポーネント内にタグを入れることで、そのページのみにタグを追加することができます。
これでこのステップは完成です。
const Seo = ({ description, meta, title, ogpImgPath, children /*追加*/ }) => { // 途中省略 return ( <> <title>{titleTemplate}</title> <meta name="description" content={metaDescription} /> <meta property="og:title" content={title} /> <meta property="og:description" content={metaDescription} /> <meta property="og:type" content={type} /> <meta property="og:site_name" content={defaultTitle} /> <meta property="og:image" content={`${site.siteMetadata?.siteUrl}${imgPath}`} /> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:creator" content={site.siteMetadata?.social?.twitter || ``} /> <meta name="twitter:title" content={title} /> <meta name="twitter:description" content={metaDescription} /> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" /> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+Sans+JP:wght@400;700&display=swap" />+ {children} </> ) }
lang属性の書き換え
次に、lang属性の部分の実装を書き換えます。
先ほど説明したように、Gatsby Head APIでは、<head>
タグ内のタグ以外は入れることができないため、代わりにgatsby-ssr.jsに以下の記載を追加します。
gatsby-ssr.jsがまだ存在していない場合は、gatsby-config.jsと同じ階層に新たにファイルを作成してください。
exports.onRenderBody = ({ setHtmlAttributes }) => { setHtmlAttributes({ lang: "ja" })}
これで、HTMLのlang属性をja
に設定することができました。
各ページの書き換え
最後に、各ページの記述を書き換えます。
具体的には、各ページのコンポーネント部分に書かれているSeoコンポーネントの部分を、新しく作ったHead関数内に移動するだけです。
具体的には、以下のように変更します。
Seoコンポーネントで受け渡すpropsの値が固定の場合と動的に変わる場合で実装が変わります。
propsの値が固定の場合
Seoコンポーネントでpropsが固定の場合は、SeoコンポーネントをHead関数内にそのまま移動するだけです。
変更前
const NotFoundPage = ({ data, location }) => { const siteTitle = data.site.siteMetadata.title return ( <Layout location={location} title={siteTitle}> <Seo title="404: Not Found" /> <h1>404</h1> <p>ページが見つかりません。</p> </Layout> ) } export default NotFoundPage
変更後
const NotFoundPage = ({ data, location }) => { const siteTitle = data.site.siteMetadata.title
return ( <Layout location={location} title={siteTitle}> {/*Seoコンポーネントを削除*/} <h1>404</h1> <p>ページが見つかりません。</p> </Layout> ) }
export default NotFoundPage
+ export const Head = () => (+ <Seo title="404: Not Found" />+ )
propsが動的に変わる場合
Seoコンポーネントでpropsの値が動的に変わる場合は、Head関数で以下の値が受け取れるため、その値を利用します。
- location
- params
- data
- pageContext
これは、以下のように受け取れます。
export const Head = ({ location, params, data, pageContext }) => ( <> <title>{pageContext.title}</title> <meta name="description" content={data.page.description} /> </>)
例えば、gatsby-starter-blogのblog-post.jsの場合、以下のように修正できます。
変更前
const BlogPostTemplate = ({ data, location }) => { const post = data.markdownRemark //途中省略 return ( <Layout location={location} title={siteTitle}> <Seo title={post.frontmatter.title} description={post.frontmatter.description || post.excerpt} ogpImgPath={post.frontmatter.ogpImgPath} /> {/*途中省略*/} </Layout> ) }
変更後
const BlogPostTemplate = ({ data, location }) => { const post = data.markdownRemark //途中省略 return ( <Layout location={location} title={siteTitle}> {/*Seo部分の削除*/} {/*途中省略*/} </Layout> ) }
+ export const Head = ({ data }) => (+ <Seo+ title={data.markdownRemark.frontmatter.title}+ description={data.markdownRemark.frontmatter.description || data.markdownRemark.excerpt}+ ogpImgPath={data.markdownRemark.frontmatter.ogpImgPath}+ />+ )
これで、Gatsby Head APIへの書き換えが完了です。
スポンサードリンク
まとめ
今回は、react-helmetからGatsby Head APIに書き換える方法を紹介しました。
いくつか手順はあるものの、手順に沿って行けば、書き換えることができたと思います。
一度移行することで、今後エラーや警告なくブログ開発できると思うので、この記事を参考にしていただけたら幸いです。