generateMetadata
本页面涵盖了所有使用 generateMetadata
和静态元数据对象的基于配置的元数据选项。
import type { Metadata } from 'next'
// 静态元数据
export const metadata: Metadata = {
title: '...',
}
// 或动态元数据
export async function generateMetadata({ params }) {
return {
title: '...',
}
}
值得注意的是:
metadata
对象和generateMetadata
函数导出仅在服务器组件中支持。- 你不能在同一路由段中同时导出
metadata
对象和generateMetadata
函数。
metadata
对象
要定义静态元数据,从 layout.js
或 page.js
文件中导出一个 Metadata
对象。
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: '...',
description: '...',
}
export default function Page() {}
请查看 元数据字段 了解所有支持的选项列表。
generateMetadata
函数
依赖于动态信息的元数据,例如当前路由参数、外部数据或父段中的 metadata
,可以通过导出一个返回 Metadata
对象 的 generateMetadata
函数来设置。
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> {
// 读取路由参数
const id = (await params).id
// 获取数据
const product = await fetch(`https://.../${id}`).then((res) => res.json())
// 可选择访问和扩展(而不是替换)父级元数据
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) {}
参数
generateMetadata
函数接受以下参数:
-
props
- 一个包含当前路由参数的对象:-
params
- 一个包含从根段到调用generateMetadata
的段的动态路由参数对象。示例:路由 URL params
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
- 一个包含当前 URL 的 搜索参数的对象。示例: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
- 父路由段中已解析元数据的 promise。
返回值
generateMetadata
应该返回一个包含一个或多个元数据字段的 Metadata
对象。
值得注意的是:
- 如果元数据不依赖运行时信息,应该使用静态的
metadata
对象 而不是generateMetadata
。- 在
generateMetadata
、generateStaticParams
、Layouts、Pages 和 Server Components 中对相同数据的fetch
请求会自动被记忆化。如果无法使用fetch
,可以使用 React 的cache
函数。searchParams
仅在page.js
段中可用。- Next.js 的
redirect()
和notFound()
方法也可以在generateMetadata
中使用。
Metadata 字段
title
title
属性用于设置文档的标题。它可以被定义为简单的字符串或可选的模板对象。
字符串
export const metadata = {
title: 'Next.js',
}
<title>Next.js</title>
模板对象
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
template: '...',
default: '...',
absolute: '...',
},
}
Default
title.default
可以用来为未定义 title
的子路由段提供回退标题。
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
default: 'Acme',
},
}
import type { Metadata } from 'next'
export const metadata: Metadata = {}
// 输出:<title>Acme</title>
Template
title.template
可以用来为子路由段中定义的 titles
添加前缀或后缀。
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
template: '%s | Acme',
default: 'Acme', // 创建模板时需要一个默认值
},
}
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'About',
}
// 输出:<title>About | Acme</title>
值得注意的是:
title.template
适用于子路由段而不是定义它的段。这意味着:
- 当你添加
title.template
时需要title.default
。- 在
layout.js
中定义的title.template
不会应用于同一路由段中page.js
定义的title
。- 在
page.js
中定义的title.template
没有效果,因为页面始终是终止段(它没有任何子路由段)。如果路由没有定义
title
或title.default
,则title.template
不会生效。
Absolute
title.absolute
可以用来提供一个忽略父段中 title.template
的标题。
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
template: '%s | Acme',
},
}
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
absolute: 'About',
},
}
// 输出:<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.template
在page.js
中没有效果,因为页面始终是路由的终止段。
description
export const metadata = {
description: '用于 Web 的 React 框架',
}
<meta name="description" content="用于 Web 的 React 框架" />
基本字段
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,
},
}
<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
是一个便捷选项,用于为需要完全限定 URL 的 metadata
字段设置基本 URL 前缀。
metadataBase
允许当前路由段及以下定义的基于 URL 的metadata
字段使用相对路径,而不是原本需要的绝对 URL。- 字段的相对路径将与
metadataBase
组合形成完全限定的 URL。 - 如果未配置,
metadataBase
将自动填充默认值。
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',
},
}
<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
将被忽略。- 在基于 URL 的
metadata
字段中使用相对路径而不配置metadataBase
将导致构建错误。- Next.js 会将
metadataBase
(例如https://acme.com/
) 和相对字段 (例如/path
) 之间的重复斜杠规范化为单个斜杠 (例如https://acme.com/path
)。
默认值
如果未配置,metadataBase
有一个默认值。
在 Vercel 上:
- 对于生产部署,将使用
VERCEL_PROJECT_PRODUCTION_URL
。- 对于预览部署,
VERCEL_BRANCH_URL
将优先,如果不存在则回退到VERCEL_URL
。如果这些值存在,它们将被用作
metadataBase
的默认值,否则将回退到http://localhost:${process.env.PORT || 3000}
。这使得 Open Graph 图像在本地构建和 Vercel 预览及生产部署上都能正常工作。在覆盖默认值时,我们建议使用环境变量来计算 URL。这允许为本地开发、测试和生产环境配置不同的 URL。有关这些环境变量的更多详细信息,请参阅系统环境变量文档。
URL 组合
URL 组合倾向于遵循开发者意图而不是默认的目录遍历语义。
metadataBase
和metadata
字段之间的尾部斜杠会被规范化。metadata
字段中的"绝对"路径(通常会替换整个 URL 路径)被视为"相对"路径(从metadataBase
的末尾开始)。
例如,给定以下 metadataBase
:
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 |
payments | https://acme.com/payments |
/payments | https://acme.com/payments |
./payments | https://acme.com/payments |
../payments | https://acme.com/payments |
https://beta.acme.com/payments | https://beta.acme.com/payments |
openGraph
export const metadata = {
openGraph: {
title: 'Next.js',
description: '用于 Web 的 React 框架',
url: 'https://nextjs.org',
siteName: 'Next.js',
images: [
{
url: 'https://nextjs.org/og.png', // 必须是绝对 URL
width: 800,
height: 600,
},
{
url: 'https://nextjs.org/og-alt.png', // 必须是绝对 URL
width: 1800,
height: 1600,
alt: '我的自定义替代文本',
},
],
videos: [
{
url: 'https://nextjs.org/video.mp4', // 必须是绝对 URL
width: 800,
height: 600,
},
],
audio: [
{
url: 'https://nextjs.org/audio.mp3', // 必须是绝对 URL
},
],
locale: 'zh_CN',
type: 'website',
},
}
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="用于 Web 的 React 框架" />
<meta property="og:url" content="https://nextjs.org/" />
<meta property="og:site_name" content="Next.js" />
<meta property="og:locale" content="zh_CN" />
<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="我的自定义替代文本" />
<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" />
export const metadata = {
openGraph: {
title: 'Next.js',
description: '用于 Web 的 React 框架',
type: 'article',
publishedTime: '2023-01-01T00:00:00.000Z',
authors: ['Seb', 'Josh'],
},
}
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="用于 Web 的 React 框架" />
<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" />
值得注意的是:
- 对于 Open Graph 图像,使用基于文件的元数据 API可能更方便。与其必须同步配置导出和实际文件,基于文件的 API 将自动为你生成正确的元数据。
robots
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,
},
},
}
<meta name="robots" content="index, follow" />
<meta
name="googlebot"
content="index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1"
/>
icons
值得注意的是:我们建议尽可能使用基于文件的元数据 API来处理图标。与其必须同步配置导出和实际文件,基于文件的 API 将自动为你生成正确的元数据。
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',
},
},
}
<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"
/>
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',
},
],
},
}
<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-*
meta 标签,因此不再需要这些标签。
themeColor
已弃用:从 Next.js 14 开始,
metadata
中的themeColor
选项已弃用。请改用viewport
配置。
colorScheme
Deprecated: Next.js 14 中
metadata
中的colorScheme
选项已被弃用。请改用viewport
配置。
manifest
Web 应用程序清单,如 Web 应用程序清单规范中定义。
export const metadata = {
manifest: 'https://nextjs.org/manifest.json',
}
<link rel="manifest" href="https://nextjs.org/manifest.json" />
twitter
Twitter 规范(令人惊讶的是)不仅用于 X(前身为 Twitter)。
了解更多关于 Twitter 卡片标记参考。
export const metadata = {
twitter: {
card: 'summary_large_image',
title: 'Next.js',
description: '用于 Web 的 React 框架',
siteId: '1467726470533754880',
creator: '@nextjs',
creatorId: '1467726470533754880',
images: ['https://nextjs.org/og.png'], // 必须是绝对 URL
},
}
<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="用于 Web 的 React 框架" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
export const metadata = {
twitter: {
card: 'app',
title: 'Next.js',
description: '用于 Web 的 React 框架',
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',
},
},
},
}
<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="用于 Web 的 React 框架" />
<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
已弃用:从 Next.js 14 开始,
metadata
中的viewport
选项已弃用。请改用viewport
配置。
verification
export const metadata = {
verification: {
google: 'google',
yandex: 'yandex',
yahoo: 'yahoo',
other: {
me: ['my-email', 'my-link'],
},
},
}
<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
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)',
},
],
},
}
<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
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',
},
},
}
<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"
/>
appLinks
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,
},
},
}
<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
描述具有历史意义的记录、文档或其他材料的集合(来源)。
export const metadata = {
archives: ['https://nextjs.org/13'],
}
<link rel="archives" href="https://nextjs.org/13" />
assets
export const metadata = {
assets: ['https://nextjs.org/assets'],
}
<link rel="assets" href="https://nextjs.org/assets" />
bookmarks
export const metadata = {
bookmarks: ['https://nextjs.org/13'],
}
<link rel="bookmarks" href="https://nextjs.org/13" />
category
export const metadata = {
category: '技术',
}
<meta name="category" content="技术" />
facebook
你可以将 Facebook 应用或 Facebook 账号连接到你的网页,以使用某些 Facebook 社交插件 Facebook 文档
值得注意的是:你可以指定 appId 或 admins,但不能同时指定两者。
export const metadata = {
facebook: {
appId: '12345678',
},
}
<meta property="fb:app_id" content="12345678" />
export const metadata = {
facebook: {
admins: '12345678',
},
}
<meta property="fb:admins" content="12345678" />
如果你想生成多个 fb:admins meta 标签,可以使用数组值。
export const metadata = {
facebook: {
admins: ['12345678', '87654321'],
},
}
<meta property="fb:admins" content="12345678" />
<meta property="fb:admins" content="87654321" />
other
所有元数据选项都应该使用内置支持来覆盖。然而,可能会有特定于你的网站的自定义元数据标签,或者刚刚发布的新元数据标签。你可以使用 other
选项来渲染任何自定义元数据标签。
export const metadata = {
other: {
custom: 'meta',
},
}
<meta name="custom" content="meta" />
如果你想生成多个相同键的 meta 标签,可以使用数组值。
export const metadata = {
other: {
custom: ['meta1', 'meta2'],
},
}
<meta name="custom" content="meta1" />
<meta name="custom" content="meta2" />
不支持的元数据
以下元数据类型目前没有内置支持。但是,它们仍然可以在布局或页面本身中渲染。
元数据 | 建议 |
---|---|
<meta http-equiv="..."> | 通过 redirect() 、Middleware、安全头部 使用适当的 HTTP 头部 |
<base> | 在布局或页面本身中渲染该标签。 |
<noscript> | 在布局或页面本身中渲染该标签。 |
<style> | 了解更多关于 Next.js 中的样式。 |
<script> | 了解更多关于使用脚本。 |
<link rel="stylesheet" /> | 直接在布局或页面本身中 import 样式表。 |
<link rel="preload /> | 使用 ReactDOM preload 方法 |
<link rel="preconnect" /> | 使用 ReactDOM preconnect 方法 |
<link rel="dns-prefetch" /> | 使用 ReactDOM prefetchDNS 方法 |
资源提示
<link>
元素有许多 rel
关键词,可以用来提示浏览器某个外部资源可能会被需要。浏览器使用这些信息根据关键词应用预加载优化。
虽然元数据 API 不直接支持这些提示,但你可以使用新的 ReactDOM
方法安全地将它们插入到文档的 <head>
中。
'use client'
import ReactDOM from 'react-dom'
export function PreloadResources() {
ReactDOM.preload('...', { as: '...' })
ReactDOM.preconnect('...', { crossOrigin: '...' })
ReactDOM.prefetchDNS('...')
return '...'
}
<link rel="preload">
在页面渲染(浏览器)生命周期的早期开始加载资源。MDN 文档。
ReactDOM.preload(href: string, options: { as: string })
<link rel="preload" href="..." as="..." />
<link rel="preconnect">
提前初始化与源的连接。MDN 文档。
ReactDOM.preconnect(href: string, options?: { crossOrigin?: string })
<link rel="preconnect" href="..." crossorigin />
<link rel="dns-prefetch">
尝试在请求资源之前解析域名。MDN 文档。
ReactDOM.prefetchDNS(href: string)
<link rel="dns-prefetch" href="..." />
值得注意的是:
- 这些方法目前仅在客户端组件中支持,这些组件在初始页面加载时仍然会进行服务器端渲染。
- Next.js 内置功能如
next/font
、next/image
和next/script
会自动处理相关的资源提示。
类型
你可以使用 Metadata
类型为你的元数据添加类型安全。如果你在 IDE 中使用内置的 TypeScript 插件,则无需手动添加类型,但如果你想的话,你仍然可以显式添加它。
metadata
对象
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
generateMetadata
函数
常规函数
import type { Metadata } from 'next'
export function generateMetadata(): Metadata {
return {
title: 'Next.js',
}
}
异步函数
import type { Metadata } from 'next'
export async function generateMetadata(): Promise<Metadata> {
return {
title: 'Next.js',
}
}
带有段参数
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) {}
带有父元数据
import type { Metadata, ResolvingMetadata } from 'next'
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
return {
title: 'Next.js',
}
}
JavaScript 项目
对于 JavaScript 项目,你可以使用 JSDoc 添加类型安全。
/** @type {import("next").Metadata} */
export const metadata = {
title: 'Next.js',
}
流式传输元数据
从 v15.2 开始,由 generateMetadata
返回的元数据将被流式传输到客户端。这允许 Next.js 在元数据解析完成后立即将其注入到 HTML 中。
由于页面元数据主要针对机器人和爬虫,Next.js 将继续阻塞渲染,直到HTML 受限机器人的元数据被解析完成。
一些机器人,如 Googlebot
,可以执行 JavaScript 并能够检查完整的页面 DOM,这意味着它们不需要阻塞元数据。然而,像 Twitterbot
这样的机器人在爬取页面时无法执行 JavaScript——它们属于HTML 受限类别。
Next.js 自动检测传入请求的用户代理,以确定是提供流式元数据还是回退到阻塞元数据。
如果你需要自定义这个列表,可以使用 next.config.js
中的 htmlLimitedBots
选项手动定义它们。Next.js 将确保与此正则表达式匹配的用户代理在请求你的网页时接收阻塞元数据。
指定 htmlLimitedBots
配置将覆盖 Next.js 的默认列表,让你完全控制哪些用户代理应该采用这种行为。这是高级行为,默认设置对大多数情况应该足够了。
module.exports = {
htmlLimitedBots: 'MySpecialBot|MyAnotherSpecialBot|SimpleCrawler',
}
注意: Next.js 包含一个 HTML 受限机器人的默认列表
版本历史
版本 | 变更 |
---|---|
v15.2.0 | 引入对 generateMetadata 的流式支持。 |
v13.2.0 | viewport 、themeColor 和 colorScheme 已被弃用,改用 viewport 配置。 |
v13.2.0 | 引入 metadata 和 generateMetadata 。 |