Next.js の動的ルーティングでメタデータを生成する

힘센캥거루
2024년 12월 16일
24
nextjs

検索エンジン最適化のために metadata をどう入れるか調べていたところ、velog でDoeunnkimmさんの記事を見て、メタデータを静的に注入していた。

投稿を始めてみると、動的ルーティングで各ポストごとに異なる metadata を入れたくなった。

そこで復習も兼ねて一度書いてみる。

1. コード

まず、上の velog で見つけたコードは以下のとおり。

// まず基本的に必要なメタデータを設定する。
const META = {
  title: "ブログタイトル",
  siteName: "サイト名",
  description: "ブログに関する大まかな説明",
  keyword: ["配列", "形式の", "キーワード"],
  url: "https://sample.kr",
  googleVerification: "xxx", // Google サーチコンソール
  naverVerification: "xxx", // Naver サーチアドバイザー
  ogImage: "https://sample.kr/assets/thumbnail.png", // サムネイル,
} as const;

// getMetadata 関数を利用して metadata を設定する。
// 下の関数 1 つで、ほとんどのサイトで必要な metadata は事足りる。
export const getMetadata = (metadataProps?: generateMetadataProps) => {
  const { title, description, asPath, ogImage } = metadataProps || {};

  const TITLE = title ? `${title} | ブログタイトル` : META.title;
  const DESCRIPTION = description || META.description;
  const PAGE_URL = asPath ? asPath : "";
  const OG_IMAGE = ogImage || META.ogImage;

  const metadata: Metadata = {
    metadataBase: new URL(META.url),
    alternates: {
      canonical: PAGE_URL,
    },
    title: TITLE,
    description: DESCRIPTION,
    keywords: [...META.keyword],
    openGraph: {
      title: TITLE,
      description: DESCRIPTION,
      siteName: TITLE,
      locale: "ko_KR",
      type: "website",
      url: PAGE_URL,
      images: {
        url: OG_IMAGE,
      },
    },
    verification: {
      google: META.googleVerification,
      other: {
        "naver-site-verification": META.naverVerification,
      },
    },
    twitter: {
      title: TITLE,
      description: DESCRIPTION,
      images: {
        url: OG_IMAGE,
      },
    },
    icons: {
      icon: "/favicon/favicon.ico",
    },
  };

  return metadata;
};

そしてこのコードを layout.tsx で呼び出して使用する。

metadata を生成してこれを export すると、ホームページに関するメタデータが生成される。

import "./globals.css";
import { Metadata } from "next";
import { getMetadata } from "@/utils/getMetadata";

// メタデータオブジェクトをエクスポート
export const metadata: Metadata = {
  // スプレッド構文 .. を利用してオブジェクトを取り込む。
  ...getMetadata(),

  // もし別のタイトルを使いたいなら、以下のようにすればよい。
  ...getMetadata({ title: "別のタイトル" }),
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ko">
      <body className="h-svh">
        <div>
          <div className="mx-auto max-w-7xl p-6 lg:px-8">{children}</div>
        </div>
      </body>
    </html>
  );
}

自分のホームページにアクセスして F12 キーを押し、<head> タグを確認すると、metadata を確認できる。

Next.js の動的ルーティングでメタデータを生成する-1

2. 動的ルーティングと metadata

動的ルーティングでは generateMetadata 関数を利用した。

これに関する説明は上記ブログやNextjs 公式ドキュメントにある。

Next.js の動的ルーティングでメタデータを生成する-2

この記事のポイントは、metadata を作るときに動的ルーティングで使われるオブジェクトを利用できるということだ。

自分は slug と記事一覧が入った Json を使ってメタデータを作成した。

export async function generateMetadata({
  params,
}: {
  params: { slug: string };
}) {
  const { slug } = await params;

  // カテゴリー一覧 json を読み込む
  const categoryData = fs.readFileSync(categoryJsonPath, "utf-8");
  const categorys: postCardFrontMatter[] = JSON.parse(categoryData);

  // 現在の slug と url が同じものを 1 件探して返す。
  const baseMetaData = categorys.find(
    (category) => category.postUrlPath === slug
  );

  // これを利用してメタデータを設定
  const metadata: Metadata = {
    ...getMetadata({
      title: baseMetaData?.data.title,
      description: baseMetaData?.data.description,
      asPath: `https://earthscience.kr/posts/${slug}`,
      ogImage:
        baseMetaData?.data.thumbnail &&
        `https://earthscience.kr/posts/${slug}/${baseMetaData.data.thumbnail}`,
    }),
  };
  return metadata;
}

3. 感想

普通は Facebook の共有デバッガーをよく使う。

しかし自分は Facebook アカウントがないので、単純にカカオトークでテストしてみた。

短所は、画像が表示されるまで少し時間がかかること。

Next.js の動的ルーティングでメタデータを生成する-3

最初は画像が表示されなかったが、翌日もう一度見てみるとちゃんと表示されていた。

一つずつ作り上げていくのが楽しいと感じる。

댓글을 불러오는 중...