Metadaten
Next.js bietet eine Metadata API, mit der Sie Metadaten Ihrer Anwendung definieren können (z.B. meta
- und link
-Tags innerhalb des HTML-head
-Elements), um SEO und Web-Sharing-Fähigkeiten zu verbessern.
Es gibt zwei Möglichkeiten, Metadaten zu Ihrer Anwendung hinzuzufügen:
- Konfigurationsbasierte Metadaten: Exportieren eines statischen
metadata
-Objekts oder einer dynamischengenerateMetadata
-Funktion in einerlayout.js
- oderpage.js
-Datei. - Dateibasierte Metadaten: Hinzufügen statischer oder dynamisch generierter spezieller Dateien zu Routensegmenten.
Mit beiden Optionen generiert Next.js automatisch die relevanten <head>
-Elemente für Ihre Seiten. Sie können auch dynamische OG-Bilder mit dem ImageResponse
-Konstruktor erstellen.
Statische Metadaten
Um statische Metadaten zu definieren, exportieren Sie ein Metadata
-Objekt aus einer layout.js
- oder statischen page.js
-Datei.
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: '...',
description: '...',
}
export default function Page() {}
export const metadata = {
title: '...',
description: '...',
}
export default function Page() {}
Alle verfügbaren Optionen finden Sie in der API-Referenz.
Dynamische Metadaten
Sie können die generateMetadata
-Funktion verwenden, um Metadaten abzurufen, die dynamische Werte erfordern.
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> {
// Routenparameter lesen
const id = params.id
// Daten abrufen
const product = await fetch(`https://.../${id}`).then((res) => res.json())
// Optional übergeordnete Metadaten abrufen und erweitern (anstatt zu ersetzen)
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) {
// Routenparameter lesen
const id = params.id
// Daten abrufen
const product = await fetch(`https://.../${id}`).then((res) => res.json())
// Optional übergeordnete Metadaten abrufen und erweitern (anstatt zu ersetzen)
const previousImages = (await parent).openGraph?.images || []
return {
title: product.title,
openGraph: {
images: ['/some-specific-page-image.jpg', ...previousImages],
},
}
}
export default function Page({ params, searchParams }) {}
Alle verfügbaren Parameter finden Sie in der API-Referenz.
Gut zu wissen:
- Sowohl statische als auch dynamische Metadaten über
generateMetadata
werden nur in Server Components unterstützt.fetch
-Anfragen werden automatisch memoized für dieselben Daten übergenerateMetadata
,generateStaticParams
, Layouts, Seiten und Server Components hinweg. Reactcache
kann verwendet werden, fallsfetch
nicht verfügbar ist.- Next.js wartet, bis das Datenabrufen innerhalb von
generateMetadata
abgeschlossen ist, bevor die UI an den Client gestreamt wird. Dies stellt sicher, dass der erste Teil einer gestreamten Antwort die<head>
-Tags enthält.
Dateibasierte Metadaten
Diese speziellen Dateien sind für Metadaten verfügbar:
- favicon.ico, apple-icon.jpg und icon.jpg
- opengraph-image.jpg und twitter-image.jpg
- robots.txt
- sitemap.xml
Sie können diese für statische Metadaten verwenden oder die Dateien programmatisch mit Code generieren.
Für Implementierung und Beispiele siehe die Metadata Files API-Referenz und Dynamic Image Generation.
Verhalten
Dateibasierte Metadaten haben höhere Priorität und überschreiben alle konfigurationsbasierten Metadaten.
Standardfelder
Es gibt zwei standardmäßige meta
-Tags, die immer hinzugefügt werden, auch wenn eine Route keine Metadaten definiert:
- Das meta charset-Tag setzt die Zeichenkodierung der Website.
- Das meta viewport-Tag setzt die Viewport-Breite und Skalierung der Website für verschiedene Geräte.
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
Gut zu wissen: Sie können das standardmäßige
viewport
-Meta-Tag überschreiben.
Reihenfolge
Metadaten werden in Reihenfolge ausgewertet, beginnend beim Root-Segment bis zum Segment, das am nächsten zum finalen page.js
-Segment liegt. Beispiel:
app/layout.tsx
(Root-Layout)app/blog/layout.tsx
(Verschachteltes Blog-Layout)app/blog/[slug]/page.tsx
(Blog-Seite)
Zusammenführung
Gemäß der Auswertungsreihenfolge werden Metadata-Objekte, die aus mehreren Segmenten derselben Route exportiert werden, oberflächlich zusammengeführt, um die finalen Metadaten der Route zu bilden. Doppelte Schlüssel werden basierend auf ihrer Reihenfolge ersetzt.
Das bedeutet, dass Metadaten mit verschachtelten Feldern wie openGraph
und robots
, die in einem früheren Segment definiert wurden, durch das letzte Segment, das sie definiert, überschrieben werden.
Felder überschreiben
export const metadata = {
title: 'Acme',
openGraph: {
title: 'Acme',
description: 'Acme ist ein...',
},
}
export const metadata = {
title: 'Blog',
openGraph: {
title: 'Blog',
},
}
// Ausgabe:
// <title>Blog</title>
// <meta property="og:title" content="Blog" />
Im obigen Beispiel:
title
ausapp/layout.js
wird durchtitle
inapp/blog/page.js
ersetzt.- Alle
openGraph
-Felder ausapp/layout.js
werden inapp/blog/page.js
ersetzt, weilapp/blog/page.js
openGraph
-Metadaten setzt. Beachten Sie das Fehlen vonopenGraph.description
.
Wenn Sie einige verschachtelte Felder zwischen Segmenten teilen möchten, während Sie andere überschreiben, können Sie sie in eine separate Variable auslagern:
export const openGraphImage = { images: ['http://...'] }
import { openGraphImage } from './shared-metadata'
export const metadata = {
openGraph: {
...openGraphImage,
title: 'Startseite',
},
}
import { openGraphImage } from '../shared-metadata'
export const metadata = {
openGraph: {
...openGraphImage,
title: 'Über uns',
},
}
Im obigen Beispiel wird das OG-Bild zwischen app/layout.js
und app/about/page.js
geteilt, während die Titel unterschiedlich sind.
Felder vererben
export const metadata = {
title: 'Acme',
openGraph: {
title: 'Acme',
description: 'Acme ist ein...',
},
}
export const metadata = {
title: 'Über uns',
}
// Ausgabe:
// <title>Über uns</title>
// <meta property="og:title" content="Acme" />
// <meta property="og:description" content="Acme ist ein..." />
Hinweise
title
ausapp/layout.js
wird durchtitle
inapp/about/page.js
ersetzt.- Alle
openGraph
-Felder ausapp/layout.js
werden inapp/about/page.js
vererbt, weilapp/about/page.js
keineopenGraph
-Metadaten setzt.
Dynamische Bildgenerierung
Der ImageResponse
-Konstruktor ermöglicht die Generierung dynamischer Bilder mit JSX und CSS. Dies ist nützlich für die Erstellung von Social-Media-Bildern wie Open-Graph-Bilder, Twitter-Karten und mehr.
ImageResponse
verwendet die Edge Runtime, und Next.js fügt automatisch die korrekten Header für zwischengespeicherte Bilder am Edge hinzu, was die Leistung verbessert und Neuberechnungen reduziert.
Zur Verwendung können Sie ImageResponse
aus next/server
importieren:
import { ImageResponse } from 'next/server'
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',
}}
>
Hallo Welt!
</div>
),
{
width: 1200,
height: 600,
}
)
}
ImageResponse
integriert sich gut mit anderen Next.js-APIs, einschließlich Route Handlers und dateibasierten Metadaten. Beispielsweise können Sie ImageResponse
in einer opengraph-image.tsx
-Datei verwenden, um Open-Graph-Bilder zur Build-Zeit oder dynamisch zur Anfragezeit zu generieren.
ImageResponse
unterstützt gängige CSS-Eigenschaften, einschließlich Flexbox und absolute Positionierung, benutzerdefinierte Schriftarten, Textumbruch, Zentrierung und verschachtelte Bilder. Vollständige Liste der unterstützten CSS-Eigenschaften.
Gut zu wissen:
- Beispiele sind im Vercel OG Playground verfügbar.
ImageResponse
verwendet @vercel/og, Satori und Resvg, um HTML und CSS in PNG zu konvertieren.- Nur die Edge Runtime wird unterstützt. Die standardmäßige Node.js-Runtime funktioniert nicht.
- Nur Flexbox und eine Teilmenge der CSS-Eigenschaften werden unterstützt. Erweiterte Layouts (z.B.
display: grid
) funktionieren nicht.- Maximale Bundle-Größe von
500KB
. Die Bundle-Größe umfasst JSX, CSS, Schriftarten, Bilder und andere Assets. Bei Überschreitung sollten Sie die Größe der Assets reduzieren oder zur Laufzeit abrufen.- Nur
ttf
,otf
undwoff
Schriftformate werden unterstützt. Für maximale Geschwindigkeit bei der Schriftanalyse sindttf
oderotf
gegenüberwoff
bevorzugt.
JSON-LD
JSON-LD ist ein Format für strukturierte Daten, das von Suchmaschinen verwendet werden kann, um Ihren Inhalt zu verstehen. Beispielsweise können Sie es verwenden, um eine Person, ein Ereignis, eine Organisation, einen Film, ein Buch, ein Rezept und viele andere Entitätstypen zu beschreiben.
Unsere aktuelle Empfehlung für JSON-LD ist, strukturierte Daten als <script>
-Tag in Ihren layout.js
- oder page.js
-Komponenten zu rendern. Beispiel:
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>
{/* JSON-LD zur Seite hinzufügen */}
<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>
{/* JSON-LD zur Seite hinzufügen */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
{/* ... */}
</section>
)
}
Sie können Ihre strukturierten Daten mit dem Rich Results Test von Google oder dem generischen Schema Markup Validator validieren und testen.
Sie können JSON-LD mit TypeScript typisieren, indem Sie Community-Pakete wie schema-dts
verwenden:
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: 'Dynamisch mit der Geschwindigkeit von statisch.',
}