📛

@vercel/ogとCloudflare Pages FunctionsでOGP画像生成APIをつくる

2024/05/30に公開

Cloudflare上にOGP画像生成APIをつくってみたので備忘録としてまとめます。

予備知識

OGP画像生成APIをつくる

動かして確認する

まずはサンプルリポジトリのOGP画像生成APIをローカルで動かしてみます。

$ npm ci

$ npm run dev
...
[wrangler:inf] Ready on http://localhost:8088
⎔ Starting local server...

コマンドを実行したらOGP画像生成用のエンドポイントにアクセスしてみます。
http://localhost:8088/ogp
サンプルOGP画像1こんな画像が表示されているはず
こんどはエンドポイントにtitleとavatarクエリをつけてアクセスします。avatarにはGithubのプロフィール画像を指定しました。
http://localhost:8088/ogp?title=OGPサンプル&avatar=https://avatars.githubusercontent.com/u/44719108
サンプルOGP画像2title,avatarクエリの内容が反映されたOGP画像

実装をみる

まずはhttp://localhost:8088/ogpにアクセスしたときに実行されるコードを確認します。Pages Functionsはファイルベースのルーティングとなっているため、http://localhost:8088/ogpにアクセスするとfunctions/ogp/index.tsxのコードが実行されます。

functions
└── ogp
    └── index.tsx

index.tsxではonRequest関数をexportして@vercel/ogのImageResponseを返すようにします。ImageResponseに定義したJSXがそのままOGP画像になります。
Open Graph (OG) Image Generation

functions/ogp/index.tsx
import { ImageResponse } from "@cloudflare/pages-plugin-vercel-og/api";
...

export const onRequest: PagesFunction = async (context) => {
  ...
  return new ImageResponse(
    /* JSXでレイアウトを定義 */
  )
}

contextからクエリの値など取得できるので動的に画像を生成することもできます。

functions/ogp/index.tsx
export const onRequest: PagesFunction = async (context) => {
  const url = new URL(context.request.url);
  const title = url.searchParams.get("title") ?? "OGP SAMPLE";
  const avatar = url.searchParams.get("avatar");
  ...

Cloudflareにデプロイする

CloudflareにアカウントがあればOGP画像生成APIをデプロイして動作を確認することもできます。
デプロイにはWranglerというCloudflareを操作するCLIを使います。さきほどのローカルでの動作確認にもWranglerを使っていました。

package.json
  ...
  "scripts": {
    "login": "wrangler login",
    "setup": "wrangler pages project create ogp-sample --production-branch main",
    "clean": "rm -rf .dist",
    "dev": "wrangler pages dev",
    "build": "npm run clean && wrangler pages functions build --outdir=.dist",
    "deploy": "npm run build && wrangler pages deploy",
    "destroy": "wrangler pages project delete ogp-sample"
  },
  "devDependencies": {
    "wrangler": "^3.57.1"
    ...

npm run deployを実行するとPages FunctionsをビルドしてCloudflareにデプロイするようnpmスクリプトを定義しました。初回の実行はプロジェクトを作成するか聞かれるのでそのままEnterを押してすすんでください。

# Cloudflareにログイン
$ npm run login

# Pages Functionsをデプロイ
$ npm run deploy
...
Compiled Worker successfully
The project you specified does not exist: "ogp-sample". Would you like to create it?"

# Enterを押す
❯ Create a new project

# Enterを押す
? Enter the production branch name: › main

...
🌎 Deploying...
✨ Deployment complete! Take a peek over at https://[デプロイ毎に固有の値].ogp-sample.pages.dev

デプロイ後に表示されるhttps://[デプロイ毎に固有の値].ogp-sample.pages.dev/ogpにアクセスするとローカルで確認したものと同じ画像が表示されるはずです(表示されない場合は少し待ってアクセスしてみてください)。

おまけ

画像に表示する文字列にカスタムフォントを適用することもできます。
http://localhost:8088/ogp/fontへアクセスするとNoto Sans JPフォントの太字でタイトルが表示されます。詳細はfunctions/ogp/font.tsxのコードを確認してください。
参考: @vercel/og を使って Next.js で OGP 画像を生成する仕組みを作ったお話
サンプルOGP画像3

Discussion