- Published on
Next.js 生成 OG 图片
什么是 OG 图片?
OG 图片(Open Graph Image)是一种元标记图片,当你的网页链接被分享到社交媒体平台(如 Facebook、Twitter、LinkedIn 等)时会显示的预览图片。
为什么需要 OG 图片?
提升分享体验
- 让分享的链接更加醒目和吸引人
- 提供更丰富的视觉信息
- 增加用户点击的可能性
品牌一致性
- 可以在分享时保持品牌的视觉识别
- 让内容在社交媒体上更专业和正式
SEO 优化
- 有助于提高社交媒体的 SEO 表现
- 增加内容在社交平台的曝光度
用户体验
- 让用户在分享前就能预览内容
- 提供更好的内容上下文
OG 图片的规范
- 推荐尺寸: 1200 x 630 像素
- 最小尺寸: 600 x 315 像素
- 宽高比: 1.91:1
- 文件格式: PNG、JPEG 或 GIF
- 文件大小: 建议小于 8MB
没有 OG 图片时,社交平台通常会随机选择页面中的图片或显示一个默认图片,这可能会影响内容的展示效果。因此,为网站设置合适的 OG 图片是提升社交分享体验的重要一环。
OG 协议标准
OG 协议最初是由 Facebook 在 2010 年提出的 Open Graph Protocol 的一部分。这个协议定义了网页在社交媒体平台上如何被展示和分享。
标准来源
Facebook Open Graph Protocol
- 最初的标准制定者
- 详细文档: Open Graph Protocol
- 被大多数社交平台采纳
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 图片的种类
静态图片 (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(静态)格式
- 适用于大多数场景
动态视频缩略图 (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" />这样可以确保在所有平台上都能正确显示预览图。
- 不同平台处理视频缩略图的方式不同:
动画图片 (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>
详细内容可以看官方文档