如何添加元数据并创建 OG 图片

元数据 API 可用于定义应用程序元数据以提升 SEO 和网页可分享性,包括:

  1. 静态 metadata 对象
  2. 动态 generateMetadata 函数
  3. 特殊的文件约定,可用于添加静态或动态生成的 faviconsOG 图片

使用以上所有选项时,Next.js 会自动为页面生成相关的 <head> 标签,您可以在浏览器的开发者工具中查看。

默认字段

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

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

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

静态元数据

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

import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: '我的博客',
  description: '...',
}

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

export default function Page() {}

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

生成元数据

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

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

  // 获取文章信息
  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 会从 UI 中单独流式传输元数据,并在解析后立即将元数据注入 HTML。

数据请求记忆化

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

import { cache } from 'react'
import { db } from '@/app/lib/db'

// getPost 会被使用两次,但只执行一次
export const getPost = cache(async (slug: string) => {
  const res = await db.query.posts.findFirst({ where: eq(posts.slug, slug) })
  return res
})

基于文件的元数据

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

您可以使用这些文件进行静态元数据设置,也可以通过代码编程方式生成这些文件。

网站图标

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

应用文件夹中的 Favicon 特殊文件,与布局和页面文件并列

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

静态 Open Graph 图片

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

应用文件夹中的 OG 图片特殊文件,与布局和页面文件并列

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

blog 文件夹中的 OG 图片特殊文件

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

还支持其他图像格式,如 jpegpngwebp。更多信息请参阅 Open Graph 图片文档

动态生成 Open Graph 图片

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

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

import { ImageResponse } from 'next/og'
import { getPost } from '@/app/lib/data'

// 图片元数据
export const size = {
  width: 1200,
  height: 630,
}

export const contentType = 'image/png'

// 图片生成
export default async function Image({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug)

  return new ImageResponse(
    (
      // ImageResponse JSX 元素
      <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)将不起作用

On this page