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

힘센캥거루
2024년 12월 16일
4
28

検索エンジン最適化のために 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

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

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

관련 글

Next.js フルスタックブログ開発記
Next.js フルスタックブログ開発記
Web開発に初めて触れてから1年ほど経った頃、自分だけのブログを持ちたいと思うようになった。そこで、およそ6か月これだけにかかりきりになって作ってみることにした。フロントエンド側の機能については、下記のキム・ドヒョンさんのブログを参考にするだけで十分だと思う。自分も mdx を使ってブログを作るだけ...
Caddyを利用した Next.js 無停止デプロイ(ローカルサーバー)
Caddyを利用した Next.js 無停止デプロイ(ローカルサーバー)
ホームページに何かをちょこちょこ載せたくなるたびにビルドしていたら、そのタイミング에 가끔 접속하는人がいるようだった。そうしているうちに、サーチコンソールでスコアがどんどん下がる現象が起きた。このままではまずいと思い、無停止デプロイをする方法を考えてみることにした。1. プロジェクトフォルダ2つ+...
Google検索インデックスの自動化 - Web Search Indexing API
Google検索インデックスの自動化 - Web Search Indexing API
前回の IndexNow に続いて、Google でも自動化してみることにした。調べてみると、Google は API として Web Search Indexing というものを提供していた。1. 対象範囲公式にこの API がサポートしている範囲は、求人情報とストリーミング動画サービスである。リ...
検索インデックス生成の自動化 - IndexNow
検索インデックス生成の自動化 - IndexNow
Bingにサイト登録をしている途中で知ったのだが、Bingでは IndexNow という機能を提供している。ポイントは、APIキーを使って、記事を書いた直後にすぐインデックス作成リクエストを飛ばせるということ。下のようなリクエストを fetch で作り、投稿機能に連動させておけば、記事をDBに保存す...
Nextjs、React サーバーがハッキングされた経験
Nextjs、React サーバーがハッキングされた経験
最初にセキュリティ問題に気づいたのは、12月5日の未明だった。React で認証なしにリモートコード実行が可能だということ。そのニュースを見て他の人には共有したものの、自分は大丈夫だろうと思って特に気にも留めなかった。1. ハッキングの痕跡を発見ところが、ブログのコードを更新しようとアクセスしてみる...
ブログに多言語機能を追加する(NextJS・next-intl・Vercel AI SDK)
ブログに多言語機能を追加する(NextJS・next-intl・Vercel AI SDK)
最近、ブログに多言語対応機能が必要だと感じた。そこで next-intl を使って多言語サービスを実装してみることにした。1.i18nまず多言語サービスを行うときには、守るべき原則がある。これを internationalization と呼ぶが、かなり長いので、先頭の i と末尾の n、そしてその...

댓글을 불러오는 중...