metadata の書き方と title の決まり方
metadata は Server Component から出すもので、レイアウトに書いた title の template は下の階層にだけ掛かり、自分自身には掛かりません。
サーバー側で先に決まっている必要がある
metadata は、そのページの HTML を組み立てる前に決まっていなければなりません。だから use client を付けたファイルからは出せません。
実機で確かめた文言です。
Error: You are attempting to export "metadata" from a component marked with
"use client", which is disallowed. "metadata" must be resolved on the server
before the page component is rendered.
title は3通りの決まり方をする
レイアウトにこう書いたとします。
export const metadata = {
title: { default: 'サイトの名前', template: '%s | サイトの名前' },
}
このとき、出来あがる <title> は書き方によって3通りに分かれます。実機で確かめた結果です。
| ページ側の title | 出来あがる title |
|---|---|
| 書かない | サイトの名前 |
| ふつうの指定 | ふつうの指定 | サイトの名前 |
| absolute を使う | 型を外した指定 |
1行目が分かりにくいところです。template は自分自身には掛かりません。掛かったら、トップページの title がサイト名の繰り返しになってしまいます。自分のぶんは default が受け持ちます。
サイト名を外したいとき
検索結果に出る幅は限られています。| サイトの名前 の分だけ、本題が削れます。
// 他の全ページからも付かなくなる効きすぎる。1ページのために全体を変えている。
export const metadata = { title: { absolute: 'App Router とは何か' }, }
そのページだけ外れる。実機で確認ずみ。
このサイトも記事ページでは absolute を使っています。題名そのもので探される種類のページでは、サイト名の分を本題に使ったほうが有利だからです。
動的なパスは generateMetadata
app/blog/[slug]/page.tsx のようなページでは、title が slug によって変わります。定数では書けないので、関数にします。
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
return { title: '記事: ' + slug }
}
実機で確かめました。出来あがった HTML はこうなります。
/blog/hello → <title>記事: hello | サイトの名前</title>
template は generateMetadata の結果にも掛かります。外したいときは、ここでも absolute を使います。
generateMetadata も metadata と同じ理由で Server Component 専用です。
出し先を1か所にまとめない
metadata は階層ごとに書けて、下の階層が上を上書きします。便利ですが、上書きされていることに気づきにくいのが難点です。
- Buildビルドした HTML の title を見る
推測しない。出来あがったものを見る。
- Buildそのページに title があるか
あれば、それが template を通ったかどうかを見る。
- Build無ければ、上の layout をたどる
いちばん近い指定が効いている。default か template かで結果が変わる。
触る前に決めておくこと
- 全ページで一意にする。同じ title が並ぶと、検索側でどれを出すか選べません
- 幅を決めておく。長すぎると途中で切れます。切れた先は読まれません
- 本文の見出しと同じにしなくてよい。画面で使う言葉と、検索窓に打つ言葉は一致しません
このサイトでは、title の幅と重複をビルド時に機械で検査しています。人の注意力で守ると必ず抜けます。
出典
- nextjs.org/docs/app/api-reference/functions/generate-metadata
- nextjs.org/docs/app/getting-started/metadata-and-og-images
- nextjs.org/docs/app/api-reference/file-conventions/metadata
このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。