使用ソフトウェア | バージョン | 備考 |
---|---|---|
Gatsby.js | 4.20 | APIは4.19から使用可能 |
Gatsby.js v4.19
よりgatsby-plugin-react-helmet
が将来的に廃止される模様。
代わりに、公式でGatsby Head APIと呼ぶ機能が実装されたため、プラグインなしでhead
タグ内にtitle
やmeta
といったタグを追加することが出来るようになっている。
gatsby-plugin-react-helmet
のページに廃止予定(will be deprecated)と書かれているため、いずれ更新がとまると思われる。
いままでreact-helmet
に依存することでhead
内にタグを書き込んでいた人が多いと思う。
今回こちらを廃止して切り替えということは、わざわざAPIに書き換える作業コストが必要となる。
それに見合うメリットはあるのだろうか。
公式によると
というメリットがあるらしい。
特に最近はWebサイトの性能評価がどんどん厳しくなっているため(1)のパフォーマンス向上で有利かと個人的に考えている。
もちろん現状のgatsby-plugin-react-helmet
はまだ正常動作するため、すぐさま切り替える必要はない。
実装前にgatsby-config.js
からgatsby-plugin-react-helmet
をコメントアウト(可能ならアンインストール)する。
これを行わずAPIで実装するとエラーでビルドできない。
アンインストールのコマンド例を掲載しておく
npm uninstall gatsby-plugin-react-helmet react-helmet
念のため上はアンインストールコマンドなので慎重に
Gatsby Head API
を使った新しい方法はコンポーネントには実装できない。
pages
かtemplate
にだけ利用できる。
たとえばindexページはpages
に当たる(固定ページ)
その中からLayout
などのコンポーネントを呼び出して使用するというのは基本である。
このときLayout
内からhead
タグに書き込むことはできないという意味。
この場合親になるindex
からヘッダを書き込む。
つまりsrc > components
に入っているjsからは使えないと覚えておいて良いだろう。
他にもgatsby-node.js
からcreatePages
関数で生成されるページのテンプレートからAPIを呼ぶことが出来る。
したがってBLOG記事などビルド時に生成されるページでもこのAPIは使用できる。
Gatsby Head API
を使うにあたって特別なインポートは必要ない。
Head
という関数をexport
してやりその中にtitle
やmeta
タグを書いておくだけで自動的に挿入される。
ただしGatsby.js
のバージョンが4.19以上である必要がある。
次が最も簡単な例。
import * as React from "react"
const headTest = () => {
return (<div>test</div>)
}
export default headTest
//次が新しいコード。必ずHeadという名前の関数。
export const Head = () => {
return (<title>ヘッダテスト</title>)
}
このようにHead
という関数を別途export
しており、その中のreturn
を使ってhead
に記述したいタグを書いている。
少々理解しにくい人もいるかもしれないが、このHead()
関数内でreturn
したタグがGatsby側で処理されてhead
に注入されるという仕組みである。
言うまでもないかもしれないが通常head
タグに書かないようなタグは使えない。
使えるのは次のタグ。
link
, meta
, style
, title
, base
, script
, noscript
.
このままだとハードコードしたデータしか使えない気がするが、そんなことはない。
記事名からタイトルを変えたい、説明文を変えたいなどのケース。
Head
を次のように書いて外部からのプロパティを読み込める。
export const Head = ({ location, params, data, pageContext }) => (
<>
略
各プロパティを説明すると
location
: location.pathname
としてやることで現在のURLが取得できるparams
: URLのパラメタを受け取る。matchPath
という機能を使うときだそうだが使ったこと無いので不明data
: GraphQL
で記述したデータが入ってくる。つまりBLOG記事の内容やタイトル、日付、画像のアドレスなどはここから取る。pageContext
: createPage
関数で渡ってくるデータを受け取る。一番よくあるのはdata
を使うことだと思う。
これはどこからくるのかというと、各ページにて
export const query = graphql`クエリ~~
のように指定して取ってくるクエリのことを指している。
これを利用することでtemplate
で様々なページが生成されたときにも個別のタイトルなどを付与することが可能。
またはuseStaticQuery
を利用しても良さそうだ。
import * as React from "react"
import { graphql, useStaticQuery } from "gatsby"
const headTest = () => {
return (<div>test</div>)
}
export default headTest
export const Head = () => {
const metaData = useStaticQuery(graphql`
query {
site {
siteMetadata {
title
description
}
}
}
`)
return (
<>
<title>{metaData.site.siteMetadata.title}</title>
</>
)
}
こちらは最小限しかテストしてないので動かないクエリもあるかもしれない。
上の方法だけだとページごとに別々のHead()
関数として書いてやらないといけないような気がする。
実はコンポーネントの中にHead()
が使えないだけでHead()
の中身をコンポーネント化することは可能。
例えば次のようなページを書いて
import * as React from "react"
import Seo from '../components/seo-head' //ここでhead用コンポーネントを呼ぶ
const headTest = () => {
return (<div>test</div>)
}
export default headTest
//Head()の中でコンポーネントを利用
export const Head = () => {
return (
<Seo
title="ここにタイトル"
twitter="Ultra-Noob"
/>
)
}
そしてSEOコンポーネント(ここではseo-head.js)の中身は
import React from "react"
const SEO = ({ title, twitter }) => {
return (
<>
<title>{title}</title>
<meta name="twitter:creator" content={twitter} />
</>
)
}
export default SEO
ブラウザで確認すると次のタグが正しく入っている。
このようにHead()
関数内はコンポーネント化できるので再利用が可能。
各ページごとにHead()
関数は毎回export
してやる必要があるので注意。
その中身をコンポーネント化できますよという意味。
上で特定のタグしか使えないと書いたが、もちろんJSXなので条件分岐が可能。
私が使うケースだとnoindex
のmeta
タグを入れるかどうかを分ける場合。
上のSEOコンポーネントに書き加えて
const SEO = ({ title, twitter, isNoindex }) => {
return (
<>
<title>{title}</title>
<meta name="twitter:creator" content={twitter} />
{
isNoindex ? <meta name="robots" content="noindex" /> : null
}
</>
)
}
isNoindex
にtrue
を入れたときだけnoindex
のメタタグが書かれるようになる。
公式よりこの他にもid
を使うことでタグを分けられるかもしれない。
これに関しては同じタグを排除する機能なので違うかも?
テストしていないので公式を読んだ上で試してもらえたらと思う。
謎の技術研究部の本番サイトで実装前と実装後のLighthouse
のスコアを計測した。
とは言ったものの殆ど差がでなかったのでスコアも掲載しない。
head
タグの仕組みを改善した程度で大きくスコアが上がるということが無いというのは少し考えれば当たり前ではある。
とは言え、過去の私のテストから外部プラグインのインポートは少ないほうがスコアが上がるのでreact-helmet
を読み込まないだけ有利になっていると予想できる。
少しでも効果があるのならば実装するに越したことはない。
公式のAPIページのみならず次のSEOコンポーネント解説ページが参考になる。
Adding an SEO Component | Gatsby(英文)
この記事でも多くの箇所で上を参照させていただいている。
より深く知りたい場合は読んでもらえたらと思う。
相変わらずGatsby.js
の記事に関しては解説が難しく理解してもらえてるかどうか怪しい。
ひとまず実装されたばかりで日本語の記事が見当たらなかったため率先して執筆させていただいた。
パフォーマンスと今後のアップデートを考慮して当サイトでは早速実装した。