Metadata
Next.js は、あなたのアプリケーションの metadata (例えば、meta
やlink
タグをあなたの 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 します。
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: '...',
description: '...',
}
export default function Page() {}
export const metadata = {
title: '...',
description: '...',
}
export default function Page() {}
すべての利用可能な options については、API Reference を参照してください。
Dynamic Metadata
generateMetadata
関数を使用して、fetch
する必要がある metadata が dynamic な値を要求します。
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) {}
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
の要求は、generateMetadata
、generateStaticParams
、Layout、ページ、そして Server Components に跨って同じデータに対して自動的にメモ化されます。fetch
が利用できない場合、React のcache
を使用することができます。- Next.js は、UI を client に Streaming する前に、
generateMetadata
内でのデータフェッチが完了するのを待ちます。これにより、Streaming された response の最初の部分が<head>
タグを含むことが保証されます。
File-based metadata
これらの特別なファイルは metadata のために利用可能です:
- favicon.ico、apple-icon.jpg、そして icon.jpg
- opengraph-image.jpg と twitter-image.jpg
- robots.txt
- sitemap.xml
これらは静的な 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
セグメントに最も近いセグメントまでの順番で評価されます。例えば:
app/layout.tsx
(Root Layout)app/blog/layout.tsx
(ネストされたブログ Layout)app/blog/[slug]/page.tsx
(ブログページ)
Merging
評価順序に従って、同じ route 内の複数のセグメントから export された MetadataObject は、浅く最終的な route の metadata 出力を形成するためにマージされます。重複するキーはそれらの順序に基づいて置換されます。
これは、以前のセグメントで定義された openGraph
や robots
などのネストされたフィールドを持つ metadata を意味します。それらは最後のセグメントで定義することにより上書きされます。
フィールドの上書き
export const metadata = {
title: 'Acme',
openGraph: {
title: 'Acme',
description: 'Acme is a...',
},
}
export const metadata = {
title: 'Blog',
openGraph: {
title: 'Blog',
},
}
// Output:
// <title>Blog</title>
// <meta property="og:title" content="Blog" />
上記の例では:
app/layout.js
のtitle
は、app/blog/page.js
のtitle
に置き換えられます。- すべての
openGraph
フィールドは、app/layout.js
からapp/blog/page.js
に置き換えられます。なぜならapp/blog/page.js
はopenGraph
metadata を設定するからです。openGraph.description
の欠如に注意してください。
あるセグメント間でネストしたフィールドの一部を共有しながら、他のフィールドを上書きしたい場合、それらを別の variable に引き出すことができます。
export const openGraphImage = { images: ['http://...'] }
import { openGraphImage } from './shared-metadata'
export const metadata = {
openGraph: {
...openGraphImage,
title: 'Home',
},
}
import { openGraphImage } from '../shared-metadata'
export const metadata = {
openGraph: {
...openGraphImage,
title: 'About',
},
}
上記の例では、OG の image はapp/layout.js
とapp/about/page.js
で共有されていますが、タイトルは異なります。
フィールドを継承する
export const metadata = {
title: 'Acme',
openGraph: {
title: 'Acme',
description: 'Acme is a...',
},
}
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.js
のtitle
はapp/about/page.js
のtitle
に置き換えられます。- すべての
openGraph
フィールドは、app/layout.js
から 継承 されてapp/about/page.js
に存在します。なぜなら、app/about/page.js
はopenGraph
metadata を設定していないからです。
Dynamic Image Generation
ImageResponse
コンストラクタは、JSX と CSS を使用して dynamic な画像を生成することができます。これは、Open Graph の画像や、Twitter カードなどのソーシャルメディア画像を作成するのに便利です。
ImageResponse
は Edge Runtime を使用し、Next.js は自動的にキャッシュされた画像に適切な headers を追加し、edge でのパフォーマンスを向上させ再計算を減らします。
それを使用するには、next/og
からImageResponse
を import することができます。
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 で取得することを検討してください。- ただし、
ttf
、otf
、woff
といったフォントの formats のみがサポートされています。フォントの解析速度を最大化するために、woff
よりもttf
またはotf
が優先されます。
JSON-LD
JSON-LD は、検索エンジンがあなたのコンテンツを理解するために使用できる構造化データのフォーマットです。例えば、それを使って人物、イベント、組織、映画、書籍、レシピなど、さまざまな種類のエンティティを説明することができます。
現在、JSON-LD に対する私たちの推奨方針は、layout.js
またはpage.js
Component で構造化データを<script>
タグとして render することです。例えば:
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>
)
}
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.",
};