Lang x Lang

Metadata

Next.js は、あなたのアプリケーションの metadata (例えば、metalinkタグをあなたの HTML のhead要素内に定義する)を設定するために使用できる Metadata API を持っており、 SEO の改善とウェブの共有性を向上させます。

アプリケーションに metadata を追加する方法は 2 つあります:

  • 設定ベースの Metadata静的な metadata object または dynamic の generateMetadata 関数layout.jsまたはpage.jsファイルに Export します。
  • **ファイルベースの Metadata **: スタティックまたは動的に生成される特別なファイルを route セグメントに追加します。

これらの options、Next.js を使用すると、自動的にページに対応する<head>要素が生成されます。また、ImageResponse コンストラクタを使って dynamic な OG 画像を作成することもできます。

Static Metadata

静的な metadata を定義するには、layout.jsまたは静的なpage.jsファイルから Metadata object を export します。

layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: '...',
  description: '...',
}

export default function Page() {}
layout.js
export const metadata = {
  title: '...',
  description: '...',
}

export default function Page() {}

すべての利用可能な options については、API Reference を参照してください。

Dynamic Metadata

generateMetadata関数を使用して、fetchする必要がある metadata が dynamic な値を要求します。

app/products/[id]/page.tsx
import type { Metadata, ResolvingMetadata } from 'next'

type Props = {
  params: { id: string }
  searchParams: { [key: string]: string | string[] | undefined }
}

export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  // read route params
  const id = 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) {}
app/products/[id]/page.js
export async function generateMetadata({ params, searchParams }, parent) {
  // read route params
  const id = 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 }) {}

すべての使用可能な params については、API Reference をご覧ください。

Good to know:

  • 静的と dynamic metadata を通じてのgenerateMetadataは、Server Componentsでのみサポートされています。
  • fetchの要求は、generateMetadatagenerateStaticParams、Layout、ページ、そして Server Components に跨って同じデータに対して自動的にメモ化されます。fetchが利用できない場合、React のcacheを使用することができます
  • Next.js は、UI を client に Streaming する前に、generateMetadata内でのデータフェッチが完了するのを待ちます。これにより、Streaming された response の最初の部分が<head>タグを含むことが保証されます。

File-based metadata

これらの特別なファイルは metadata のために利用可能です:

これらは静的な metadata として使用することも、code でこれらのファイルをプログラム的に生成することもできます。

実装と例については、Metadata Files API Reference およびDynamic Image Generation を参照してください。

Behavior

ファイルベースの metadata は、より高い priority を持ち、任意の config ベースの metadata を上書きします。

Default フィールド

metadata を定義しない route であっても、常に追加される二つの default metaタグがあります:

  • meta charset tag は、ウェブサイトの文字エンコーディングを設定します。
  • meta viewport tag はウェブサイトがさまざまなデバイスに対応できるように、viewport width とスケールを設定します。
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

Good to know: default の viewport の meta タグを上書きすることができます。

Ordering

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

  1. app/layout.tsx (Root Layout)
  2. app/blog/layout.tsx(ネストされたブログ Layout)
  3. app/blog/[slug]/page.tsx (ブログページ)

Merging

評価順序に従って、同じ route 内の複数のセグメントから export された MetadataObject は、浅く最終的な route の metadata 出力を形成するためにマージされます。重複するキーはそれらの順序に基づいて置換されます。

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

フィールドの上書き

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置き換えられます
  • すべての openGraph フィールドは、app/layout.js から app/blog/page.js置き換えられます。なぜなら app/blog/page.jsopenGraph metadata を設定するからです。 openGraph.description の欠如に注意してください。

あるセグメント間でネストしたフィールドの一部を共有しながら、他のフィールドを上書きしたい場合、それらを別の variable に引き出すことができます。

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 の image は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..." />

Notes

  • app/layout.jstitleapp/about/page.jstitle置き換えられます
  • すべての openGraph フィールドは、app/layout.js から 継承 されて app/about/page.js に存在します。なぜなら、app/about/page.jsopenGraph metadata を設定していないからです。

Dynamic Image Generation

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

ImageResponseEdge Runtime を使用し、Next.js は自動的にキャッシュされた画像に適切な headers を追加し、edge でのパフォーマンスを向上させ再計算を減らします。

それを使用するには、next/ogからImageResponseを import することができます。

app/about/route.js
import { ImageResponse } from 'next/og'

export const runtime = 'edge'

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、Route Handlers やファイルベースの Metadata とよく統合されます。例えば、 opengraph-image.tsx ファイルで ImageResponseを使用して、 Open Graph の画像を build 時または動的に request 時に生成することができます。

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

Good to know:

  • 例は、Vercel OG Playground で利用できます。
  • ImageResponse@vercel/og Satori 、そして Resvg を使用して、HTML と CSS を PNG に変換します。
  • Edge Runtime のみがサポートされます。default Node.js runtime は機能しません。
  • Flexbox と CSS プロパティの一部のみがサポートされています。高度な Layout(例えば、display: grid)は機能しません。
  • 500KBの最大バンドル size。バンドルの size には、あなたの JSX、CSS、フォント、画像、およびその他のアセットが含まれます。これを超える場合は、任意のアセットの size を減らすか、runtime で取得することを検討してください。
  • ただし、ttfotfwoffといったフォントの formats のみがサポートされています。フォントの解析速度を最大化するために、woffよりもttfまたはotfが優先されます。

JSON-LD

JSON-LD は、検索エンジンがあなたのコンテンツを理解するために使用できる構造化データのフォーマットです。例えば、それを使って人物、イベント、組織、映画、書籍、レシピなど、さまざまな種類のエンティティを説明することができます。

現在、JSON-LD に対する私たちの推奨方針は、layout.jsまたはpage.jsComponent で構造化データを<script>タグとして render することです。例えば:

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>
  )
}
app/products/[id]/page.js
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>
  )
}

Rich Results Test で Google の構造化データを検証し、test することができます。また、汎用の Schema Markup Validator も利用できます。

あなたは、schema-dts のようなコミュニティパッケージを使用して、JSON-LD を TypeScript で type することができます:

import { Product, WithContext } from "schema-dts";

const jsonLd: WithContext<Product> = {
  "@context": "https://schema.org",
  "@type": "Product",
  name: "Next.js Sticker",
  image: "https://nextjs.org/imgs/sticker.png",
  description: "Dynamic at the speed of static.",
};

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use