このブログ、ISUCON 10 の予選の記事を書くに当たって、Netlify CMS + next.js Blog Template でデザインをとりあえずなんとかしたやつなんだけど、OGP 画像とかなんにもかんがえてなかったので無事死亡した。
デフォルト画像をとりあえず変えときゃいいかなとも思ったんだけど、どうせならちょっと作るかーということで、 puppeteer で OGP 画像を生成するようにしてみた。
https://github.com/macoshita/macoshita.me/blob/master/gen-og-image.ts
import path from "path";
import mkdirp from "mkdirp";
import puppeteer from "puppeteer";
import { fetchPostContent, PostContent } from "./src/lib/posts";
(async () => {
const ogImageDir = path.resolve(process.cwd(), "./dist/og-image/");
await mkdirp(ogImageDir);
const browser = await puppeteer.launch();
const page = await browser.newPage();
page.setViewport({ width: 1200, height: 630 });
await page.goto(
`file:${path.resolve(process.cwd(), "./og-image/index.html")}`
);
await page.waitForSelector(".wf-active");
for await (const post of fetchPostContent()) {
page.evaluate((post) => {
const p = JSON.parse(post) as PostContent;
const $ = (id: string): HTMLElement => document.getElementById(id)!;
$("title").innerText = p.title;
$("description").innerText = p.tags?.map((t) => `#${t}`).join(" ") ?? "";
}, JSON.stringify(post));
await page.screenshot({ path: path.join(ogImageDir, post.slug + ".png") });
}
await browser.close();
})().catch((e) => {
console.error(e);
process.exit(1);
});
やっていることは割と単純で、
waitForSelector('.wf-active')
多分、変更があったページだけに絞るとかしないといつか重すぎて死ぬ、、けどそのときはそのときで。スクショ撮るのはそんなに時間がかからないっぽいので、ぶっちゃけ 100 ページくらいまでは余裕なんじゃないかと思う。
スクショ用の html はこちら → https://github.com/macoshita/macoshita.me/blob/master/og-image/index.html
Ajax でローカルのファイルを取ってきたりをしてないので、今の所ローカルサーバ立てなくてもちゃんと表示できる。もし必要が出てきても、gen-og-image.ts でサーバ立ててスクショ取ってサーバ終了、でイケるはず。
大勝利した様子 ↓
原因不明だけどちゃんと動いていない。が、Netlify CMS の入力欄がいまいちすぎるので、早くも違うものを使いたくなってきたので、これ以上詰めるかはあやしい。なかなかブログ環境はいい感じに決まらない……。