makenowjust-labs/blog

MakeNowJust Laboratory Tech Blog

OGP 画像の自動生成をする

2022-04-25

前々から課題として感じていた、このブログの OGP 画像の自動生成を実装しました。 OGP 画像は Twitter などの SNS にシェアするときに表示される画像です。

この記事では自動生成の実装や、skia-canvasbudoux といったライブラリを利用して、タイトルの自動改行や高速な生成を実現したので、それらについても解説します。

OGP

Twitter などの SNS にシェアするときに表示されるタイトルや画像・説明文を指定するための仕様として、 OGP (Open Graph Protocol) というものがあります。 HTML の <meta> タグを使ってこれらの情報を指定するもので、例えばこのブログのトップページであれば、次のような HTML タグが追加されています。

<meta property="og:title" content="makenowjust-labs/blog" />
<meta property="og:url" content="https://makenowjust-labs.github.io/blog/" />
<meta property="og:description" content="MakeNowJust Laboratory Tech Blog" />
<meta property="og:site_name" content="makenowjust-labs/blog" />
<meta property="og:type" content="blog" />
<meta
  property="og:image"
  content="https://makenowjust-labs.github.io/blog/cover.png"
/>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@make_now_just" />
<meta name="twitter:creator" content="@make_now_just" />

そして、これらの情報を元にこんな表示がされるわけです。

Twitter での表示のスクリーンショット

別にアクセス数を稼ぐことを目的としていないブログなのでどうでもいいのですが、このような表示があると親切なことは間違いないです。

それと、背景の画像は Unsplash からそれっぽいのを探してきました。 ありがとうございます。

OGP 画像の自動生成

OGP を設定するにあたって問題となるのが OGP 画像の生成です。 さきほどの例はトップページだからいいのですが、個々のブログ記事に対していちいち OGP 画像を用意するのは骨が折れます。 そこで OGP 画像を自動生成することを検討するわけですが、主に次の 2 つのような方法が考えられます。

  1. OGP 画像を動的に生成するサーバーを用意して、そちらで生成する。
  2. ブログのビルド時に OGP 画像を生成して、静的に配信する。

今回は 2 の方法を取ることにしました。 その理由は、Lambda などを使っても静的に配信するよりは面倒なことになりがちだからです。

また、1 の方法の実装としては vercel/og-image などが有名です。

自動生成の実装

自動生成は Next.js のビルドとは統合せずに、別のスクリプトとして実装して、npm scripts として実行するようにしています。 実装はこのスクリプトとなります。

実装には次のライブラリなどを使用しました。

それぞれについて解説します。

zx

zx は Google が公開している、JavaScript でシェルスクリプトのようなスクリプトを書きやすくするライブラリです。 今回のスクリプトでは外部コマンドの呼び出しをしていないので、単に ES Module が楽に使えて、fs などのパッケージがデフォルトで読み込まれているだけの何かになっている気がします。 別に使わなくてもよかったかもしれない‥‥。

skia-canvas

skia-canvas は Chrome などに使われている描画ライブラリ Skia の Node.js ラッパーで、HTML5 Canvas API を実装したものです。 同じく Node.js 上で HTML5 Canvas API を実装したライブラリとしては node-canvas がありますが、こちらよりも高速 (多分) でビルドが楽な気がします。

また、OGP 画像の自動生成では puppeteerplaywright を使って、ブラウザで描画したもののスクリーンショットを取る、という方法を使うことも多いのですが (vercel/og-image はこの方法を取っています)、 こうすると生成時間がかなり長くなってしまうため、レイアウトなどは大変ですが Canvas API を使う方法で実装することにしました。

fontsource

fontsource は Google Fonts などで配信されているフォントを NPM のパッケージとして公開しているプロジェクトです。 今回は OGP 画像中で使うフォントをインストールするために利用しました。 別にリポジトリにフォントファイルを入れてもいいのですが、このようにすることで多少管理が楽になるかと思い採用しています。

budoux

budoux は Google が公開している、文章の改行位置をいい感じに推定してくれるライブラリです。 skia-canvas には自動改行が実装されているのですが、あまり賢くなかったのでこのライブラリを利用しています。

ちなみに、英語が入るとあまり上手く改行位置を見つけてくれないみたいなので、事前に空白文字で分割する処理を入れています。

あとがき

課題だった OGP 画像の自動生成を実現できてよかったです。 完全に自己満足なのですが、Twitter などに記事をシェアするモチベーションが高まります。

記事を書いていて気付いたのですが、使用しているライブラリが Google にどっぷりな気がします。 Google に足を向けて眠れない‥‥。

というわけで、最後まで目を通していただきありがとうございました。