本文へスキップ

技術

X は og: ではなく twitter: を読む —— Next.js のメタデータで踏んだ2つ

「共有したときのカードが、どのページを貼っても同じ文言になる」。原因は2つあって、どちらも黙って起きます。ページは正しく表示され、エラーも出ません。

X は og: ではなく twitter: を読む

openGraph だけを書いたページは、画像だけ差し替わってタイトルと説明がルートレイアウトの値のまま残ります。X が twitter:* を優先して読むためです。

このサイトでは、更新ログの個別ページ5件が実際にその状態でした。og:title は記事の見出しなのに、twitter:title はサイト全体のキャッチコピーのまま。貼るまで気づけません。

検証は「貼ってみる」しかありません。X の下書きに実 URL を入れて、出るカードを見る。デプロイしないと確かめられないのが厄介なところです。

Next.js のメタデータは、親を丸ごと置き換える

もう1つがこちらです。Next.js のメタデータは浅くマージされます。子のセグメントが openGraph を定義すると、親の openGraphまるごと置き換わります。中の imagessiteName だけが残る、ということはありません。

// app/<slug>/layout.tsx
export const metadata = {
  openGraph: { title: 'スグイコ' },   // ← 親の openGraph を丸ごと置き換える
}                                      //   images も siteName も消える

これで og:image が消え、共有カードが画像なしになりました。og:site_name にいたっては、メタデータを組み立てる関数を通す13ページすべてで出ていませんでした。ルートレイアウトが持っていても、子が上書きしていたためです。

対策 —— 別々に書ける口を作らない

個別に気をつける、では必ず漏れます。2つを同時に生成する関数を1つ置いて、そこからしか書けないようにしました。

  • openGraphtwitter を、同じ引数から一緒に組み立てる
  • siteName もその関数が持つ(親から降ってこないので)
  • ページ側は文言だけを渡す。片方だけ書く手段が無い

「気をつける」を仕組みに変える、というだけの話ですが、これが唯一効きました。

同じことが alternates でも起きる

後日、RSS フィードのリンクを足そうとして同じ穴に落ちかけました。alternates も同じように丸ごと置き換わります。

つまり、alternates.canonical を返す関数を通るページでは、ルートレイアウトに書いた alternates.types丸ごと消えます。キーが違うだけで、openGraph のときとまったく同じ現象です。

フィードのリンクも、canonical と同じ関数の中に入れました。置き換わるものは、置き換える側が全部持つ。 これが結論です。

Notes 一覧へ戻る