Open Graph Image Generator
这节我们来用 Next.js 提供的 og
功能用 React 的方式编写一个 Open Graph 图片生成函数。
这部分的内容在 Next.js 文档描述不明朗,你应该前往 Vercel 的文档中查看更多信息,下面是覆盖常用应用场景的 Demo。
什么是 Open Graph Image
Open Graph Image 是一种网页标记的一部分,属于 Open Graph 协议的一部分。这个协议最初由 Facebook 开发,用于控制社交媒体平台上分享链接时显示的内容。当你在社交网络上分享一个链接时,Open Graph 协议允许网站管理员定义如何展示该链接的标题、描述以及图像。
特别地,Open Graph Image 标签 (og:image) 定义了当链接被分享到社交媒体时,应该显示哪张图片。通过在 HTML 代码中添加此标签,可以指定一个图片的 URL,社交媒体平台在显示链接预览时就会使用这个图片。
例如。在我的站点中包含以下的 Open Graph Image 标签:
那么,在 Twitter 中的显示的效果就是:
基础 UI 的绘制
首先,新建 Route handler 文件 /api/og/route.tsx
,并在其中添加以下代码:
现在访问 /og
就会生成一个这样的图片了。
上面的例子中,全部使用了内联的 CSS 样式,我们也可以直接使用 Tailwind 规范的 CSS 原子类名。(此功能是实验性的,但是一般可以正常工作)。
需要注意的是,这里使用的是 tw=
属性而不是 className
。并且此 Tailwind 样式不会受到项目的 Tailwind 配置文件而改变。
Important注意到,这里我们使用了
runtime = 'edge'
,在 Next.js 中,API Handler 有两种不同的运行时,默认为nodejs
,另一种则为edge
,edge
运行时比nodejs
效率更高效,并且借助 Vercel 边缘网络可以更快的服务用户,但是此环境下仅支持一些 Node.js 的核心模块,所以我们需要注意这一点。下面的例子中,我们都以 Edge Runtime 为例,在 Node.js 和 Edge 中对于请求的处理方式是不同的,例如在 Edge 中只能使用
fetch
模块去获取数据,而在 Node.js 中可以使用fs
模块去读取文件或者使用 XMLHTTPRequest 去请求外部数据。
资源加载
在 Edge 环境中,我们只能使用 fetch 去获取外部数据或者资源。
加载本地图片
我们可以使用 fetch
去加载一个本地的图片。
现在假设我们在同级目录下存在一个图片文件 next.png
。
需要注意的是,在导入图片时,我们使用了 new URL('./next.png', import.meta.url)
,这是因为在 Edge 环境中,我们无法使用相对路径去加载文件,所以我们需要使用 new URL
去获取文件的绝对路径。另外我们也无法使用 fs
或者直接 import
去加载文件。
获取到图片之后,我们可以直接使用 arrayBuffer
去获取图片的二进制数据,然后直接使用这个数据去渲染图片,这里直接把图片的二进制数据作为 src
属性传递给 img
标签,虽然会导致 TypeScript 报错,但是实际上是可以正常工作的。
我们可以传入 height
或者 width
任意一个值去对图片进行缩放。
Warning在对图片进行缩放时,需要注意图片的缩放比例保持整数,比如原图片高为
1024
,缩放后为512
,这是2x
缩放。如果缩放比例不是整数,会导致渲染之后的图片出现模糊和锯齿。
这一节的文档对应部分为:Open Graph (OG) Image Examples - using-a-local-image
获取远程字体
在 Vercel 的 Edge 环境中,每个函数的大小被限制为 1MiB(Hobby Plan)。但是任何一个包含常用汉字的字体都会在 3MiB 以上,所以我们可以利用 fetch
去获取远程的字体文件,然后使用这个字体文件去渲染文字,例如下面我们加载远程的小赖字体。
Important在 Vercel 中,入站流量和出站流量一样都会被计费,所以再生成动态 OG 时,请注意缓存已生成的图片,避免入站流量过大。
效果为
加载本地字体
和加载本地图片一样,我们也可以使用 fetch
去加载本地的字体文件。在上一节的基础上,我们只需要修改这些。
缓存
一般的,在生成的 OG 会被 Vercel 缓存。但是这个缓存的不可控性和 Vercel 的流量非常的昂贵。我们可以设置 OG 图片响应的 HTTP 缓存标头控制缓存的配置。
Important上面的例子是官方文档总提到的方法,但是在 Next.js v14.1.3 版本或跟旧的版本中(也可能存在与未来的版本),此方法不生效。
我们可以使用 middleware.js
去重写这个路径的响应。首先建立 src/middleware.ts
添加下面的代码。
上面的代码中,当路径命中 /og
,那么,重写响应,添加缓存标头。
另外,你也可以使用 vercel.json
去控制其他路径的 HTTP 标头,比使用 middleware.js
更加方便。这部分的内容可以在 缓存标头和利用边缘网络加速访问 了解更多。
参考
这节内容的对应文档位于:Open Graph (OG) Image Generation
OG 生成器的演练场可以访问 OG playground
上面的 DEMO 位于: nextjs-book/tree/main/demo/og
最后更新于 2024/7/26 16:15:59
本书还在编写中..
前往 https://innei.in/posts/tech/my-first-nextjs-book-here#comment 发表你的观点吧。