エッジで動的にOG画像を生成できる@vercel/ogを触ってみた
はじめに
Vercelからエッジで動的にOG画像を生成できる@vercel/og
が発表されました。
早速触ってみたいと思います。
@vercel/ogとは
Vercel Edge Functionsを使用して動的にOG画像を生成してくれます。
OG画像はHTMLとCSS(というかJSX)を使用して定義することができるので、特にReactエンジニアは非常に簡単にOG画像を定義できます。すごい。
コアエンジンにはSatoriというHTMLとCSSをSVGに変換するライブラリが使われています。
環境
-
@vercel/og
: 0.0.15 - Vercel Edge Functions
-
next
: ^12.2.3
触ってみた
実装は非常に簡単でAPI Routesにruntime: 'experimental-edge'
のエンドポイントを作成するだけでOKです。
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>
)
)
}
これだけで開発サーバーを起動して http://localhost:3000/api/og にアクセスするとOG画像を確認できます。
あとは任意のページにmeta
タグを配置すればOKです。
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',
}}
>
{title}
</div>
)
)
} catch (e) {
if (e instanceof Error) {
console.error(e.message)
}
return new Response(`Failed to generate the image`, {
status: 500,
})
}
}
Google Fontsを使用する
Google Fontsに限らず、ttf
, otf
, woff
形式のフォントファイルがサポートされています。
Google Fontsの場合は各フォントのページのDownload family
でダウンロードしたフォントファイルをassets
配下に格納してコードから読み込むことで使用することができます。
RobotoのBold 700を使用したい場合は以下のようにします(事前にフォントファイルをダウンロードしてRoboto-Bold.ttf
をassets
配下に格納しておいてください)。
import { ImageResponse } from '@vercel/og'
export const config = {
runtime: 'experimental-edge',
}
export default async function handler() {
const fontData = await fetch(
new URL('../../assets/Roboto-Bold.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/og
+Vercel Edge Functions+Next.jsの組み合わせであれば非常に簡単に動的にOG画像を生成できて驚きました。
エッジではなくNode.jsで使用したい場合はSatoriをそのまま使用することもできそうですし、これから盛り上がっていきそうだなと思いました。
また、公式ドキュメントに使用例やAPIの仕様が記載されているのでそちらも確認してみてください。
Discussion