Vercel/og 是?

@vercel/og Vercel宣布可以在边缘动态生成 OG 图像。
什么意思呢?
我最近在项目里遇到一个需求,因为项目在澳大利亚上线的关系,每隔一段时间要过一次审查,每次审查需要对OG image进行修改文言,每次都要让前端进行修改,后来我们就在思考:

有没有什么办法?可以一劳永逸的自动更新图片呢?

这就是我们本次要介绍的vercel og的作用了。他是Vercel推出的一个根据Vercel Edge Functions动态生成 OG 图像的工具:

Vercel/og

由于 OG 图像可以使用 HTML 和 CSS(或者更确切地说,JSX或TSX)来定义,因此定义 OG 图像非常容易,特别是对于 React 工程师来说,这个效率是惊人的。

核心引擎使用一个名为Satori的库,它将 HTML 和 CSS 转换为 SVG来供使用。

环境

  • nextjs
  • Vercel Edge Functions
  • @Vercel/og

尝试

实现非常简单,runtime: 'experimental-edge'只需在 API 路由中创建一个端点即可。

nextjs的路由里有一个api的文件夹:
pages/api/og.tsx

import { ImageResponse } from '@vercel/og'

export const config = {
  runtime: 'experimental-edge',
}

export default function handler() {
  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          width: '100%',
          height: '100%',
          backgroundColor: 'white',
          fontSize: '128px',
        }}
      >
        Hello world!
      </div>
    )
  )
}

接下来启动服务器即可,我们就可以在localhost:3000/api/og访问到我们想要看到的图片了。

我们接下来要做的就是把他放到我们需要释放的地方,比如meta标签里,再比如Next的SEO组件里,根据实际需求来做:

import Head from 'next/head'

<Head>
  <title>Hello world</title>
  <meta
    key="og:image"
    property="og:image"
    content="https://example.com/api/og"
  />
</Head>

动态插入标题

https://example.com/api/og?title=hoge

您可以使用查询参数动态插入标题,如下所示

import { ImageResponse } from '@vercel/og'
import { NextRequest } from 'next/server'

export const config = {
  runtime: 'experimental-edge',
}

export default function handler(req: NextRequest) {
  try {
    const { searchParams } = new URL(req.url)
    const title = searchParams.get('title')?.slice(0, 100) ?? 'Hello world!'

    return new ImageResponse(
      (
        <div
          style={{
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            width: '100%',
            height: '100%',
            backgroundColor: 'white',
            fontSize: '128px',
          }}
        >
        {/* 这里应该就是hoge */}
          {title}
        </div>
      )
    )
  } catch (e) {
    if (e instanceof Error) {
      console.error(e.message)
    }
    return new Response(`Failed to generate the image`, {
      status: 500,
    })
  }
}

使用字体

根据我的实际操作,OG这个库本身只支持一个字体和粗细大小,其他的类型的字体需要我们手动导入,所以这边详细的阐述一下,导入字体的操作。

除了Google Fonts之外,还支持ttfotfwoff等格式的字体文件。

比如我想要导入Arial的字体。

import { ImageResponse } from '@vercel/og'

export const config = {
  runtime: 'experimental-edge',
}

export default async function handler() {
  const fontData = await fetch(
    new URL('../../assets/Arial.ttf', import.meta.url)
  ).then((res) => res.arrayBuffer())

  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          width: '100%',
          height: '100%',
          backgroundColor: 'white',
          fontFamily: '"Roboto"',
          fontWeight: 'bold',
          fontSize: '128px',
        }}
      >
        Hello world!
      </div>
    ),
    {
      fonts: [
        {
          name: 'Roboto',
          data: fontData,
          weight: 700,
          style: 'normal',
        },
      ],
    }
  )
}

这样一来就可以达到我们想要的效果了。

总结

这是我第一次尝试并且应用@vercel/og。
我很惊讶使用 Vercel + Edge Functions + Next.js的组合可以如此轻松地动态生成 OG 图像
如果你想使用 Node.js 而不是 Edge,似乎你可以直接使用Satori,我认为它将来会变得更流行。

另外,还请查看官方文档,其中包含使用示例和 API 规范:

Open Graph (OG) Image Generation Image Generation")

og-image-api

og-image-example

最后修改:2024 年 03 月 20 日
收款不要了,给孩子补充点点赞数吧