Published on

Next.js 生成 OG 图片

什么是 OG 图片?

OG 图片(Open Graph Image)是一种元标记图片,当你的网页链接被分享到社交媒体平台(如 Facebook、Twitter、LinkedIn 等)时会显示的预览图片。

为什么需要 OG 图片?

  1. 提升分享体验

    • 让分享的链接更加醒目和吸引人
    • 提供更丰富的视觉信息
    • 增加用户点击的可能性
  2. 品牌一致性

    • 可以在分享时保持品牌的视觉识别
    • 让内容在社交媒体上更专业和正式
  3. SEO 优化

    • 有助于提高社交媒体的 SEO 表现
    • 增加内容在社交平台的曝光度
  4. 用户体验

    • 让用户在分享前就能预览内容
    • 提供更好的内容上下文

OG 图片的规范

  • 推荐尺寸: 1200 x 630 像素
  • 最小尺寸: 600 x 315 像素
  • 宽高比: 1.91:1
  • 文件格式: PNG、JPEG 或 GIF
  • 文件大小: 建议小于 8MB

没有 OG 图片时,社交平台通常会随机选择页面中的图片或显示一个默认图片,这可能会影响内容的展示效果。因此,为网站设置合适的 OG 图片是提升社交分享体验的重要一环。

OG 协议标准

OG 协议最初是由 Facebook 在 2010 年提出的 Open Graph Protocol 的一部分。这个协议定义了网页在社交媒体平台上如何被展示和分享。

标准来源

  1. Facebook Open Graph Protocol

  2. Twitter Cards 标准

    • Twitter 的专属标准,提供了额外的展示选项
    • 与 OG 协议兼容但有自己的特殊标签
    • 提供四种不同的卡片类型:
      • Summary Card: 标准的小型预览卡片
      • Summary Card with Large Image: 大图预览卡片
      • App Card: 应用下载卡片
      • Player Card: 媒体播放器卡片
    • 图片尺寸建议:
      • Summary Card: 最小 144x144px,建议 300x157px
      • Summary Card with Large Image: 最小 300x157px,建议 1200x628px
    • 使用 name 而不是 property 属性,标签前缀为 twitter:

    基本的 Twitter Cards 元标签示例:

    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:site" content="@username" />
    <meta name="twitter:title" content="页面标题" />
    <meta name="twitter:description" content="页面描述" />
    <meta name="twitter:image" content="https://example.com/image.jpg" />
    

    最佳实践是同时使用两种标准:

    <!-- Facebook OG -->
    <meta property="og:title" content="页面标题" />
    <meta property="og:image" content="https://example.com/image.jpg" />
    
    <!-- Twitter Cards -->
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="页面标题" />
    <meta name="twitter:image" content="https://example.com/image.jpg" />
    

在网页中添加 OG 图片

要在网页中添加 OG 图片,需要在 HTML 的 <head> 标签中添加相应的 meta 标签。以下是一个基本示例:

<head>
  <meta property="og:image" content="https://example.com/og-image.jpg" />
  <meta property="og:image:width" content="1200" />
  <meta property="og:image:height" content="630" />
</head>

OG 图片的种类

  1. 静态图片 (Static Images)

    <meta property="og:image" content="https://example.com/article-image.jpg" />
    <meta property="og:image:width" content="1200" />
    <meta property="og:image:height" content="630" />
    
    • 最基本和最常用的类型
    • 支持 JPG、PNG、GIF(静态)格式
    • 适用于大多数场景
  2. 动态视频缩略图 (Dynamic Video Thumbnails)

    • 不同平台处理视频缩略图的方式不同:
      • Facebook 会自动从视频中提取第一帧或关键帧作为缩略图
      • Twitter 需要单独指定缩略图
      • 其他平台可能需要手动设置

    最佳实践是同时提供视频和缩略图:

    <!-- 视频元数据 -->
    <meta property="og:video" content="https://example.com/video.mp4" />
    <meta property="og:video:type" content="video/mp4" />
    <meta property="og:video:width" content="1280" />
    <meta property="og:video:height" content="720" />
    
    <!-- 明确指定缩略图 -->
    <meta property="og:image" content="https://example.com/video-thumbnail.jpg" />
    <meta property="og:image:width" content="1200" />
    <meta property="og:image:height" content="630" />
    

    这样可以确保在所有平台上都能正确显示预览图。

  3. 动画图片 (Animated Images)

    <meta property="og:image" content="https://example.com/animation.gif" />
    <meta property="og:image:type" content="image/gif" />
    <meta property="og:image:width" content="1200" />
    <meta property="og:image:height" content="630" />
    
    • 支持动态 GIF
    • 部分平台支持简短视频预览
    • 文件大小限制更严格

每种类型都有其特定的使用场景和限制:

类型最佳使用场景主要限制
静态图片文章、产品页面文件大小、分辨率
视频缩略图视频内容、直播平台支持度
动画图片简短演示、品牌推广文件大小、兼容性

动态生成 OG 图片

为了达到更好的效果,我们可以针对不同内容动态生成 OG 图片,这里介绍 Next.js 中如何实现。

1. 在路由段中创建 opengraph-image 或者 twitter-image 文件

使用 ImageResponse 动态生成图片:

import { ImageResponse } from 'next/og'

 
// Image metadata
export const alt = 'About Acme'
export const size = {
  width: 1200,
  height: 630,
}


export default function Image({ params })

  return new ImageResponse(
    (
      // ImageResponse JSX element
      <div
        style={{
          fontSize: 128,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        About Acme
      </div>
    ),
    // ImageResponse options
    {
      // For convenience, we can re-use the exported opengraph-image
      // size config to also set the ImageResponse's width and height.
      ...size,
    }
  )
}

接受一个参数 params,接收动态路由参数,app/shop/[tag]/[item]/opengraph-image.js,/shop/1/2 会生成 { tag: '1', item: '2' } 的图片。 可以试试这个参数去获取外部数据,然后生成图片:

  const post = await fetch(`https://.../posts/${params.slug}`).then((res) =>
    res.json()
  )

也可以使用 node 的 fs 模块去读取本地文件:

import { join } from 'node:path'
import { readFile } from 'node:fs/promises'

  const logoData = await readFile(join(process.cwd(), 'logo.png'))
  const logoSrc = Uint8Array.from(logoData).buffer

本地文件的路径使用相对于项目根目录的相对路径。

详细内容可以看官方文档

2. 使用 @vercel/og 创建动态生成 og 图片的 api

@vercel/og 是一个用于生成 OG 图片的库,它可以在任何框架中使用,并且在 Vercel 平台上部署时有最佳性能。

pnpm i @vercel/og

然后创建一个 api 文件,为了确保社交媒体平台能够正常获取你的 OG 图片,建议在 robots.txt 文件中将 OG 图片 API 路由添加到 Allow 列表中。

Allow: /api/og/*

写一个返回图片的 endpoint 文件,

import { ImageResponse } from '@vercel/og';
 
export default async function handler() {
  return new ImageResponse(
    (
      <div
        style={{
          fontSize: 40,
          color: 'black',
          background: 'white',
          width: '100%',
          height: '100%',
          padding: '50px 200px',
          textAlign: 'center',
          justifyContent: 'center',
          alignItems: 'center',
        }}
      >
        👋 Hello
      </div>
    ),
    {
      width: 1200,
      height: 630,
    },
  );
}

可以从前端传任意你需要的参数,然后生成图片,比如说把文章的标题,作者,发布时间,封面图,内容摘要等使用查询参数传入:

const title = searchParams.get("title");
const author = searchParams.get("author");
const publishTime = searchParams.get("publishTime");

<head>
  <title>Hello world</title>
  <meta
    property="og:image"
    content="https://og-examples.vercel.sh/api/static?title=${title}&author=${author}&publishTime=${publishTime}"
  />
</head>

详细内容可以看官方文档