了解Open Graph:优化你的网站在社交媒体上的分享

最近在X上分享了个自己博客的链接,发现和平常看到很多大佬分享的博客链接相比显得非常朴素。一开始我以为是开通了Premium的原因hhh,直到我翻 Next.js API Reference 时,发现了关于MetaData Files的 opengraph-image 介绍才恍然大悟🫨,同时发现是个很有趣的东西,听我细嗦🤗。
Open Graph 快速通关 ⚔️
什么是Open Graph 🤔️
Open Graph 是一种由Facebook引入的元数据协议,旨在标准化网页上的元数据信息,以便在社交媒体平台上分享时更好地呈现。通过使用Open Graph标签,您可以控制分享时显示的标题、摘要、图像等关键信息,使您的内容在社交媒体上更具吸引力。
大白话:在一些主流的社交媒体美化你分享的链接,呈现更好的预览效果。(微信小程序分享
如何使用Open Graph 🤔️
使用Open Graph非常简单,只需在网页的头部插入一些HTML标签。以下是一些基本的Open Graph标签:
<meta property="og:title" content="您的标题">
<meta property="og:description" content="您的描述">
<meta property="og:image" content="您的图像链接">
<meta property="og:url" content="您的网页链接">
强烈建议首次使用时阅读更完整的协议内容,说不定你会发现更拓展你需求的MetaData 🤗 Open Graph Protocol
整理需求 📝
添加Open Graph是简单的,只需要在html中加入meta
选项。但在实现的过程中,你需要确定:
- ⚠️ 请注意,Open Graph的
og:image
属性需要接受一个绝对路径的地址。- 理论上可以接受相对路径,但这会依赖于社交媒体平台如何解析和处理这些路径。大多数情况下,为确保最佳兼容性,建议使用绝对路径。
- 如果你需要的只是一张静态资源的图片(比如你只是想将博客的封面图作为分享的图片。
- 这时你只需要在获取博客详情时,动态添加相关的内容到多个
<meta>
标签中。
- 这时你只需要在获取博客详情时,动态添加相关的内容到多个
- 如果你需要根据文章的标题 / 内容生成一张动态的
og:image
地址。- 那你需要有一定的后端知识,搭建一个能返回支持定制化的图片接口。
这些都是你在添加Open Graph时需要思考的事情,这决定了你的实现方式以及难易度的不同。以下我会用根据博客标题动态生成Open Graph图片链接的方式来举例。
技术方案 😇
需求确定了,但在这里的技术选型时,我纠结于是否使用Node.js
去实现这样一个根据携带参数绘制Canvas并生成图片的接口,具体考虑如下😇:
- 优点:可定制化高。Canvas API不用黑的是它的绘图能力,可以通过自定义各种图形、文本等元素,实现丰富的图像效果。
- 缺点:
- 性能开销:动态生成图像可能引起较高的性能开销,绘图操作也会占用较多内存。
- 额外的交互:因为现在我的博客是
Next.js
对Markdown
文件进行解析 & 静态托管的,所以在前端需要实现额外的交互逻辑。 - 难以缓存:我并不想这个接口是显性实时请求的,或许得考虑在前端创建博客后就生成动态的图片。但是这个情况有例外,就是在非博客页需要自己手动再去生成
og:image
,感觉拓展性变差很多,有点本末倒置了😵💫
后来想起来在之前使用Next.js
的时候,Pages Router模式下有个API Routes的特性,可以实现服务端API的效果。但是它只允许一些简单API的响应,不包括图片😭
然后我又双叒叕想起来自己博客其实是Next.js 13
,所以我只能用App Router(但是我没那么喜欢😭👊。然后刚好App Router有个Route Handlers,他是代替以前API Routes的新特性,并且可以包含更多响应类型,包括ImageResponse
对象,可以使用定义tsx的方式来生成图片!!!因祸得福了属于是🤡。
最后的方案确定成了:Route Handlers + GenerateMetadata。
(说在前面,它并没有比Node.js
的方案在性能上好到哪里去,它最大的优点是省事😬。)
生成动态Open Graph图片
定义API Route
- 创建处理请求Open Graph的handler路由文件
app/api/og.tsx
。 - 因为我这里使用的是GET方式,所以我就让动态标题通过query来传递 & 接收。
- 定义一段tsx,描述生成图片的结构。
- 图片需使用原始
<img>
标签。- ⚠️ 在需要使用到图片的地方都得使用绝对路径。(
background-image
/<img src="xxx">
- ⚠️ 在需要使用到图片的地方都得使用绝对路径。(
- 使用
Tailwind CSS
定义样式,给元素添加tw
属性即可。 - 直接修改
style
属性同样可以生效。 - 部分样式在
ImageResponse
中会失效。
- 图片需使用原始
- 返回
Next.js
提供的ImageResponse
实例化对象。
(如果需要修改字体,可以参照ImageResponse文档中的第二个参数进行修改。)
Talk is cheap, show me the code 🤗
// app/api/og.tsx
import { ImageResponse, NextRequest } from 'next/server'
export const runtime = 'edge'
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url)
const hasTitle = searchParams.get('title')
const title = hasTitle
? hasTitle.slice(0, 50) // limit title length
: siteMetadata.title
return new ImageResponse(
(
<div
tw='h-full w-full flex flex-col justify-center py-10 px-20 text-white'
style={ {
backgroundImage: `url(${/* your background image */})`,
backgroundSize: '100% 100%',
} }
>
<div
tw='text-6xl font-bold'
>
{ title }
</div>
<div
tw='text-2xl mt-4 tracking-wider font-semibold'
>
@Simba.Wang {/* your name */}
</div>
</div>
),
{
width: 1200,
height: 630,
},
)
}
在本地生成一个标题为「Hello-Word」的Open Graph Image,测试下你的API吧:http://127.0.0.1:3000/api/og?title=Hello-World (链接需根据自身情况修改
在页面中生成meta标签
到了这一步就没啥难点啦 只需要定义页面的generateMetadata
,组装你想描述的meta即可.我用我自己博客标签页的generateMetadata
抛砖引玉一下:
// app/categories/[slug]/page.tsx
import { siteMetadata } from '../../../utils/siteMetaData'; // replace to your site meta data
export async function generateMetadata({ params }: { params: { slug: string } }) {
const title = params.slug.toUpperCase()
const description = `Learn more about ${params.slug} | Simba's Blog`
const openGraphTitle = `Category — ${title}`
return {
description,
title: `#${title}`,
openGraph: {
description,
title: openGraphTitle,
url: `${siteMetadata.siteUrl}/categories/${params.slug}`,
siteName: siteMetadata.title,
type: "article",
authors: [siteMetadata.author],
images: [
{
url: `${siteMetadata.siteUrl}/api/og?title=${openGraphTitle}`,
},
],
},
twitter: {
description,
title: openGraphTitle,
card: "summary_large_image",
images: [
`${siteMetadata.siteUrl}/api/og?title=${openGraphTitle}`,
],
}
};
}
这里需要注意的一点是:当 openGraphTitle
更改时,就意味着 meta 标签的 URL 会发生更改,但社交平台并不会实时更新 meta 标签渲染的内容。比如 Twitter Cards 就有相关的更新规定,他们会在每 7 天重新建立索引,所以你的 meta 标签更新的渲染内容需要在 7 天后才能看到。
The Twitter web crawler re-indexes the Card tag information on your page roughly every seven days.
具体可以查看社交平台文档所支持的 Open Graph 属性来定义。同时也有需要额外自定义 meta 标签属性的平台,比如 Twitter Cards。
最后放一张我博客里 Tailwind CSS - 非常值得一试的CSS框架 链接的Twitter Card效果图。动手来试试吧!!!🤗