December 30, 2023

Next.jsのサイトにOGPを動的に生成する

Next.js 13.3から導入されたopengraph-image という機能を使って動的にOGP画像を生成していきます。

今回はすべてのサイトで扱えるOGPを生成しますが、Next.jsにはX(Twitter)用の画像も用意できます。 その場合は、opengraph-imagetwitter-image に置き換えればそのまま利用可能です。

設定方法

静的OGP

opengraph-imageはもちろん動的に生成もできますが、静的にも生成可能です。
一番簡単な方法は画像ファイルを用意して任意のパスに配置する方法です。
対応している拡張子はこれら4つで .jpg, .jpeg, .png, .gif 、 画像を opengraph-image.jpg のようにリネームすればそのままOGPとして反映されます。

自分で作成している写真サイトAAkira.studio/app 配下に静的画像を配置して、トップページのOGPは固定にしています。
また、/app に配置しておくことで、opengraph-image.jpgがないパスの場合は自動でこの画像が使われます。

動的OGP

画像ではなくコードでOGPの設定をしていきます。
opengraph-image をtsxの拡張子で作成するとTypeScriptでOGPを生成できます。

関数名はなんでも良くて、export defaultで作成した関数が読み込まれます。
その他にも、altsize などをexport constで指定できます。
指定できるパラメータについてはドキュメントを参照してください。

ここでは ImageResponse クラスを使って画像を生成します。
ImageResponseには通常通りタグでレイアウトを定義しますが、style属性の指定にクセがありました。 ここは実際に触って色々確かめてください。

デバッグは localhost:3000/[ogp path]/opengraph-image のように任意のOGPを表示したいパスに opengraph-imageとつけると確認できます。
わざわざサーバーにアップロードしなくても確認できるためとても捗りました。

また、パスパラメータも取得可能です。
その場合は関数の引数に { params }: { params: { slug: string } } のように書くとパスパラメータを読み込めます。
もちろん複数パスも可能で、 app/shop/[tag]/[item]/ というパスだったらパラメータは { params }: { params: { tag: string; item: string; } } のようになります。

例)

import { ImageResponse } from 'next/og'
 
export const runtime = 'edge'
 
export const alt = 'About Acme'
export const size = {
  width: 1200,
  height: 630,
}
export const contentType = 'image/png'
 
export default async function Image({ params }: { params: { slug: string } }) {
  const post = await fetch(`https://.../posts/${params.slug}`).then((res) =>
    res.json()
  )
 
  return new ImageResponse(
    (
      <div
        style={{
          fontSize: 48,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        {post.title}
      </div>
    ),
    {
      ...size,
    }
  )
}

このように、通常のNext.jsの記法がつかえるので、SVGなどの読み込みも可能です。
私のサイトでは画像をCloudinaryにホスティングしているため、開いているページのパスから画像を判別して、動的に取得してOGPを生成しています。
最終的にはロゴのSVGと組み合わせてこのようになりました。

OGP Example

たったこれだけで、地味に面倒なOGP画像が作れて、管理もかなり楽なのでOGP画像がないサイトはすぐ作ることをおすすめします!

© AAkira 2023