og-imageを使ってOGP画像を動的に作成する方法
現在はVercelから@vercel/og
がリリースされているのでそちらを使用するようにしてください!
Introducing OG Image Generation: Fast, dynamic social card images at the Edge
OGPを動的に生成する方法はimgixやcloudinaryなどいくつかありますが、手軽に始められる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
手順
- ホスティングまで
- 日本語化
- 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が開発している、日本語改行位置を自動的にいい感じに調整してくれるツールです。
こんな感じに調整してくれます。
インストール・使い方
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の導入も簡単でしたね。