コンテンツにスキップ

メタデータ

Next.jsには、SEOとWeb共有性を向上させるために、アプリケーションのメタデータ(HTMLの`head`要素内の`meta`タグや`link`タグなど)を定義するために使用できるメタデータAPIがあります。

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

  • **設定ベースのメタデータ**:`layout.js`または`page.js`ファイルに、静的な`metadata`オブジェクト、または動的な`generateMetadata`関数をエクスポートします。
  • **ファイルベースのメタデータ**:静的または動的に生成された特別なファイルをルートセグメントに追加します。

これらのどちらのオプションでも、Next.jsはページに関連する`<head>`要素を自動的に生成します。また、`ImageResponse`コンストラクタを使用して、動的なOG画像を作成することもできます。

静的メタデータ

静的メタデータを定義するには、`layout.js`または静的な`page.js`ファイルから`Metadata`オブジェクトをエクスポートします。

layout.tsx | page.tsx
import type { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: '...',
  description: '...',
}
 
export default function Page() {}

使用可能なすべてのオプションについては、APIリファレンスを参照してください。

動的メタデータ

動的な値を必要とするメタデータを`fetch`するために、`generateMetadata`関数を使用できます。

app/products/[id]/page.tsx
import type { Metadata, ResolvingMetadata } from 'next'
 
type Props = {
  params: Promise<{ id: string }>
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
 
export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  // read route params
  const id = (await params).id
 
  // fetch data
  const product = await fetch(`https://.../${id}`).then((res) => res.json())
 
  // optionally access and extend (rather than replace) parent metadata
  const previousImages = (await parent).openGraph?.images || []
 
  return {
    title: product.title,
    openGraph: {
      images: ['/some-specific-page-image.jpg', ...previousImages],
    },
  }
}
 
export default function Page({ params, searchParams }: Props) {}

使用可能なすべてのパラメータについては、APIリファレンスを参照してください。

知っておくべきこと:

  • `generateMetadata`を介した静的および動的メタデータはどちらも、**サーバーコンポーネントでのみサポートされています**。
  • `fetch`リクエストは、`generateMetadata`、`generateStaticParams`、レイアウト、ページ、およびサーバーコンポーネント全体で同じデータに対して自動的にメモ化されます。`fetch`が使用できない場合は、Reactの`cache`を使用できます。
  • Next.jsは、クライアントにUIをストリーミングする前に、`generateMetadata`内のデータフェッチが完了するまで待機します。これにより、ストリーミングレスポンスの最初の部分に`<head>`タグが含まれていることが保証されます。

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

メタデータに使用できる特別なファイルは次のとおりです。

これらは静的メタデータに使用できます。また、コードを使用してこれらのファイルをプログラムで生成することもできます。

実装と例については、メタデータファイルAPIリファレンスと動的画像生成を参照してください。

挙動

ファイルベースのメタデータは優先度が高く、設定ベースのメタデータよりも優先されます。

デフォルトフィールド meta charsetタグは、ウェブサイトの文字エンコーディングを設定します。
  • meta viewportタグは、ウェブサイトのビューポートの幅とスケールを設定し、さまざまなデバイスに合わせて調整します。
  • <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    知っておくと良いこと:デフォルトのviewportメタタグは上書きできます。

    順序付け

    メタデータは、ルートセグメントから最終的なpage.jsセグメントに最も近いセグメントまで、順番に評価されます。例えば

    1. app/layout.tsx (ルートレイアウト)
    2. app/blog/layout.tsx (ネストされたブログレイアウト)
    3. app/blog/[slug]/page.tsx (ブログページ)

    マージ

    評価順序に従って、同じルート内の複数のセグメントからエクスポートされたメタデータオブジェクトは、ルートの最終的なメタデータ出力を形成するために、**浅く**マージされます。重複するキーは、順序に基づいて**置き換え**られます。

    これは、openGraphrobotsなど、ネストされたフィールドを持つメタデータが、それらを定義する最後のセグメントによって**上書き**されることを意味します。

    フィールドの上書き

    app/layout.js
    export const metadata = {
      title: 'Acme',
      openGraph: {
        title: 'Acme',
        description: 'Acme is a...',
      },
    }
    app/blog/page.js
    export const metadata = {
      title: 'Blog',
      openGraph: {
        title: 'Blog',
      },
    }
     
    // Output:
    // <title>Blog</title>
    // <meta property="og:title" content="Blog" />

    上記の例では

    • app/layout.jstitleは、app/blog/page.jstitleに**置き換え**られます。
    • app/blog/page.jsopenGraphメタデータを設定しているため、app/layout.jsのすべてのopenGraphフィールドはapp/blog/page.jsで**置き換え**られます。 openGraph.descriptionが存在しないことに注意してください。

    他のセグメントを上書きしながら、いくつかのネストされたフィールドをセグメント間で共有したい場合は、それらを別の変数に抽出できます。

    app/shared-metadata.js
    export const openGraphImage = { images: ['http://...'] }
    app/page.js
    import { openGraphImage } from './shared-metadata'
     
    export const metadata = {
      openGraph: {
        ...openGraphImage,
        title: 'Home',
      },
    }
    app/about/page.js
    import { openGraphImage } from '../shared-metadata'
     
    export const metadata = {
      openGraph: {
        ...openGraphImage,
        title: 'About',
      },
    }

    上記の例では、OG画像はapp/layout.jsapp/about/page.jsで共有されていますが、タイトルは異なります。

    フィールドの継承

    app/layout.js
    export const metadata = {
      title: 'Acme',
      openGraph: {
        title: 'Acme',
        description: 'Acme is a...',
      },
    }
    app/about/page.js
    export const metadata = {
      title: 'About',
    }
     
    // Output:
    // <title>About</title>
    // <meta property="og:title" content="Acme" />
    // <meta property="og:description" content="Acme is a..." />

    注記

    • app/layout.jsの`title`は、`app/about/page.js`の`title`に**置き換え**られます。
    • `app/about/page.js`は`openGraph`メタデータを設定していないため、`app/layout.js`のすべての`openGraph`フィールドは`app/about/page.js`で**継承**されます。

    動的画像生成

    ImageResponseコンストラクタを使用すると、JSXとCSSを使用して動的画像を生成できます。これは、Open Graph画像、Twitterカードなどのソーシャルメディア画像を作成するのに役立ちます。

    これを使用するには、`next/og`から`ImageResponse`をインポートします。

    app/about/route.js
    import { ImageResponse } from 'next/og'
     
    export async function GET() {
      return new ImageResponse(
        (
          <div
            style={{
              fontSize: 128,
              background: 'white',
              width: '100%',
              height: '100%',
              display: 'flex',
              textAlign: 'center',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            Hello world!
          </div>
        ),
        {
          width: 1200,
          height: 600,
        }
      )
    }

    ImageResponseは、ルートハンドラやファイルベースのメタデータなど、他のNext.js APIと適切に統合されています。たとえば、`opengraph-image.tsx`ファイルで`ImageResponse`を使用して、ビルド時またはリクエスト時に動的にOpen Graph画像を生成できます。

    ImageResponseは、フレックスボックスと絶対配置、カスタムフォント、テキストの折り返し、センタリング、ネストされた画像など、一般的なCSSプロパティをサポートしています。 サポートされているCSSプロパティの完全なリストをご覧ください

    知っておくべきこと:

    • Vercel OG Playgroundで例を確認できます。
    • ImageResponseは、@vercel/ogSatori、およびResvgを使用して、HTMLとCSSをPNGに変換します。
    • Edgeランタイムのみがサポートされています。デフォルトのNode.jsランタイムは機能しません。
    • フレックスボックスとCSSプロパティのサブセットのみがサポートされています。高度なレイアウト(例:`display:grid`)は機能しません。
    • 最大バンドルサイズは`500KB`です。バンドルサイズには、JSX、CSS、フォント、画像、その他のすべてのアセットが含まれます。制限を超えた場合は、アセットのサイズを削減するか、実行時にフェッチすることを検討してください。
    • `ttf`、`otf`、`woff`フォント形式のみがサポートされています。フォントの解析速度を最大化するには、`woff`よりも`ttf`または`otf`が推奨されます。

    JSON-LD

    JSON-LDは、検索エンジンがコンテンツを理解するために使用できる構造化データの形式です。たとえば、人物、イベント、組織、映画、本、レシピなど、さまざまな種類のエンティティを記述するために使用できます。

    JSON-LDに関する現在の推奨事項は、`layout.js`または`page.js`コンポーネントで構造化データを`<script>`タグとしてレンダリングすることです。例えば

    app/products/[id]/page.tsx
    export default async function Page({ params }) {
      const product = await getProduct(params.id)
     
      const jsonLd = {
        '@context': 'https://schema.org',
        '@type': 'Product',
        name: product.name,
        image: product.image,
        description: product.description,
      }
     
      return (
        <section>
          {/* Add JSON-LD to your page */}
          <script
            type="application/ld+json"
            dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
          />
          {/* ... */}
        </section>
      )
    }

    Googleのリッチリザルトテストまたは汎用のスキーママークアップバリデータを使用して、構造化データを検証およびテストできます。

    schema-dtsのようなコミュニティパッケージを使用して、TypeScriptでJSON-LDを入力できます。

    import { Product, WithContext } from 'schema-dts'
     
    const jsonLd: WithContext<Product> = {
      '@context': 'https://schema.org',
      '@type': 'Product',
      name: 'Next.js Sticker',
      image: 'https://nextjs.dokyumento.jp/imgs/sticker.png',
      description: 'Dynamic at the speed of static.',
    }