vercel/og-imageを使ったブログOGPの簡単自動生成

この記事は[DeNA 21 新卒 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/dena-21-shinsotsu)の8日目の記事です。


こんにちは、[@p1ass](https://twitter.com/p1ass)です。


皆さんはブログのOGP画像をどのように生成しているでしょうか？
以前の私はGIMPを使って手動で作成していたのですが、手動で作るのは手間で、どうにかして自動化できないかと模索していました

今回は、そんな中見つけた[vercel/og-image](https://github.com/vercel/og-image)というOSSを紹介します。vercel/og-imageを使えば、OGP画像を生成するサーバを簡単に作成できます。OGP画像の自動生成に興味のある方の参考になれば幸いです。

なお、この記事のスコープは**『URLやクエリパラメータを指定すると画像が返ってくる』**ところまでで、SPAでどう動的に表示させるかといった話は含んでいません。（[私のブログ](https://blog.p1ass.com)がHugoを使って静的に書き出しているからです）

## OGP画像生成に求めるもの

OGP画像生成に求める要件は人によって異なると思います。私の場合、ブログOGPの画像生成に求めるのは次の3点でした。

- タイトル文章から画像が自動生成される
- 記事ごとに個別の画像は不要
- デザインをカスタマイズできる

[私のブログ](https://blog.p1ass.com/)はバックエンドの記事が多いので、「個別の画像をOGPに入れたい」といった要件は不要です。タイトル文章から良い感じに生成されてくれたらOKです。

デザインはそこまで凝る予定はないですが、どうせなら自分オリジナルなものを作りたいです。

## vercel/og-iamgeの概要

要件を満たすものを調査する中で見つけたのが、[vercel/og-image](https://github.com/vercel/og-image)でした。vercel-ogimageはNext.jsで有名なVercel社が公開している"Open Graph Image as a Service"です。

![og-imageへのリンク](https://gh-card.dev/repos/vercel/og-image.svg)

vercel/og-iamgeは次のような特徴があります。

- URL・クエリパラメータを指定することで生成画像が変化
- テンプレートHTMLをいじることで自由に生成する画像のデザインを変更可能
- `vercel` コマンドで簡単にVercelにデプロイ
- Vercelにデプロイすると自動でCDNが設定

画像生成が簡単なのも便利ですが、**特にPaaSである[Vercel](https://vercel.com/)に簡単にデプロイできるところが魅力**で、Cloud Functionsなどで自前で構築するよりもはるかに簡単に運用できます。

画像生成の例は次の公式exampleから確認できます。
[https://og-image.vercel.app/](https://og-image.vercel.app/)

![スクリーンショット 2020-12-04 12.06.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191796/2c047f2c-07e1-a8af-8a69-a98946168e4a.png)


左のメニューからパラメータを変更することで、生成する画像が変化します。
また、画像をクリックすることで画像URLをコピーでき、どのようなパラメータがURLやクエリパラメータに渡っているのか確認できます。

**例: デフォルトで設定されている`Hello World`画像のURL**

`https://og-image.vercel.app/**Hello**%20World.png?theme=light&md=1&fontSize=100px&images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fvercel-triangle-black.svg`

詳しいデプロイ方法は[リポジトリのREADME](https://github.com/vercel/og-image)を参考にしてください。

## vercel/og-imageを使う上での注意点

vercel/og-imageを使う上でいくつかハマった点があるので共有します。

### 日本語フォントがない

Vercelにはデフォルトで日本語フォントが用意されていません。
[Google Fonts](https://fonts.google.com/)などからWebフォントを読み込むようにテンプレートを変更する必要があります。

https://github.com/p1ass/og-image/blob/main/api/_lib/template.ts#L25

### デフォルトのCache-Controlが1年

vercel/og-imageのデフォルトのCache-Controlは1年にセットされています。

```typescript
res.setHeader('Cache-Control', 'public, immutable, no-transform, s-maxage=31536000, max-age=31536000');
```

https://github.com/vercel/og-image/blob/main/api/index.ts#L22

[VercelのCDNはデプロイのたびにキャッシュがパージされる](https://vercel.com/docs/edge-network/caching)ので一見問題ないように思えます。
しかし、TwitterのOGPサーバがCache-Controlを見てOGPをキャッシュしているようで、**「デプロイしなおしてもTwitterで表示される画像が変わらない」**という問題が発生します。
この問題はTwitterの[Card Validator](https://cards-dev.twitter.com/validator)を使っても解決しないので非常に厄介です。

私は一度、日本語フォントがない状態で生成されたOGPがCache-Contorol1年でTwitterにキャッシュされてしまい、全てのOGPが真っ白になってしまいました。
対応としては、Cache-Controlを短くした後、画像URLにプレフィックスをつけてデプロイし直し、誤ってTwitterにキャッシュされた画像が使われないようにしました。


## 他のOGP画像生成方法との比較

vercel/og-imageにもOGP画像を生成する方法はいくつか存在します。
その中でよく聞く方法をピックアップしてみました。

### Cloud Functionsを使った画像生成

[FirebaseCloudFunctionsとcanvasだけで動的にOGP画像を生成し2020年を生き延びよう](https://qiita.com/_masaokb/items/4e5e7c91d3a582f60e5f)で紹介されている方法です。

metaタグにCloud FunctionsのURLを設定しているあたりはvercel/og-imageと同じです。画像のキャッシュのためにCloud Storageにキャッシュしているのが特徴です。

Vercelが無料なのは個人用途だけなので、会社で実装する場合はCloud Functionsの方がお金周りの観点から楽だと思います。

個人用途では、自分でデプロイパイプラインを構築する必要がないvercel/og-imageの方が楽に運用できるでしょう。

### Cloudinaryを使った画像生成

[Cloudinaryで動的にOGP画像を生成する方法](https://catnose99.com/cloudinary-dynamic-ogp-image/)で紹介されている手法です。

CloudinaryもVercelと同様に無料プランが用意されており、個人用途には有用です。
また、SaaSなので運用の手間が減るのもグッドポイントです。

テンプレートのカスタマイズの観点からだと、vercel/og-imageはHTMLが使えて柔軟性が高いので、少し凝ったデザインをしたいならvercel/og-imageの方が良いのではないでしょうか？
逆にそこまでこだわらないのなら、Cloudinaryを選択するのもアリだと思います。

## 最後に

この記事では、vercel/og-imageを中心にブログのOGP画像の生成方法について紹介しました。vercel/og-iamgeは本当に便利なのでぜひ使ってみてください！
「他にもこんなやり方があるよ」って方はTwitterやはてブなどでコメントしていただけると助かります。

明日の[DeNA 21 新卒 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/dena-21-shinsotsu)の担当はfiordさんです。

アドベントカレンダーの更新情報などは[DeNA 公式 Twitter アカウント @DeNAxTech](https://twitter.com/DeNAxTech) で発信しているのでこちらもぜひチェックしてみてください！Blog 記事だけでなく色々な勉強会での登壇資料も発信しています。
<a href="https://twitter.com/DeNAxTech?ref_src=twsrc%5Etfw" class="twitter-follow-button" data-size="large" data-lang="ja" data-show-count="false">Follow @DeNAxTech</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>