generateMetadata

Sie können das metadata-Objekt oder die generateMetadata-Funktion verwenden, um Metadaten zu definieren.

Das metadata-Objekt

Um statische Metadaten zu definieren, exportieren Sie ein Metadata-Objekt aus einer layout.js- oder page.js-Datei.

import type { Metadata } from 'next'

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

export default function Page() {}

Siehe Metadata-Felder für eine vollständige Liste der unterstützten Optionen.

generateMetadata-Funktion

Dynamische Metadaten, die von dynamischen Informationen abhängen, wie z.B. den aktuellen Routenparametern, externen Daten oder metadata in übergeordneten Segmenten, können durch Exportieren einer generateMetadata-Funktion definiert werden, die ein Metadata-Objekt zurückgibt.

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> {
  // Routenparameter lesen
  const { id } = await params

  // Daten abrufen
  const product = await fetch(`https://.../${id}`).then((res) => res.json())

  // Optional auf übergeordnete Metadaten zugreifen 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) {}

Gut zu wissen:

  • Metadaten können zu layout.js- und page.js-Dateien hinzugefügt werden.
  • Next.js löst die Metadaten automatisch auf und erstellt die relevanten <head>-Tags für die Seite.
  • Die Exporte des metadata-Objekts und der generateMetadata-Funktion werden nur in Server Components unterstützt.
  • Sie können nicht sowohl das metadata-Objekt als auch die generateMetadata-Funktion aus demselben Routensegment exportieren.
  • fetch-Anfragen innerhalb von generateMetadata werden automatisch memoized für dieselben Daten über generateMetadata, generateStaticParams, Layouts, Pages und Server Components hinweg.
  • React cache kann verwendet werden, falls fetch nicht verfügbar ist.
  • Dateibasierte Metadaten haben eine höhere Priorität und überschreiben das metadata-Objekt und die generateMetadata-Funktion.

Referenz

Parameter

Die generateMetadata-Funktion akzeptiert folgende Parameter:

  • props - Ein Objekt mit den Parametern der aktuellen Route:

    • params - Ein Objekt mit den dynamischen Routenparametern vom Wurzelsegment bis zu dem Segment, aus dem generateMetadata aufgerufen wird. Beispiele:

      RouteURLparams
      app/shop/[slug]/page.js/shop/1{ slug: '1' }
      app/shop/[tag]/[item]/page.js/shop/1/2{ tag: '1', item: '2' }
      app/shop/[...slug]/page.js/shop/1/2{ slug: ['1', '2'] }
    • searchParams - Ein Objekt mit den Suchparametern der aktuellen URL. Beispiele:

      URLsearchParams
      /shop?a=1{ a: '1' }
      /shop?a=1&b=2{ a: '1', b: '2' }
      /shop?a=1&a=2{ a: ['1', '2'] }
  • parent - Ein Promise der aufgelösten Metadaten aus übergeordneten Routensegmenten.

Rückgabewert

generateMetadata sollte ein Metadata-Objekt zurückgeben, das ein oder mehrere Metadatenfelder enthält.

Gut zu wissen:

  • Wenn Metadaten nicht von Laufzeitinformationen abhängen, sollten sie mit dem statischen metadata-Objekt anstelle von generateMetadata definiert werden.
  • fetch-Anfragen werden automatisch memoized für dieselben Daten über generateMetadata, generateStaticParams, Layouts, Pages und Server Components hinweg. React cache kann verwendet werden, falls fetch nicht verfügbar ist.
  • searchParams sind nur in page.js-Segmenten verfügbar.
  • Die Next.js-Methoden redirect() und notFound() können auch innerhalb von generateMetadata verwendet werden.

Metadata-Felder

Die folgenden Felder werden unterstützt:

title

Das title-Attribut wird verwendet, um den Titel des Dokuments festzulegen. Es kann als einfache Zeichenkette oder als optionales Template-Objekt definiert werden.

Zeichenkette
layout.js | page.js
export const metadata = {
  title: 'Next.js',
}
<head> output
<title>Next.js</title>
default

title.default kann verwendet werden, um einen Fallback-Titel für untergeordnete Routensegmente bereitzustellen, die keinen title definieren.

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

export const metadata: Metadata = {
  title: {
    default: 'Acme',
  },
}
app/about/page.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {}

// Ausgabe: <title>Acme</title>
template

title.template kann verwendet werden, um ein Präfix oder Suffix zu titles hinzuzufügen, die in untergeordneten Routensegmenten definiert sind.

import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | Acme',
    default: 'Acme', // ein Default ist erforderlich, wenn ein Template erstellt wird
  },
}

Gut zu wissen:

  • title.template gilt für untergeordnete Routensegmente und nicht für das Segment, in dem es definiert ist. Das bedeutet:

    • title.default ist erforderlich, wenn Sie ein title.template hinzufügen.
    • title.template, das in layout.js definiert ist, gilt nicht für einen title, der in einer page.js desselben Routensegments definiert ist.
    • title.template, das in page.js definiert ist, hat keine Wirkung, da eine Seite immer das abschließende Segment ist (sie hat keine untergeordneten Routensegmente).
  • title.template hat keine Wirkung, wenn eine Route keinen title oder title.default definiert hat.

absolute

title.absolute kann verwendet werden, um einen Titel bereitzustellen, der title.template aus übergeordneten Segmenten ignoriert.

import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | Acme',
  },
}

Gut zu wissen:

  • layout.js

    • title (Zeichenkette) und title.default definieren den Standardtitel für untergeordnete Segmente (die keinen eigenen title definieren). Es wird title.template aus dem nächstgelegenen übergeordneten Segment ergänzen, falls vorhanden.
    • title.absolute definiert den Standardtitel für untergeordnete Segmente. Es ignoriert title.template aus übergeordneten Segmenten.
    • title.template definiert eine neue Titelvorlage für untergeordnete Segmente.
  • page.js

    • Wenn eine Seite keinen eigenen Titel definiert, wird der aufgelöste Titel des nächstgelegenen übergeordneten Elements verwendet.
    • title (Zeichenkette) definiert den Titel der Route. Es wird title.template aus dem nächstgelegenen übergeordneten Segment ergänzen, falls vorhanden.
    • title.absolute definiert den Titel der Route. Es ignoriert title.template aus übergeordneten Segmenten.
    • title.template hat in page.js keine Wirkung, da eine Seite immer das abschließende Segment einer Route ist.

description

layout.js | page.js
export const metadata = {
  description: 'The React Framework for the Web',
}
<head> output
<meta name="description" content="The React Framework for the Web" />

Andere Felder

layout.js | page.js
export const metadata = {
  generator: 'Next.js',
  applicationName: 'Next.js',
  referrer: 'origin-when-cross-origin',
  keywords: ['Next.js', 'React', 'JavaScript'],
  authors: [{ name: 'Seb' }, { name: 'Josh', url: 'https://nextjs.org' }],
  creator: 'Jiachi Liu',
  publisher: 'Sebastian Markbåge',
  formatDetection: {
    email: false,
    address: false,
    telephone: false,
  },
}
<head> output
<meta name="application-name" content="Next.js" />
<meta name="author" content="Seb" />
<link rel="author" href="https://nextjs.org" />
<meta name="author" content="Josh" />
<meta name="generator" content="Next.js" />
<meta name="keywords" content="Next.js,React,JavaScript" />
<meta name="referrer" content="origin-when-cross-origin" />
<meta name="color-scheme" content="dark" />
<meta name="creator" content="Jiachi Liu" />
<meta name="publisher" content="Sebastian Markbåge" />
<meta name="format-detection" content="telephone=no, address=no, email=no" />

metadataBase

metadataBase ist eine praktische Option, um einen Basis-URL-Präfix für metadata-Felder festzulegen, die eine vollständig qualifizierte URL erfordern.

  • metadataBase ermöglicht es URL-basierten metadata-Feldern, die im aktuellen Routensegment und darunter definiert sind, einen relativen Pfad anstelle einer ansonsten erforderlichen absoluten URL zu verwenden.
  • Der relative Pfad des Felds wird mit metadataBase kombiniert, um eine vollständig qualifizierte URL zu bilden.
layout.js | page.js
export const metadata = {
  metadataBase: new URL('https://acme.com'),
  alternates: {
    canonical: '/',
    languages: {
      'en-US': '/en-US',
      'de-DE': '/de-DE',
    },
  },
  openGraph: {
    images: '/og-image.png',
  },
}
<head> output
<link rel="canonical" href="https://acme.com" />
<link rel="alternate" hreflang="en-US" href="https://acme.com/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://acme.com/de-DE" />
<meta property="og:image" content="https://acme.com/og-image.png" />

Gut zu wissen:

  • metadataBase wird typischerweise in der root app/layout.js gesetzt, um auf URL-basierte metadata-Felder über alle Routen hinweg anzuwenden.
  • Alle URL-basierten metadata-Felder, die absolute URLs erfordern, können mit einer metadataBase-Option konfiguriert werden.
  • metadataBase kann eine Subdomain enthalten, z.B. https://app.acme.com oder einen Basispfad, z.B. https://acme.com/start/from/here
  • Wenn ein metadata-Feld eine absolute URL bereitstellt, wird metadataBase ignoriert.
  • Die Verwendung eines relativen Pfads in einem URL-basierten metadata-Feld ohne Konfiguration einer metadataBase führt zu einem Build-Fehler.
  • Next.js normalisiert doppelte Schrägstriche zwischen metadataBase (z.B. https://acme.com/) und einem relativen Feld (z.B. /path) zu einem einfachen Schrägstrich (z.B. https://acme.com/path)

URL-Zusammensetzung

Die URL-Zusammensetzung bevorzugt die Absicht des Entwicklers gegenüber der Standard-Semantik der Verzeichnistraversierung.

  • Schrägstriche zwischen metadataBase und metadata-Feldern werden normalisiert.
  • Ein "absoluter" Pfad in einem metadata-Feld (der normalerweise den gesamten URL-Pfad ersetzen würde) wird als "relativer" Pfad behandelt (beginnend vom Ende von metadataBase).

Beispielsweise mit der folgenden metadataBase:

import type { Metadata } from 'next'

export const metadata: Metadata = {
  metadataBase: new URL('https://acme.com'),
}

Jedes metadata-Feld, das die obige metadataBase erbt und seinen eigenen Wert setzt, wird wie folgt aufgelöst:

metadata-FeldAufgelöste URL
/https://acme.com
./https://acme.com
paymentshttps://acme.com/payments
/paymentshttps://acme.com/payments
./paymentshttps://acme.com/payments
../paymentshttps://acme.com/payments
https://beta.acme.com/paymentshttps://beta.acme.com/payments

openGraph

layout.js | page.js
export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'Das React-Framework für das Web',
    url: 'https://nextjs.org',
    siteName: 'Next.js',
    images: [
      {
        url: 'https://nextjs.org/og.png', // Muss eine absolute URL sein
        width: 800,
        height: 600,
      },
      {
        url: 'https://nextjs.org/og-alt.png', // Muss eine absolute URL sein
        width: 1800,
        height: 1600,
        alt: 'Mein benutzerdefinierter Alt-Text',
      },
    ],
    videos: [
      {
        url: 'https://nextjs.org/video.mp4', // Muss eine absolute URL sein
        width: 800,
        height: 600,
      },
    ],
    audio: [
      {
        url: 'https://nextjs.org/audio.mp3', // Muss eine absolute URL sein
      },
    ],
    locale: 'en_US',
    type: 'website',
  },
}
<head> output
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="Das React-Framework für das Web" />
<meta property="og:url" content="https://nextjs.org/" />
<meta property="og:site_name" content="Next.js" />
<meta property="og:locale" content="en_US" />
<meta property="og:image" content="https://nextjs.org/og.png" />
<meta property="og:image:width" content="800" />
<meta property="og:image:height" content="600" />
<meta property="og:image" content="https://nextjs.org/og-alt.png" />
<meta property="og:image:width" content="1800" />
<meta property="og:image:height" content="1600" />
<meta property="og:image:alt" content="Mein benutzerdefinierter Alt-Text" />
<meta property="og:video" content="https://nextjs.org/video.mp4" />
<meta property="og:video:width" content="800" />
<meta property="og:video:height" content="600" />
<meta property="og:audio" content="https://nextjs.org/audio.mp3" />
<meta property="og:type" content="website" />
layout.js | page.js
export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'Das React-Framework für das Web',
    type: 'article',
    publishedTime: '2023-01-01T00:00:00.000Z',
    authors: ['Seb', 'Josh'],
  },
}
<head> output
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="Das React-Framework für das Web" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2023-01-01T00:00:00.000Z" />
<meta property="article:author" content="Seb" />
<meta property="article:author" content="Josh" />

Gut zu wissen:

  • Es kann praktischer sein, die dateibasierte Metadata API für Open-Graph-Bilder zu verwenden. Anstatt die Konfiguration mit den tatsächlichen Dateien synchron halten zu müssen, generiert die dateibasierte API automatisch die korrekten Metadaten für Sie.

robots

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

export const metadata: Metadata = {
  robots: {
    index: true,
    follow: true,
    nocache: false,
    googleBot: {
      index: true,
      follow: true,
      noimageindex: false,
      'max-video-preview': -1,
      'max-image-preview': 'large',
      'max-snippet': -1,
    },
  },
}
<head> output
<meta name="robots" content="index, follow" />
<meta
  name="googlebot"
  content="index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1"
/>

icons

Gut zu wissen: Wir empfehlen die Verwendung der dateibasierten Metadata API für Icons, wo möglich. Anstatt die Konfiguration mit den tatsächlichen Dateien synchron halten zu müssen, generiert die dateibasierte API automatisch die korrekten Metadaten für Sie.

layout.js | page.js
export const metadata = {
  icons: {
    icon: '/icon.png',
    shortcut: '/shortcut-icon.png',
    apple: '/apple-icon.png',
    other: {
      rel: 'apple-touch-icon-precomposed',
      url: '/apple-touch-icon-precomposed.png',
    },
  },
}
<head> output
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
  rel="apple-touch-icon-precomposed"
  href="/apple-touch-icon-precomposed.png"
/>
layout.js | page.js
export const metadata = {
  icons: {
    icon: [
      { url: '/icon.png' },
      new URL('/icon.png', 'https://example.com'),
      { url: '/icon-dark.png', media: '(prefers-color-scheme: dark)' },
    ],
    shortcut: ['/shortcut-icon.png'],
    apple: [
      { url: '/apple-icon.png' },
      { url: '/apple-icon-x3.png', sizes: '180x180', type: 'image/png' },
    ],
    other: [
      {
        rel: 'apple-touch-icon-precomposed',
        url: '/apple-touch-icon-precomposed.png',
      },
    ],
  },
}
<head> output
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="icon" href="https://example.com/icon.png" />
<link rel="icon" href="/icon-dark.png" media="(prefers-color-scheme: dark)" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
  rel="apple-touch-icon-precomposed"
  href="/apple-touch-icon-precomposed.png"
/>
<link
  rel="apple-touch-icon"
  href="/apple-icon-x3.png"
  sizes="180x180"
  type="image/png"
/>

Gut zu wissen: Die msapplication-* Meta-Tags werden in Chromium-basierten Versionen von Microsoft Edge nicht mehr unterstützt und sind daher nicht mehr notwendig.

themeColor

Veraltet: Die themeColor-Option in metadata ist seit Next.js 14 veraltet. Bitte verwenden Sie stattdessen die viewport-Konfiguration.

colorScheme

Veraltet: Die colorScheme-Option in metadata ist seit Next.js 14 veraltet. Bitte verwenden Sie stattdessen die viewport-Konfiguration.

manifest

Ein Web-App-Manifest, wie in der Web Application Manifest-Spezifikation definiert.

layout.js | page.js
export const metadata = {
  manifest: 'https://nextjs.org/manifest.json',
}
<head> output
<link rel="manifest" href="https://nextjs.org/manifest.json" />

twitter

Die Twitter-Spezifikation wird (überraschenderweise) für mehr als nur X (ehemals bekannt als Twitter) verwendet.

Mehr erfahren über die Twitter Card Markup-Referenz.

layout.js | page.js
export const metadata = {
  twitter: {
    card: 'summary_large_image',
    title: 'Next.js',
    description: 'Das React-Framework für das Web',
    siteId: '1467726470533754880',
    creator: '@nextjs',
    creatorId: '1467726470533754880',
    images: ['https://nextjs.org/og.png'], // Muss eine absolute URL sein
  },
}
<head> output
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="Das React-Framework für das Web" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
layout.js | page.js
export const metadata = {
  twitter: {
    card: 'app',
    title: 'Next.js',
    description: 'Das React-Framework für das Web',
    siteId: '1467726470533754880',
    creator: '@nextjs',
    creatorId: '1467726470533754880',
    images: {
      url: 'https://nextjs.org/og.png',
      alt: 'Next.js Logo',
    },
    app: {
      name: 'twitter_app',
      id: {
        iphone: 'twitter_app://iphone',
        ipad: 'twitter_app://ipad',
        googleplay: 'twitter_app://googleplay',
      },
      url: {
        iphone: 'https://iphone_url',
        ipad: 'https://ipad_url',
      },
    },
  },
}
<head> output
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="Das React-Framework für das Web" />
<meta name="twitter:card" content="app" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
<meta name="twitter:image:alt" content="Next.js Logo" />
<meta name="twitter:app:name:iphone" content="twitter_app" />
<meta name="twitter:app:id:iphone" content="twitter_app://iphone" />
<meta name="twitter:app:id:ipad" content="twitter_app://ipad" />
<meta name="twitter:app:id:googleplay" content="twitter_app://googleplay" />
<meta name="twitter:app:url:iphone" content="https://iphone_url" />
<meta name="twitter:app:url:ipad" content="https://ipad_url" />
<meta name="twitter:app:name:ipad" content="twitter_app" />
<meta name="twitter:app:name:googleplay" content="twitter_app" />

viewport

Veraltet: Die viewport-Option in metadata ist seit Next.js 14 veraltet. Bitte verwenden Sie stattdessen die viewport-Konfiguration.

verification

layout.js | page.js
export const metadata = {
  verification: {
    google: 'google',
    yandex: 'yandex',
    yahoo: 'yahoo',
    other: {
      me: ['my-email', 'my-link'],
    },
  },
}
<head> output
<meta name="google-site-verification" content="google" />
<meta name="y_key" content="yahoo" />
<meta name="yandex-verification" content="yandex" />
<meta name="me" content="my-email" />
<meta name="me" content="my-link" />

appleWebApp

layout.js | page.js
export const metadata = {
  itunes: {
    appId: 'myAppStoreID',
    appArgument: 'myAppArgument',
  },
  appleWebApp: {
    title: 'Apple Web App',
    statusBarStyle: 'black-translucent',
    startupImage: [
      '/assets/startup/apple-touch-startup-image-768x1004.png',
      {
        url: '/assets/startup/apple-touch-startup-image-1536x2008.png',
        media: '(device-width: 768px) and (device-height: 1024px)',
      },
    ],
  },
}
<head> output
<meta
  name="apple-itunes-app"
  content="app-id=myAppStoreID, app-argument=myAppArgument"
/>
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Apple Web App" />
<link
  href="/assets/startup/apple-touch-startup-image-768x1004.png"
  rel="apple-touch-startup-image"
/>
<link
  href="/assets/startup/apple-touch-startup-image-1536x2008.png"
  media="(device-width: 768px) and (device-height: 1024px)"
  rel="apple-touch-startup-image"
/>
<meta
  name="apple-mobile-web-app-status-bar-style"
  content="black-translucent"
/>

alternates

layout.js | page.js
export const metadata = {
  alternates: {
    canonical: 'https://nextjs.org',
    languages: {
      'en-US': 'https://nextjs.org/en-US',
      'de-DE': 'https://nextjs.org/de-DE',
    },
    media: {
      'only screen and (max-width: 600px)': 'https://nextjs.org/mobile',
    },
    types: {
      'application/rss+xml': 'https://nextjs.org/rss',
    },
  },
}
<head> output
<link rel="canonical" href="https://nextjs.org" />
<link rel="alternate" hreflang="en-US" href="https://nextjs.org/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://nextjs.org/de-DE" />
<link
  rel="alternate"
  media="only screen and (max-width: 600px)"
  href="https://nextjs.org/mobile"
/>
<link
  rel="alternate"
  type="application/rss+xml"
  href="https://nextjs.org/rss"
/>
layout.js | page.js
export const metadata = {
  appLinks: {
    ios: {
      url: 'https://nextjs.org/ios',
      app_store_id: 'app_store_id',
    },
    android: {
      package: 'com.example.android/package',
      app_name: 'app_name_android',
    },
    web: {
      url: 'https://nextjs.org/web',
      should_fallback: true,
    },
  },
}
<head> output
<meta property="al:ios:url" content="https://nextjs.org/ios" />
<meta property="al:ios:app_store_id" content="app_store_id" />
<meta property="al:android:package" content="com.example.android/package" />
<meta property="al:android:app_name" content="app_name_android" />
<meta property="al:web:url" content="https://nextjs.org/web" />
<meta property="al:web:should_fallback" content="true" />

archives

Beschreibt eine Sammlung von Aufzeichnungen, Dokumenten oder anderen Materialien von historischem Interesse (Quelle).

layout.js | page.js
export const metadata = {
  archives: ['https://nextjs.org/13'],
}
<head> output
<link rel="archives" href="https://nextjs.org/13" />

assets

layout.js | page.js
export const metadata = {
  assets: ['https://nextjs.org/assets'],
}
<head> output
<link rel="assets" href="https://nextjs.org/assets" />

bookmarks

layout.js | page.js
export const metadata = {
  bookmarks: ['https://nextjs.org/13'],
}
<head> output
<link rel="bookmarks" href="https://nextjs.org/13" />

category

layout.js | page.js
export const metadata = {
  category: 'technology',
}
<head> output
<meta name="category" content="technology" />

facebook

Sie können eine Facebook-App oder ein Facebook-Konto mit Ihrer Webseite verbinden, um bestimmte Facebook Social Plugins zu nutzen Facebook-Dokumentation

Gut zu wissen: Sie können entweder appId oder admins angeben, aber nicht beides.

layout.js | page.js
export const metadata = {
  facebook: {
    appId: '12345678',
  },
}
<head> output
<meta property="fb:app_id" content="12345678" />
layout.js | page.js
export const metadata = {
  facebook: {
    admins: '12345678',
  },
}
<head> output
<meta property="fb:admins" content="12345678" />

Wenn Sie mehrere fb:admins Meta-Tags generieren möchten, können Sie einen Array-Wert verwenden.

layout.js | page.js
export const metadata = {
  facebook: {
    admins: ['12345678', '87654321'],
  },
}
<head> output
<meta property="fb:admins" content="12345678" />
<meta property="fb:admins" content="87654321" />

pinterest

Sie können Pinterest Rich Pins auf Ihrer Webseite aktivieren oder deaktivieren.

layout.js | page.js
export const metadata = {
  pinterest: {
    richPin: true,
  },
}
<head> output
<meta name="pinterest-rich-pin" content="true" />

other

Alle Metadaten-Optionen sollten durch die integrierte Unterstützung abgedeckt sein. Es kann jedoch benutzerdefinierte Metadaten-Tags geben, die spezifisch für Ihre Seite sind, oder brandneue Metadaten-Tags, die gerade veröffentlicht wurden. Sie können die other-Option verwenden, um beliebige benutzerdefinierte Metadaten-Tags zu rendern.

layout.js | page.js
export const metadata = {
  other: {
    custom: 'meta',
  },
}
<head> output
<meta name="custom" content="meta" />

Wenn Sie mehrere Meta-Tags mit demselben Schlüssel generieren möchten, können Sie einen Array-Wert verwenden.

layout.js | page.js
export const metadata = {
  other: {
    custom: ['meta1', 'meta2'],
  },
}
<head> output
<meta name="custom" content="meta1" /> <meta name="custom" content="meta2" />

Nicht unterstützte Metadaten

Die folgenden Metadaten-Typen werden derzeit nicht nativ unterstützt. Sie können jedoch weiterhin im Layout oder auf der Seite selbst gerendert werden.

Typen

Sie können Typsicherheit zu Ihren Metadaten hinzufügen, indem Sie den Typ Metadata verwenden. Wenn Sie das integrierte TypeScript-Plugin in Ihrer IDE verwenden, müssen Sie den Typ nicht manuell hinzufügen, können ihn aber dennoch explizit angeben, wenn Sie möchten.

metadata-Objekt

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

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

generateMetadata-Funktion

Reguläre Funktion
layout.tsx | page.tsx
import type { Metadata } from 'next'

export function generateMetadata(): Metadata {
  return {
    title: 'Next.js',
  }
}
Async-Funktion
layout.tsx | page.tsx
import type { Metadata } from 'next'

export async function generateMetadata(): Promise<Metadata> {
  return {
    title: 'Next.js',
  }
}
Mit Segment-Props
layout.tsx | page.tsx
import type { Metadata } from 'next'

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

export function generateMetadata({ params, searchParams }: Props): Metadata {
  return {
    title: 'Next.js',
  }
}

export default function Page({ params, searchParams }: Props) {}
Mit übergeordneten Metadaten
layout.tsx | page.tsx
import type { Metadata, ResolvingMetadata } from 'next'

export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  return {
    title: 'Next.js',
  }
}
JavaScript-Projekte

Für JavaScript-Projekte können Sie JSDoc verwenden, um Typsicherheit hinzuzufügen.

layout.js | page.js
/** @type {import("next").Metadata} */
export const metadata = {
  title: 'Next.js',
}
MetadatenEmpfehlung
<meta http-equiv="...">Verwenden Sie geeignete HTTP-Header über redirect(), Middleware, Security Headers
<base>Rendern Sie das Tag im Layout oder auf der Seite selbst.
<noscript>Rendern Sie das Tag im Layout oder auf der Seite selbst.
<style>Erfahren Sie mehr über Styling in Next.js.
<script>Erfahren Sie mehr über die Verwendung von Skripten.
<link rel="stylesheet" />Importieren Sie Stylesheets direkt im Layout oder auf der Seite selbst.
<link rel="preload />Verwenden Sie die ReactDOM preload-Methode
<link rel="preconnect" />Verwenden Sie die ReactDOM preconnect-Methode
<link rel="dns-prefetch" />Verwenden Sie die ReactDOM prefetchDNS-Methode

Resource Hints

Das <link>-Element hat eine Reihe von rel-Schlüsselwörtern, die verwendet werden können, um dem Browser mitzuteilen, dass eine externe Ressource wahrscheinlich benötigt wird. Der Browser verwendet diese Informationen, um je nach Schlüsselwort Preloading-Optimierungen anzuwenden.

Während die Metadata-API diese Hints nicht direkt unterstützt, können Sie neue ReactDOM-Methoden verwenden, um sie sicher in den <head> des Dokuments einzufügen.

'use client'

import ReactDOM from 'react-dom'

export function PreloadResources() {
  ReactDOM.preload('...', { as: '...' })
  ReactDOM.preconnect('...', { crossOrigin: '...' })
  ReactDOM.prefetchDNS('...')

  return '...'
}

Startet das Laden einer Ressource früh im Seitenrendering-Lebenszyklus (Browser). MDN Docs.

ReactDOM.preload(href: string, options: { as: string })
<head> output
<link rel="preload" href="..." as="..." />

Initiiert präemptiv eine Verbindung zu einem Origin. MDN Docs.

ReactDOM.preconnect(href: string, options?: { crossOrigin?: string })
<head> output
<link rel="preconnect" href="..." crossorigin />

Versucht, einen Domainnamen aufzulösen, bevor Ressourcen angefordert werden. MDN Docs.

ReactDOM.prefetchDNS(href: string)
<head> output
<link rel="dns-prefetch" href="..." />

Gut zu wissen:

  • Diese Methoden werden derzeit nur in Client Components unterstützt, die beim ersten Seitenaufruf serverseitig gerendert werden.
  • Integrierte Next.js-Funktionen wie next/font, next/image und next/script handhaben relevante Resource Hints automatisch.

Verhalten

Standardfelder

Es gibt zwei standardmäßige meta-Tags, die immer hinzugefügt werden, selbst wenn eine Route keine Metadaten definiert:

<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.

Streaming von Metadaten

Metadaten, die von generateMetadata zurückgegeben werden, werden an den Client gestreamt. Dadurch kann Next.js Metadaten in das HTML einfügen, sobald sie aufgelöst sind.

Da Seitenmetadaten hauptsächlich Bots und Crawler ansprechen, streamt Next.js Metadaten für Bots, die JavaScript ausführen und das vollständige Seiten-DOM untersuchen können (z.B. Googlebot). Für HTML-beschränkte Bots (z.B. Twitterbot), die beim Crawlen kein JavaScript ausführen können, blockieren die Metadaten weiterhin das Rendern der Seite.

Next.js erkennt automatisch den User Agent eingehender Anfragen, um zu entscheiden, ob gestreamte Metadaten bereitgestellt oder auf blockierende Metadaten zurückgegriffen werden soll.

Wenn Sie diese Liste anpassen müssen, können Sie sie manuell über die Option htmlLimitedBots in next.config.js definieren. Next.js stellt sicher, dass User Agents, die diesem Regex entsprechen, blockierende Metadaten erhalten, wenn sie Ihre Webseite anfordern.

import type { NextConfig } from 'next'

const config: NextConfig = {
  htmlLimitedBots: /MySpecialBot|MyAnotherSpecialBot|SimpleCrawler/,
}

export default config

Die Angabe einer htmlLimitedBots-Konfiguration überschreibt die Standardliste von Next.js und gibt Ihnen die volle Kontrolle darüber, welche User Agents dieses Verhalten aufweisen sollen. Dies ist ein erweitertes Verhalten, und die Standardeinstellung sollte für die meisten Fälle ausreichen.

Reihenfolge

Metadaten werden in der Reihenfolge ausgewertet, beginnend beim Root-Segment bis zum Segment, das dem endgültigen page.js-Segment am nächsten ist. Zum Beispiel:

  1. app/layout.tsx (Root-Layout)
  2. app/blog/layout.tsx (Verschachteltes Blog-Layout)
  3. app/blog/[slug]/page.tsx (Blog-Seite)

Zusammenführung

Gemäß der Auswertungsreihenfolge werden Metadata-Objekte, die aus mehreren Segmenten derselben Route exportiert werden, flach zusammengeführt, um die endgültige Metadatenausgabe einer 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 sind, durch das letzte Segment, das sie definiert, überschrieben werden.

Überschreiben von Feldern

app/layout.js
export const metadata = {
  title: 'Acme',
  openGraph: {
    title: 'Acme',
    description: 'Acme ist ein...',
  },
}
app/blog/page.js
export const metadata = {
  title: 'Blog',
  openGraph: {
    title: 'Blog',
  },
}

// Ausgabe:
// <title>Blog</title>
// <meta property="og:title" content="Blog" />

Im obigen Beispiel:

  • title aus app/layout.js wird durch title in app/blog/page.js ersetzt.
  • Alle openGraph-Felder aus app/layout.js werden in app/blog/page.js ersetzt, weil app/blog/page.js openGraph-Metadaten setzt. Beachten Sie das Fehlen von openGraph.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:

app/shared-metadata.js
export const openGraphImage = { images: ['http://...'] }
app/page.js
import { openGraphImage } from './shared-metadata'

export const metadata = {
  openGraph: {
    ...openGraphImage,
    title: 'Startseite',
  },
}
app/about/page.js
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.

Vererbung von Feldern

app/layout.js
export const metadata = {
  title: 'Acme',
  openGraph: {
    title: 'Acme',
    description: 'Acme ist ein...',
  },
}
app/about/page.js
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 aus app/layout.js wird durch title in app/about/page.js ersetzt.
  • Alle openGraph-Felder aus app/layout.js werden in app/about/page.js vererbt, weil app/about/page.js keine openGraph-Metadaten setzt.

Versionsverlauf

VersionÄnderungen
v15.2.0Streaming-Unterstützung für generateMetadata eingeführt.
v13.2.0viewport, themeColor und colorScheme zugunsten der viewport-Konfiguration als veraltet markiert.
v13.2.0metadata und generateMetadata eingeführt.