📈

Nextjs ImageResponseで動的にOG画像を作成

2024/09/03に公開

ImageResponseとは

ImageResponseはNext.js 13から基本的に提供している機能で、OG(Open Graph)イメージに動的なイメージを生成してくれます。これでページことのogイメージを生成することができます。
※Next.js 13.4のリリースで、パフォーマンスの最適化と複数のCSSプロパティのサポートが追加された

メリット

サーバーサイドレンダリング: サーバーで画像を生成するため、クライアントのロード時間を短縮できる
動的データの反映: ブログポストのタイトルや説明など、動的なデータを画像に反映することで、コンテンツをより魅力的に見せることができる
コードの簡素化: 従来は外部ライブラリを使用する必要があるが、今は不要になった。

設定方法

slug]フォルダにopengraph-image.jsxファイルを追加し、ブログポストごとに異なるOG画像を生成できるようにします。

└── app
    ├── scr
    │   └── tips
    │       └── [slug]
    │           ├── page.jsx
    │           └── opengraph-image.jsx

opengraph-image.jsxで画像レスポンスを生成し、スタイルを設定します。

opengraph-image.jsx
import { getPostDataBySlug } from '@/app/api/tipsData';
import { ImageResponse } from 'next/og';

// Image metadata
export const size = {
  width: 1200,
  height: 630,
};

export const contentType = 'image/png';

export default async function Image({ params }) {
  const data = await getPostDataBySlug(params.slug);

  try {
    return new ImageResponse(
      (
        <div
          style={{
            width: '100%',
            height: '100%',
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            justifyContent: 'center',
            background: 'linear-gradient(to bottom right, #3978d1, #051b39)',
            borderRadius: '15px',
            overflow: 'hidden',
            position: 'relative',
            padding: '1.4rem',
          }}
        >
          
        </div>
      ),
      {
        ...size,
      },
    );
  } catch (error) {
    console.log(error);
    return null;
  }
}

CSSの設定が難しかった
すぐに確認できない点や、class名を使用できない点などが、、
ImageResponseで使用できるCSSは以下に記載されている。意外と使えるものと使えないものがあるようだ。
https://nextjs.org/docs/app/api-reference/functions/image-response
https://github.com/vercel/satori#css

[slug]/page.jsx
export const generateMetadata = async ({ params }) => {
...
openGraph: {
      images: [
        {
          url: `/tips/${params.slug}/opengraph-image`,
          alt: `${data.title.rendered}`,
          width: 1200,
          height: 630,
        },
      ],
    },
    twitter: {
      card: 'summary_large_image',
      title: `${data.title.rendered}`,
      description: data.excerpt.rendered,
      images: [
        {
          url: `/tips/${params.slug}/twitter-image`,
          alt: `${data.title.rendered}`,
        },
      ],
    },

Twitter用の画像もtwitter-image.jsxとして作成すれば使える!

感じた点

  • 内部画像や外部画像の使用制限: ImageResponseはサーバー側で画像を生成するため、/publicや/assetsフォルダにある画像を直接取得することはできないらしい。背景画像としてURLを使用するか、SVGコードを直接挿入したら良いと
  • リアルタイムプレビューの難しさ: スタイルを修正するたびにリロードする必要がある

結論

Next.jsのImageResponseを使用すれば、OG画像を動的に生成して、簡単にタイトルが入った画像を作成できます!ちなみに、画像サイズは2:1にすると画像が切れずに見やすくなるかも

Discussion