静的生成でogp画像、投稿したblogのサムネ自動生成完了!!

投稿日

問題提起

前回で、SSRではogp画像の自動生成ができたが、SGではできなかった。

調べて、satoriというsvg生成するパッケージと、sharpというsvgをpngに変換するパッケージで、ogpを自動生成、ついでにそれをブログのサムネイル(アイキャッチを設定していないとき)にした。

コード

import satori from "satori";
import fs from "fs";
import sharp from "sharp";

// import { inter } from "/utils/fonts";
// import { Roboto, Noto_Sans_JP } from "next/font/google";

export default async function writeOgpImage(articleTitle, path) {
  if (!fs.existsSync(`public/writePngImg/${path}`))
    fs.mkdirSync(`public/writePngImg/${path}`);

  const image = await makeImg(articleTitle);
  fs.writeFileSync(`public/writePngImg/${path}/ogp.png`, image);
}

const makeImg = async function (title) {
  const roboto = fs.readFileSync("./makeImgAssets/Roboto-Regular.ttf");
  const notojp = fs.readFileSync("./makeImgAssets/NotoSansJP-Regular.ttf");
  const svg = await satori(
    <div
      style={{
        color: "black",
        background:
          "url(背景画像をmicrocmsに置き、絶対パスで記述しました)",
        backgroundSize: "1200px 800px",
        backgroundRepeat: "no-repeat",
        backgroundPosition: "right top",
        display: "flex",
        width: "100%",
        height: "100%",
        padding: "60px 30px",
        fontFamily: "Inter",
      }}
    >
      <div
        style={{
          fontSize: "48px",
          background: "rgba(255,255,255,0.8)",
          width: "100%",
          height: "100%",
          padding: "40px 20px",
          borderRadius: "8px",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          wordBreak: "auto-phrase",
          position: "relative",
        }}
      >
        {title}
        <p
          style={{
            fontSize: "32px",
            position: "absolute",
            bottom: "48px",
            right: "48px",
            display: "flex",
            alignItems: "center",
            gap: "4px",
          }}
        >
          <img
            style={{ display: "block", width: "50px", height: "50px" }}
            src="松の画像をmicrocmsに置き、絶対パスで記述しました"
            alt=""
          />
          松竹梅
        </p>
      </div>
    </div>,
    {
      width: 1200,
      height: 800,
      // embedFont: false,
      fonts: [
        {
          name: "robot",
          data: roboto,
        },
        {
          name: "NotoSansJP",
          data: notojp,
        },
      ],
    }
  );
  return sharp(Buffer.from(svg)).png().toBuffer();
};

上記を下記のようにgenerateStaticParams内で関数としていれると、開発環境で保存したらその時点で画像がフォルダに格納される。サムネやogpはそれを読み込むだけ

export async function generateStaticParams() {
  const allTitleSlugs = await getAllTitleAndSlugs();
  for (let i = 0; i < allTitleSlugs.length; i++) {
    await writeOgpImage(allTitleSlugs[i].title, allTitleSlugs[i].slug);
  }
  
    ・・・・
  return paths;
}

次はコードを見やすくするhighlightの導入