morimorig3.com

og-imageを使ってOGP画像を動的に作成する方法

keyVisual
この記事の内容は古いです!

現在はVercelから@vercel/ogがリリースされているのでそちらを使用するようにしてください!

Introducing OG Image Generation: Fast, dynamic social card images at the Edge


OGPを動的に生成する方法はimgixcloudinaryなどいくつかありますが、手軽に始められるog-imageを紹介します。

この記事では主に、日本語化とBudouXの導入について解説します。og-imageの導入解説記事は先人が素晴らしいものを残してくれています。

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

vercel/og-imageをフォークして自分だけのOGP画像生成サービスを作ろう

og-imageとは

Next.jsを開発しているVercel社が提供する、動的にOpen Graph画像を生成するサービスです。

vercel/og-image: Open Graph Image as a Service - generate cards for Twitter, Facebook, Slack, etc

手順

  1. ホスティングまで
  2. 日本語化
  3. BudouX導入

ホスティングまで

vercel/og-image: Open Graph Image as a Service - generate cards for Twitter, Facebook, Slack, etc

デプロイの手順通り進めれば、Vercelでホスティングまでしてくれます。

日本語化

og-imageで日本語を表示に対応するためには、日本語フォントを導入する必要があります。ここではNotoを使用します。

フォントのデータが必要なので用意します。私は、サブセット化されているものを使用しました。

ixkaito/NotoSansJP-subset: Noto Sans JP サブセット (OTF, WOFF, WOFF 2.0)

ダウンロードしてきた、フォントファイルを_fontsフォルダーに格納してtemplate.tsで読み込ませます。

  const rglr = readFileSync(`${__dirname}/../_fonts/Inter-Regular.woff2`).toString("base64");
  const bold = readFileSync(`${__dirname}/../_fonts/Inter-Bold.woff2`).toString("base64");
  const mono = readFileSync(`${__dirname}/../_fonts/Vera-Mono.woff2`).toString("base64");
  const noto = readFileSync(`${__dirname}/../_fonts/NotoSansJP-Bold.woff2`).toString("base64");

あとはCssを出力しているgetCssの中で定義して使用するだけで完了です。

  function getCss(fontSize: string) {
    let foreground = "#333333";

    return `
    @font-face {
      font-family: 'Noto';
      font-style:  normal;
      font-weight: normal;
      src: url(data:font/woff2;charset=utf-8;base64,${noto}) format('woff2');
    }

    .heading {
      font-family: 'Noto', sans-serif;
      font-size: ${sanitizeHtml(fontSize)};
      font-weight: 700;
      color: ${foreground};
      line-height: 1.3;
      max-width: 1000px
    }
    `;
  }

BudouX導入

Webで問題になりがちな日本語の改行位置を調整します。BudouXはGoogleが開発している、日本語改行位置を自動的にいい感じに調整してくれるツールです。

こんな感じに調整してくれます。

ogp-before ビフォー

ogp-after アフター

インストール・使い方

BudouX 🍇

getHtmlの中でHTMLを出力して返り値に渡してあげると完了です。

  import { loadDefaultJapaneseParser } from "budoux";
...
  export function getHtml(parsedReq: ParsedRequest) {
    const { text, md, fontSize } = parsedReq;
    const parser = loadDefaultJapaneseParser();
    const title = parser.translateHTMLString(text);
    return `<!DOCTYPE html>
  <html>
    <meta charset="utf-8">
    <title>Generated Image</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
      ${getCss(fontSize)}
    </style>
    <body>
      <div class="grid">
        <div class="heading">${emojify(
          md ? marked(title) : sanitizeHtml(title)
        )}
        </div>
      </div>
    </body>
  </html>`;
  }

og-imageはHTMLページをレンダリングしてスクリーンショットを撮っているだけのようなのでBudouXの導入も簡単でしたね。

参考