Logo

Next.js 14で動的なOGP画像を設定する方法

Next.js 14で動的なOGP画像を設定する方法をご紹介します。

ブログを運用しているとブログ記事のタイトルやサムネイル画像をOGPとして動的に変えて表示したい要望があるかもしれません。以前の記事で静的なOGP画像を設定する方法をご紹介しましたが、今回は動的なOGP画像をNext.jsアプリケーションで設定する方法をご紹介します。

静的なOGP画像の設定方法については以下の記事をご覧ください。

環境

  • Next.js: ^14.2.5

動的なOGP画像を設定する

動的な画面と同じ階層にopengraph-image.tsx・twitter-image.tsxという名前のファイルを作成する

動的な画面にopengraph-image.tsx、twitter-image.tsxという名前でファイルを作成します。それによって指定した画面ではOGP画像やメタ情報を作成したファイルを基に生成することができます。

例えば、自分の環境ではブログ記事詳細画面は/articles/[slug]というルートになるので、以下のようになります。

ディレクトリ構造

ImageResponseを利用してカスタムコンポーネントを実装する

ファイルが作成できたら中身を実装していきます。

Next.jsではImageResponseというコンストラクターが提供されており、jsx(tsx)やcssで書いたコードを画像に変換することができます。(内部的にはsatoriというHTMLやCSSからSVGに変換するライブラリを使用しています。CSS記法にやや癖があります。)

以下のサンプルコードではブログ記事の詳細APIを取得してタイトルを動的に変換したOGP画像を生成しています。

サンプルコード

import { getDetail } from '@/libs/microcms';
import { ImageResponse } from 'next/og';

// Route segment config
export const runtime = 'edge';

// Image metadata
export const alt = "Blog by Yui Sato's Tech";
export const size = {
  width: 1200,
  height: 630,
};

export const contentType = 'image/png';

type Props = {
  params: {
    slug: string;
  };
};

// Image generation
export default async function Image({ params }: Props) {
  // 記事詳細データ取得
  const data = await getDetail(params.slug);

  return new ImageResponse(
    (
      // ImageResponse JSX element
      <div
        style={{
          fontSize: 36,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          backgroundImage: `url("${process.env.BASE_URL}/article-ogp-image.png")`,
          padding: '40px',
        }}
      >
        {data.title}
      </div>
    ),
    // ImageResponse options
    {
      ...size,
    },
  );
}

試しにSlackで確認してみると・・・

動的なOGPが表示できていることを確認できました。

一点注意点として、next/ogライブラリから提供されるImageResponseのフォントはデフォルトだとNoto Sans、Font-Weight: 400の1つのフォント形式しか提供されていないため、太字にしたりタイポグラフィを変えたい場合はカスタムフォントを別途追加して読み込ませる必要があります。(上記サンプルコードにはフォント設定はノイズになるため省略しています)

参考: Font weight not resolving correctly

カスタムフォントの設定方法についてはまた別の記事でご紹介したいと思います。

参考記事