👏

Next.jsでOGP画像+ALTを動的に生成する

に公開

TL;DR

opengraph-image.tsxだけでは動的なALT設定は不可能
⭕️ opengraph-image.tsxでOGP画像作成 + generatemetadata()でALT生成 の合わせ技でALTも動的に設定可能!

背景

Next.jsではv13.3.0からOGP画像をコードで動的に生成できるようになりました。
opengraph-image.tsx(もしくはtwitter-image.tsx)をpage.tsxと同じ階層に置くだけでOGP画像を作成してくれるという優れものです。

具体的なコードを見てみましょう。

app/posts/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og'
 
export const alt = 'Image Description'; // 静的 ALT
export const size = { width: 1200, height: 630 };
export const contentType = 'image/png';
 
export default async function Image({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = await params;
  const post = await fetch(`https://.../posts/${slug}`).then(res => res.json());

  return new ImageResponse(
    <div style={{ display: "flex" }}>{post.title}</div>,
    { ...size }
  )
}

paramsを用いて引っ張ってきたデータで画像を生成し、altに"Image Description"を設定しているのが何となくわかりますね。
しかし、この方法ではparamsを用いたイメージ生成はできても、ALTの設定はできません。
altImage()の外側で定義しなければならないからです。
見た目は動的に変わるのにALTは全部同じ、これではアクセシビリティ的に良くありませんよね。。
今回はその解決方法を考えてみました。

解決方法

以下のステップを踏むことでOGP画像に動的にALTを設定することができました。

1.opengraph-image.tsxでOGP作成

前述した方法でOGP画像を生成します。
この時点で設定したALTは次のステップで上書きされるため適当なものにしておきましょう。

app/posts/[slug]/opengraph-image.tsx
 import { ImageResponse } from 'next/og'
 
 export const alt = 'tmp ALT'; // 上書きされる

 (前述と同じ)

2.generatemetadata()でALT設定

続いて、page.tsxgenerateMetadata()を使ってALTを設定します。
この時、image.urlには表示させたい画像の絶対パスを指定する必要がありますが、opengraph-image.tsxで作成されたOGP画像はapp/posts/[slug]/opengraph-imageに作成されるため、それを指定すればOKです。

app/posts/[slug]/opengraph-image.tsx
export async function generateMetadata({
 params,
 }: {
 params: Promise<{ slug: string }>;
 }): Promise<Metadata> {
 const { slug } = await params;
 
 // opengraph-image.tsxで作成されたOGP画像の絶対パス
 const ogImageUrl = `https:/posts/${slug}/opengraph-image`;
 
 // 上書きするALT
 const description = `${data.slug} の説明`;

 return {
     metadataBase: new URL(baseUrl),
     title: title,
     description: description,
     openGraph: {
     title: title,
     description: description,
     images: [
         {
         url: ogImageUrl,
         width: 1200,
         height: 630,
         alt: description, // ここでALTを上書きする
         },
     ],
     },
 };
 }

参考

https://nextjs.org/docs/app/api-reference/file-conventions/metadata/opengraph-image

https://nextjs.org/docs/app/api-reference/functions/generate-metadata#opengraph

Discussion