跳到内容
App Router入门元数据和 OG 图像

元数据和 OG 图片

元数据 API 可用于定义应用程序元数据,以改善 SEO 和网络共享性,包括

  1. 静态 metadata 对象
  2. 动态 generateMetadata 函数
  3. 可用于添加静态或动态生成的网站图标OG 图像的特殊文件约定

通过上述所有选项,Next.js 将自动为您的页面生成相关的 <head> 标签,可以在浏览器的开发工具中进行检查。

metadata 对象和 generateMetadata 函数导出仅在服务器组件中受支持。

默认字段

即使路由未定义元数据,也会始终添加两个默认的 meta 标签

<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

其他元数据字段可以使用 Metadata 对象(用于静态元数据)或 generateMetadata 函数(用于生成的元数据)进行定义。

静态元数据

要定义静态元数据,请从静态 layout.jspage.js 文件中导出 Metadata 对象。例如,要向博客路由添加标题和描述

app/blog/layout.tsx
import type { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: 'My Blog',
  description: '...',
}
 
export default function Layout() {}

您可以在generateMetadata 文档中查看可用选项的完整列表。

生成的元数据

您可以使用 generateMetadata 函数来 fetch 依赖于数据的元数据。例如,要获取特定博客文章的标题和描述

app/blog/[slug]/page.tsx
import type { Metadata, ResolvingMetadata } from 'next'
 
type Props = {
  params: Promise<{ slug: string }>
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
 
export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  const slug = (await params).slug
 
  // fetch post information
  const post = await fetch(`https://api.vercel.app/blog/${slug}`).then((res) =>
    res.json()
  )
 
  return {
    title: post.title,
    description: post.description,
  }
}
 
export default function Page({ params, searchParams }: Props) {}

流式元数据

对于动态渲染的页面,Next.js 会单独流式传输元数据,一旦 generateMetadata 解析,就会将其注入 HTML,而不会阻塞 UI 渲染。

流式元数据通过允许视觉内容首先流式传输来提高感知性能。

流式元数据已为需要元数据位于 <head> 标签中的机器人和爬虫(例如 TwitterbotSlackbotBingbot)**禁用**。这些机器人和爬虫通过传入请求的用户代理标头进行检测。

您可以使用 Next.js 配置文件中的 htmlLimitedBots 选项来完全自定义或**禁用**流式元数据。

静态渲染的页面不使用流式传输,因为元数据在构建时解析。

了解更多关于流式元数据的信息。

记忆化数据请求

在某些情况下,您可能需要为元数据和页面本身获取**相同**的数据。为了避免重复请求,您可以使用 React 的 cache 函数 来记忆返回值,只获取一次数据。例如,要为元数据和页面获取博客文章信息

app/lib/data.ts
import { cache } from 'react'
import { db } from '@/app/lib/db'
 
// getPost will be used twice, but execute only once
export const getPost = cache(async (slug: string) => {
  const res = await db.query.posts.findFirst({ where: eq(posts.slug, slug) })
  return res
})
app/blog/[slug]/page.tsx
import { getPost } from '@/app/lib/data'
 
export async function generateMetadata({
  params,
}: {
  params: { slug: string }
}) {
  const post = await getPost(params.slug)
  return {
    title: post.title,
    description: post.description,
  }
}
 
export default async function Page({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug)
  return <div>{post.title}</div>
}

基于文件的元数据

以下特殊文件可用于元数据

您可以将这些用于静态元数据,也可以使用代码以编程方式生成这些文件。

网站图标

网站图标是代表您网站在书签和搜索结果中的小图标。要为您的应用程序添加网站图标,请创建 favicon.ico 并将其添加到 app 文件夹的根目录。

Favicon Special File inside the App Folder with sibling layout and page files

您还可以使用代码以编程方式生成网站图标。有关更多信息,请参阅网站图标文档

静态开放图谱图像

开放图谱 (OG) 图像是代表您网站在社交媒体中的图像。要为您的应用程序添加静态 OG 图像,请在 app 文件夹的根目录中创建 opengraph-image.png 文件。

OG image special file inside the App folder with sibling layout and page files

您还可以通过在更深层的文件夹结构中创建 opengraph-image.png 来为特定路由添加 OG 图像。例如,要为 /blog 路由创建特定的 OG 图像,请在 blog 文件夹中添加一个 opengraph-image.jpg 文件。

OG image special file inside the blog folder

更具体的图像将优先于文件夹结构中其上方的任何 OG 图像。

还支持其他图像格式,例如 jpegpnggif。有关更多信息,请参阅开放图谱图像文档

生成的开放图谱图像

ImageResponse 构造函数允许您使用 JSX 和 CSS 生成动态图像。这对于依赖于数据的 OG 图像非常有用。

例如,要为每篇博客文章生成唯一的 OG 图像,请在 blog 文件夹中添加 opengraph-image.tsx 文件,并从 next/og 导入 ImageResponse 构造函数

app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og'
import { getPost } from '@/app/lib/data'
 
// Image metadata
export const size = {
  width: 1200,
  height: 630,
}
 
export const contentType = 'image/png'
 
// Image generation
export default async function Image({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug)
 
  return new ImageResponse(
    (
      // ImageResponse JSX element
      <div
        style={{
          fontSize: 128,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        {post.title}
      </div>
    )
  )
}

ImageResponse 支持常见的 CSS 属性,包括 flexbox 和绝对定位、自定义字体、文本换行、居中和嵌套图像。查看支持的 CSS 属性的完整列表

须知:

  • 示例可在Vercel OG Playground中找到。
  • ImageResponse 使用 @vercel/ogsatoriresvg 将 HTML 和 CSS 转换为 PNG。
  • 仅支持 flexbox 和 CSS 属性的子集。高级布局(例如 display: grid)将不起作用。