跳至内容
API 参考函数generateMetadata

generateMetadata

本页介绍了使用 generateMetadata 和静态元数据对象的所有基于配置的元数据选项。

layout.tsx | page.tsx
import type { Metadata } from 'next'
 
// either Static metadata
export const metadata: Metadata = {
  title: '...',
}
 
// or Dynamic metadata
export async function generateMetadata({ params }) {
  return {
    title: '...',
  }
}

需知:

  • metadata 对象和 generateMetadata 函数导出仅在服务器组件中受支持
  • 您不能从同一路由段导出 metadata 对象和 generateMetadata 函数。

metadata 对象

要定义静态元数据,请从 layout.jspage.js 文件导出 Metadata 对象

layout.tsx | page.tsx
import type { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: '...',
  description: '...',
}
 
export default function Page() {}

有关受支持选项的完整列表,请参阅元数据字段

generateMetadata 函数 Metadata 对象generateMetadata 函数来设置。

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 = (await 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/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/shop/1/2
  • searchParams - 包含当前 URL 的 搜索参数 的对象。例如:

    网址searchParams
    /shop?a=1{ a: '1' }
    /shop?a=1&b=2{ a: '1', b: '2' }
    /shop?a=1&a=2{ a: ['1', '2'] }
  • parent - 来自父路由段的已解析元数据的承诺。

  • 返回值 Metadata 对象

    需知:

    • 如果元数据不依赖于运行时信息,则应使用静态 metadata 对象 而不是 generateMetadata 来定义它。
    • 对于 generateMetadatagenerateStaticParams、布局、页面和服务器组件中的相同数据,fetch 请求会自动进行 记忆化。如果 fetch 不可用,则可以使用 React cache
    • searchParams 仅在 page.js 段中可用。
    • Next.js 方法 redirect()notFound() 也可以在 generateMetadata 中使用。

    元数据字段 title 字符串 或可选的 模板对象

    字符串
    layout.js | page.js
    export const metadata = {
      title: 'Next.js',
    }

    <head> 输出
    <title>Next.js</title>

    模板对象
    app/layout.tsx
    import type { Metadata } from 'next'
     
    export const metadata: Metadata = {
      title: {
        template: '...',
        default: '...',
        absolute: '...',
      },
    }

    默认值
    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 = {}
     
    // Output: <title>Acme</title>
    模板
    app/layout.tsx
    import type { Metadata } from 'next'
     
    export const metadata: Metadata = {
      title: {
        template: '%s | Acme',
        default: 'Acme', // a default is required when creating a template
      },
    }
    app/about/page.tsx
    import type { Metadata } from 'next'
     
    export const metadata: Metadata = {
      title: 'About',
    }
     
    // Output: <title>About | Acme</title>

    需知:

    • title.template 适用于路由段,而适用于定义它的路由段。这意味着

      • 添加 title.template 时,必须提供 title.default
      • layout.js 中定义的 title.template 不会应用于同一路由段的 page.js 中定义的 title
      • page.js 中定义的 title.template 无效,因为页面始终是终止段(它没有任何子路由段)。
    • 如果路由未定义 titletitle.default,则 title.template 无效

    绝对路径

    title.absolute 可用于提供忽略父段中设置的 title.template 的标题。

    app/layout.tsx
    import type { Metadata } from 'next'
     
    export const metadata: Metadata = {
      title: {
        template: '%s | Acme',
      },
    }
    app/about/page.tsx
    import type { Metadata } from 'next'
     
    export const metadata: Metadata = {
      title: {
        absolute: 'About',
      },
    }
     
    // Output: <title>About</title>

    需知:

    • layout.js

      • title(字符串)和 title.default 定义子段(未定义自己的 title)的默认标题。如果存在,它将增强来自最近父段的 title.template
      • title.absolute 定义子段的默认标题。它忽略来自父段的 title.template
      • title.template 为子段定义新的标题模板。
    • page.js

      • 如果页面未定义自己的标题,则将使用最近父级解析的标题。
      • title(字符串)定义路由标题。如果存在,它将增强来自最近父段的 title.template
      • title.absolute 定义路由标题。它忽略来自父段的 title.template
      • title.templatepage.js 中无效,因为页面始终是路由的终止段。

    description

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

    基本字段
    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.net.cn' }],
      creator: 'Jiachi Liu',
      publisher: 'Sebastian Markbåge',
      formatDetection: {
        email: false,
        address: false,
        telephone: false,
      },
    }
    <head> 输出
    <meta name="application-name" content="Next.js" />
    <meta name="author" content="Seb" />
    <link rel="author" href="https://nextjs.net.cn" />
    <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 默认值
    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> 输出
    <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" />

    需知:

    • metadataBase 通常在根目录 app/layout.js 中设置,以应用于所有路由中的基于 URL 的 metadata 字段。
    • 所有需要绝对 URL 的基于 URL 的 metadata 字段都可以使用 metadataBase 选项进行配置。
    • metadataBase 可以包含子域(例如 https://app.acme.com)或基本路径(例如 https://acme.com/start/from/here
    • 如果 metadata 字段提供绝对 URL,则将忽略 metadataBase
    • 在未配置 metadataBase 的情况下,在基于 URL 的 metadata 字段中使用相对路径将导致构建错误。
    • Next.js 会将 metadataBase(例如 https://acme.com/)和相对字段(例如 /path)之间的重复斜杠规范化为单个斜杠(例如 https://acme.com/path

    默认值

    如果未配置,metadataBase 将使用默认值

    在 Vercel 上

    • 对于生产环境部署,将使用 VERCEL_PROJECT_PRODUCTION_URL
    • 对于预览部署,VERCEL_BRANCH_URL 将优先使用,如果不存在,则回退到 VERCEL_URL

    如果存在这些值,它们将用作 metadataBase默认值,否则它将回退到 https://127.0.0.1:${process.env.PORT || 3000}。这允许 Open Graph 图像在本地构建以及 Vercel 预览和生产环境部署中都能正常工作。覆盖默认值时,我们建议使用环境变量来计算 URL。这允许为本地开发、测试和生产环境配置 URL。

    有关这些环境变量的更多详细信息,请参阅系统环境变量文档。

    URL 组合

    URL 组合优先考虑开发人员意图,而不是默认的目录遍历语义。

    例如,给定以下 metadataBase

    app/layout.tsx
    import type { Metadata } from 'next'
     
    export const metadata: Metadata = {
      metadataBase: new URL('https://acme.com'),
    }

    继承上述 metadataBase 并设置自身值的任何 metadata 字段都将解析如下

    metadata 字段解析后的 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.net.cn',
        siteName: 'Next.js',
        images: [
          {
            url: 'https://nextjs.net.cn/og.png', // Must be an absolute URL
            width: 800,
            height: 600,
          },
          {
            url: 'https://nextjs.net.cn/og-alt.png', // Must be an absolute URL
            width: 1800,
            height: 1600,
            alt: 'My custom alt',
          },
        ],
        videos: [
          {
            url: 'https://nextjs.net.cn/video.mp4', // Must be an absolute URL
            width: 800,
            height: 600,
          },
        ],
        audio: [
          {
            url: 'https://nextjs.net.cn/audio.mp3', // Must be an absolute URL
          },
        ],
        locale: 'en_US',
        type: 'website',
      },
    }
    <head> 输出
    <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.net.cn/" />
    <meta property="og:site_name" content="Next.js" />
    <meta property="og:locale" content="en_US" />
    <meta property="og:image" content="https://nextjs.net.cn/og.png" />
    <meta property="og:image:width" content="800" />
    <meta property="og:image:height" content="600" />
    <meta property="og:image" content="https://nextjs.net.cn/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:video" content="https://nextjs.net.cn/video.mp4" />
    <meta property="og:video:width" content="800" />
    <meta property="og:video:height" content="600" />
    <meta property="og:audio" content="https://nextjs.net.cn/audio.mp3" />
    <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> 输出
    <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" />

    需知:

    robots

    layout.tsx | page.tsx
    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> 输出
    <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

    温馨提示:我们建议尽可能使用基于文件的元数据 API来处理图标。基于文件的 API 会自动为您生成正确的元数据,而无需将配置导出与实际文件同步。

    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> 输出
    <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> 输出
    <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"
    />

    温馨提示:Microsoft Edge 的 Chromium 版本不再支持 msapplication-* 元标记,因此不再需要。

    themeColor

    已弃用:自 Next.js 14 起,metadata 中的 themeColor 选项已弃用。请改用viewport 配置

    manifest Web 应用程序清单文件规范

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

    twitter

    Twitter 规范(令人惊讶地)不仅用于 X(以前称为 Twitter)。

    详细了解Twitter 卡片标记参考

    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.net.cn/og.png'], // Must be an absolute URL
      },
    }
    <head> 输出
    <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.net.cn/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.net.cn/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> 输出
    <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.net.cn/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

    已弃用:自 Next.js 14 起,metadata 中的 viewport 选项已弃用。请改用viewport 配置

    verification

    layout.js | page.js
    export const metadata = {
      verification: {
        google: 'google',
        yandex: 'yandex',
        yahoo: 'yahoo',
        other: {
          me: ['my-email', 'my-link'],
        },
      },
    }
    <head> 输出
    <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> 输出
    <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.net.cn',
        languages: {
          'en-US': 'https://nextjs.net.cn/en-US',
          'de-DE': 'https://nextjs.net.cn/de-DE',
        },
        media: {
          'only screen and (max-width: 600px)': 'https://nextjs.net.cn/mobile',
        },
        types: {
          'application/rss+xml': 'https://nextjs.net.cn/rss',
        },
      },
    }
    <head> 输出
    <link rel="canonical" href="https://nextjs.net.cn" />
    <link rel="alternate" hreflang="en-US" href="https://nextjs.net.cn/en-US" />
    <link rel="alternate" hreflang="de-DE" href="https://nextjs.net.cn/de-DE" />
    <link
      rel="alternate"
      media="only screen and (max-width: 600px)"
      href="https://nextjs.net.cn/mobile"
    />
    <link
      rel="alternate"
      type="application/rss+xml"
      href="https://nextjs.net.cn/rss"
    />
    layout.js | page.js
    export const metadata = {
      appLinks: {
        ios: {
          url: 'https://nextjs.net.cn/ios',
          app_store_id: 'app_store_id',
        },
        android: {
          package: 'com.example.android/package',
          app_name: 'app_name_android',
        },
        web: {
          url: 'https://nextjs.net.cn/web',
          should_fallback: true,
        },
      },
    }
    <head> 输出
    <meta property="al:ios:url" content="https://nextjs.net.cn/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.net.cn/web" />
    <meta property="al:web:should_fallback" content="true" />

    archives

    描述具有历史意义的记录、文档或其他资料的集合(来源)。

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

    assets

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

    bookmarks

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

    category

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

    facebook

    您可以将 Facebook 应用或 Facebook 帐户连接到您的网页,以便使用某些 Facebook 社交插件Facebook 文档

    需要注意的是:您可以指定 appId 或 admins,但不能同时指定两者。

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

    如果要生成多个 fb:admins 元标记,可以使用数组值。

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

    other

    所有元数据选项都应使用内置支持来涵盖。但是,可能存在特定于您网站的自定义元数据标记,或者刚刚发布的全新元数据标记。您可以使用“其他”选项来呈现任何自定义元数据标记。

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

    如果要生成多个相同键的元标记,可以使用数组值。

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

    不支持的元数据

    以下元数据类型当前没有内置支持。但是,它们仍然可以在布局或页面本身中呈现。

    元数据建议
    <meta http-equiv="...">通过redirect()中间件安全标头使用适当的 HTTP 标头
    <base>在布局或页面本身中呈现标记。
    <noscript>在布局或页面本身中呈现标记。
    <style>详细了解Next.js 中的样式
    <script>详细了解使用脚本
    <link rel="stylesheet" />直接在布局或页面本身中导入样式表。
    <link rel="preload />使用ReactDOM 预加载方法
    <link rel="preconnect" />使用ReactDOM 预连接方法
    <link rel="dns-prefetch" />使用ReactDOM 预取 DNS 方法

    资源提示

    <link> 元素有许多 rel 关键字,可用于提示浏览器可能需要外部资源。浏览器使用此信息根据关键字应用预加载优化。

    虽然元数据 API 不直接支持这些提示,但您可以使用新的 ReactDOM 方法 将它们安全地插入到文档的 <head> 中。

    app/preload-resources.tsx
    'use client'
     
    import ReactDOM from 'react-dom'
     
    export function PreloadResources() {
      ReactDOM.preload('...', { as: '...' })
      ReactDOM.preconnect('...', { crossOrigin: '...' })
      ReactDOM.prefetchDNS('...')
     
      return '...'
    }

    在页面渲染(浏览器)生命周期的早期开始加载资源。 MDN 文档

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

    预先启动与源的连接。 MDN 文档

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

    尝试在请求资源之前解析域名。 MDN 文档

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

    需知:

    类型

    您可以使用 Metadata 类型为您的元数据添加类型安全。如果您在 IDE 中使用内置的 TypeScript 插件,则无需手动添加类型,但如果需要,您仍然可以显式添加它。

    metadata 对象

    layout.tsx | page.tsx
    import type { Metadata } from 'next'
     
    export const metadata: Metadata = {
      title: 'Next.js',
    }

    generateMetadata 函数 常规函数

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

    异步函数
    layout.tsx | page.tsx
    import type { Metadata } from 'next'
     
    export async function generateMetadata(): Promise<Metadata> {
      return {
        title: 'Next.js',
      }
    }

    带有段落属性
    layout.tsx | page.tsx
    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) {}

    带有父元数据
    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 项目
    layout.js | page.js
    /** @type {import("next").Metadata} */
    export const metadata = {
      title: 'Next.js',
    }

    版本历史

    版本更改
    v13.2.0viewportthemeColorcolorScheme 已弃用,取而代之的是 viewport 配置
    v13.2.0引入了 metadatagenerateMetadata