Metadata-Objekt und generateMetadata-Optionen

Diese Seite behandelt alle konfigurationsbasierten Metadata-Optionen mit generateMetadata und dem statischen Metadata-Objekt.

import { Metadata } from 'next'

// Entweder statische Metadata
export const metadata: Metadata = {
  title: '...',
}

// Oder dynamische Metadata
export async function generateMetadata({ params }) {
  return {
    title: '...',
  }
}
// Entweder statische Metadata
export const metadata = {
  title: '...',
}

// Oder dynamische Metadata
export async function generateMetadata({ params }) {
  return {
    title: '...',
  }
}

Gut zu wissen:

  • Das metadata-Objekt und die generateMetadata-Funktion werden nur in Server Components unterstützt.
  • Sie können nicht gleichzeitig das metadata-Objekt und die generateMetadata-Funktion aus demselben Routen-Segment exportieren.

Das metadata-Objekt

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

import { Metadata } from 'next'

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

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

export default function Page() {}

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

generateMetadata-Funktion

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

import { 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> {
  // Routen-Parameter auslesen
  const id = params.id

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

  // Optional auf übergeordnete Metadata 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) {}
export async function generateMetadata({ params, searchParams }, parent) {
  // Routen-Parameter auslesen
  const id = params.id

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

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

Parameter

Die generateMetadata-Funktion akzeptiert folgende Parameter:

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

    • params - Ein Objekt mit den dynamischen Routen-Parametern vom Wurzel-Segment 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 Metadata aus übergeordneten Routen-Segmenten.

Rückgabewert

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

Gut zu wissen:

  • Wenn Metadata nicht von Laufzeitinformationen abhängt, sollte sie mit dem statischen metadata-Objekt definiert werden, nicht mit generateMetadata.
  • fetch-Anfragen werden automatisch memoisiert für dieselben Daten über generateMetadata, generateStaticParams, Layouts, Pages und Server Components hinweg. React cache kann verwendet werden, wenn 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

title

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

String

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

Template-Objekt

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '...',
    default: '...',
    absolute: '...',
  },
}
export const metadata = {
  title: {
    default: '...',
    template: '...',
    absolute: '...',
  },
}
Default

title.default kann verwendet werden, um einen Fallback-Titel für untergeordnete Routen-Segmente 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 einen Präfix oder Suffix zu titles hinzuzufügen, die in untergeordneten Routen-Segmenten definiert sind.

import { Metadata } from 'next'

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

export const metadata: Metadata = {
  title: 'About',
}

// Ausgabe: <title>About | Acme</title>
export const metadata = {
  title: 'About',
}

// Ausgabe: <title>About | Acme</title>

Gut zu wissen:

  • title.template gilt für untergeordnete Routen-Segmente 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 Routen-Segments definiert ist.
    • title.template, das in page.js definiert ist, hat keine Wirkung, da eine Page immer das abschließende Segment ist (sie hat keine untergeordneten Routen-Segmente).
  • 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 in übergeordneten Segmenten ignoriert.

import { Metadata } from 'next'

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

export const metadata: Metadata = {
  title: {
    absolute: 'About',
  },
}

// Ausgabe: <title>About</title>
export const metadata = {
  title: {
    absolute: 'About',
  },
}

// Ausgabe: <title>About</title>

Gut zu wissen:

  • layout.js

    • title (string) 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 ein neues Titel-Template für untergeordnete Segmente.
  • page.js

    • Wenn eine Page keinen eigenen Titel definiert, wird der aufgelöste Titel des nächstgelegenen übergeordneten Elements verwendet.
    • title (string) 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 Page 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" />

Grundlegende 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' }],
  colorScheme: 'dark',
  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 bequeme Option, um eine 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 Routen-Segment 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.
  • Wenn nicht konfiguriert, wird metadataBase automatisch mit einem Standardwert gefüllt.
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 für URL-basierte metadata-Felder über alle Routen hinweg zu gelten.
  • 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 von 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).

Standardwert

Wenn nicht konfiguriert, hat metadataBase einen Standardwert:

  • Wenn VERCEL_URL erkannt wird: https://${process.env.VERCEL_URL}, andernfalls fällt es auf http://localhost:${process.env.PORT || 3000} zurück.
  • Wenn Sie den Standardwert überschreiben, empfehlen wir die Verwendung von Umgebungsvariablen, um die URL zu berechnen. Dies ermöglicht die Konfiguration einer URL für lokale Entwicklung, Staging und Produktionsumgebungen.

URL-Zusammensetzung

Die URL-Zusammensetzung bevorzugt die Absicht des Entwicklers gegenüber Standard-Directory-Traversal-Semantik.

  • Schrägstriche am Ende 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 am Ende von metadataBase).

Beispielsweise, gegeben die folgende metadataBase:

import { Metadata } from 'next'

export const metadata: Metadata = {
  metadataBase: new URL('https://acme.com'),
}
export const 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: 'The React Framework for the Web',
    url: 'https://nextjs.org',
    siteName: 'Next.js',
    images: [
      {
        url: 'https://nextjs.org/og.png',
        width: 800,
        height: 600,
      },
      {
        url: 'https://nextjs.org/og-alt.png',
        width: 1800,
        height: 1600,
        alt: 'My custom alt',
      },
    ],
    locale: 'en_US',
    type: 'website',
  },
}
<head> output
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the 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:url" content="https://nextjs.org/og.png" />
<meta property="og:image:width" content="800" />
<meta property="og:image:height" content="600" />
<meta property="og:image:url" 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="My custom alt" />
<meta property="og:type" content="website" />
layout.js | page.js
export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'The React Framework for the 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="The React Framework for the 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 synchronisieren zu müssen, generiert die dateibasierte API automatisch die korrekten Metadaten für Sie.

robots

import type { Metadata } from 'next'

export const metadata: Metadata = {
  robots: {
    index: false,
    follow: true,
    nocache: true,
    googleBot: {
      index: true,
      follow: false,
      noimageindex: true,
      'max-video-preview': -1,
      'max-image-preview': 'large',
      'max-snippet': -1,
    },
  },
}
<head> output
<meta name="robots" content="noindex, follow, nocache" />
<meta
  name="googlebot"
  content="index, nofollow, noimageindex, 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 synchronisieren 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')],
    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="apple-touch-icon" href="/apple-icon.png" />
<link
  rel="apple-touch-icon-precomposed"
  href="/apple-touch-icon-precomposed.png"
/>
<link rel="icon" href="https://example.com/icon.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 erforderlich.

themeColor

Mehr über theme-color erfahren.

Einfache Theme-Farbe

layout.js | page.js
export const metadata = {
  themeColor: 'black',
}
<head> output
<meta name="theme-color" content="black" />

Mit media-Attribut

layout.js | page.js
export const metadata = {
  themeColor: [
    { media: '(prefers-color-scheme: light)', color: 'cyan' },
    { media: '(prefers-color-scheme: dark)', color: 'black' },
  ],
}
<head> output
<meta name="theme-color" media="(prefers-color-scheme: light)" content="cyan" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />

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

Mehr über die Twitter Card Markup-Referenz erfahren.

layout.js | page.js
export const metadata = {
  twitter: {
    card: 'summary_large_image',
    title: 'Next.js',
    description: 'The React Framework for the Web',
    siteId: '1467726470533754880',
    creator: '@nextjs',
    creatorId: '1467726470533754880',
    images: ['https://nextjs.org/og.png'],
  },
}
<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="The React Framework for the 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: 'The React Framework for the 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="The React Framework for the 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

Gut zu wissen: Das viewport Meta-Tag wird automatisch mit den folgenden Standardwerten gesetzt. Normalerweise ist eine manuelle Konfiguration nicht erforderlich, da die Standardwerte ausreichend sind. Die Informationen werden jedoch der Vollständigkeit halber bereitgestellt.

layout.js | page.js
export const metadata = {
  viewport: {
    width: 'device-width',
    initialScale: 1,
    maximumScale: 1,
  },
}
<head> output
<meta
  name="viewport"
  content="width=device-width, initial-scale=1, maximum-scale=1"
/>

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="apple-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" />

other

Alle Metadaten-Optionen sollten durch die integrierte Unterstützung abgedeckt sein. Es kann jedoch benutzerdefinierte Metadaten-Tags geben, die spezifisch für Ihre Site sind oder gerade erst veröffentlicht wurden. Sie können die Option other 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" />

Nicht unterstützte Metadaten

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

MetadatenEmpfehlung
<meta http-equiv="...">Verwenden Sie geeignete HTTP-Header über redirect(), Middleware oder Sicherheits-Header
<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 bietet eine Reihe von rel-Schlüsselwörtern, die dem Browser signalisieren, dass eine externe Ressource wahrscheinlich benötigt wird. Der Browser nutzt diese Informationen, um je nach Schlüsselwort Vorabladungsoptimierungen 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 null
}
'use client'

import ReactDOM from 'react-dom'

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

  return null
}

Lädt eine Ressource früh im Seitenrendering-Prozess (Browser) vor. MDN Docs.

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

Initiiert präventiv 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="..." />

Wissenswert:

  • Diese Methoden werden derzeit nur in Client Components unterstützt, die beim ersten Seitenaufruf trotzdem serverseitig gerendert werden.
  • Integrierte Next.js-Funktionen wie next/font, next/image und next/script verarbeiten relevante Resource Hints automatisch.
  • React 18.3 enthält noch keine Typdefinitionen für ReactDOM.preload, ReactDOM.preconnect und ReactDOM.preconnectDNS. Sie können // @ts-ignore als temporäre Lösung verwenden, um Typfehler zu vermeiden.

Typen

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

metadata-Objekt

import type { Metadata } from 'next'

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

generateMetadata-Funktion

Reguläre Funktion

import type { Metadata } from 'next'

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

Async-Funktion

import type { Metadata } from 'next'

export async function generateMetadata(): Promise<Metadata> {
  return {
    title: 'Next.js',
  }
}

Mit Segment-Props

import type { Metadata } from 'next'

type Props = {
  params: { id: string }
  searchParams: { [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

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.

/** @type {import("next").Metadata} */
export const metadata = {
  title: 'Next.js',
}

Versionsverlauf

VersionÄnderungen
v13.2.0metadata und generateMetadata eingeführt.