Next.js と TypeScript で、Metadata APIを理解する

TwitterFacebookHatena

Next.js のメタデータの最適化について

Next.js 13.4 の App Router において 便利な Metadata API が使えるようになりました。これを使うことで、アプリケーションのメタデータ(例えば、HTML の head 要素内の meta タグや link タグ)を簡単に定義することができるんですね。SEO(検索エンジン最適化)が向上します。Pages Router に比べると、シンプルに記述できるようになりました。

メタデータをアプリケーションに追加する方法は主に 2 つあります。

設定ベースのメタデータ

layout.js ファイルや page.js ファイルで静的なメタデータオブジェクトをエクスポートするか、動的な generateMetadata 関数をエクスポートします。

ファイルベースのメタデータ

ルートセグメントに静的または動的に生成された特別なファイルを追加します。

これらのオプションを使用すると、Next.js は自動的にページのための適切な <head> 要素を生成します。また、ImageResponse コンストラクタを使用して、動的な OG(Open Graph)イメージを作成することも可能です。

主要な用語のまとめ

まずは、主要な用語を表形式でまとめてみました。今回は、Metadata API を中心に解説していきます。

用語 説明
Metadata API Next.js が提供する API で、アプリケーションのメタデータを定義するために使用します。
Config-based Metadata layout.js ファイルや page.js ファイルで静的なメタデータオブジェクトをエクスポートするか、動的な generateMetadata 関数をエクスポートする方法です。
File-based Metadata ルートセグメントに静的または動的に生成された特別なファイルを追加する方法です。
ImageResponse Next.js のコンストラクタで、JSX と CSS を使用して動的なイメージを生成するために使用します。OGP やアイキャッチ画像に最適。
Static Metadata layout.js ファイルや静的な page.js ファイルから Metadata オブジェクトをエクスポートします。
Dynamic Metadata generateMetadata 関数を使用して、動的な値が必要なメタデータを取得します。

ソースコードの解説

Building Your Application: Routing | Next.jsを参考に、ソースコードを紐解いていきます。

静的メタデータ

以下に示すのは、静的なメタデータを定義するためのコード例です。layout.js ファイルまたは page.js ファイルから Metadata オブジェクトをエクスポートします。この例では、特定のページ(例えば、ホームページ)のメタデータを設定しています。非常にシンプルになりましたね。

// app/layout.tsx
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'サイトのタイトル',
  description: 'サイトの説明',
  openGraph: {
    title: 'サイトのタイトル',
    description: 'サイトの説明',
    images: ['/path-to-your-image.jpg'],
  },
}

export default function HomePage() {
  // ここにコンテンツを記述します。
}

このコードは、ホームページのメタデータを設定します。タイトル、説明、Open Graph タグ(タイトル、説明、イメージ)を設定しています。

こちらは、OGP の設定例。非常にシンプルに記述できます。

export const metadata = {
  openGraph: {
    title: 'サイトのタイトル',
    description: 'サイトの説明',
    url: 'https://example.com',
    siteName: 'サイトのタイトル',
    images: [
      {
        url: 'https://example.com/og.png',
        width: 800,
        height: 600,
      },
      {
        url: 'https://example.com/og-alt.png',
        width: 1800,
        height: 1600,
        alt: '代替テキスト',
      },
    ],
    locale: 'en_US',
    type: 'website',
  },
}

title.template

結構便利だなと思ったのがこちらです。これは、ページの名前の前後に、追加の言葉をつけることができる機能のことです。

title.templateを使うと、子ルートで定義されたタイトルに接頭辞や接尾辞を追加できます。layout.js で定義された title.template は、同じルートの page.js で定義されたタイトルには適用されません。

// app/layout.tsx
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | タイトル',
  },
}
// app/about/page.tsx
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'About',
}

// 出力: <title>About | タイトル</title>

metadataBase

metadataBase は、基本 URL プレフィックスを設定する便利なオプションです。絶対 URL が必要なすべての URL ベースのメタデータフィールドは、metadataBase オプションで設定することができます。

// layout.js / page.js
export const metadata = {
  metadataBase: new URL('https://example.com'),
  alternates: {
    canonical: '/',
    languages: {
      'en-US': '/en-US',
      'de-DE': '/de-DE',
    },
  },
  openGraph: {
    images: '/og-image.png',
  },
}

出力結果はこのようになります。

<!-- <head> output -->
<link rel="canonical" href="https://example.com" />
<link rel="alternate" hreflang="en-US" href="https://nextjs.org/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://nextjs.org/de-DE" />
<meta property="og:image" content="https://example.com/og-image.png" />

参考:Functions: generateMetadata | Next.js

動的メタデータ

次に、動的な値が必要なメタデータを取得するためのコード例です。generateMetadata 関数を使用します。

以下に、generateMetadata関数を使用して動的なメタデータを生成する例です。この例では、ブログ記事のページを想定しています。記事の ID をパラメータとして受け取り、その ID を使用して記事のデータをフェッチします。フェッチしたデータから、メタデータのタイトルと説明を設定します。

import { Metadata, ResolvingMetadata } from 'next'

type Props = {
  params: { id: string }
}

export async function generateMetadata({ params }: Props, parent?: ResolvingMetadata): Promise<Metadata> {
  const id = params.id
  const post = await fetch(`https://your-api/posts/${id}`).then((res) => res.json())
  const previousImages = (await parent).openGraph?.images || []

  return {
    title: post.title,
    description: post.summary,
    openGraph: {
      images: ['/some-specific-page-image.jpg', ...previousImages],
    },
  }
}

export default function PostPage({ params }: Props) {}

このコードは、特定のブログ記事の情報を取得し、その情報を使用してメタデータを生成します。記事の情報は、記事の ID を使用してフェッチします。また、親のメタデータから Open Graph イメージを取得し、それを新たなメタデータに追加します。

Next.js と TypeScript で、Metadata APIを理解する