generateMetadata + 动态 SEO

对于动态路由页面,需要根据实际内容生成动态的 metadata,而不是依赖全局配置。

为什么需要 generateMetadata

在真实项目中,仅靠全局 metadata 是远远不够的。

像课程页、课时页、博客页这类内容页面,通常都具备独立语义,例如:

  • /courses/[courseSlug]
  • /courses/[courseSlug]/lessons/[lessonSlug]

这两个页面显然不应该共用同一套SEO数据,需要各自有独立的title、description、canonical,甚至还需要单独生成 Open Graph 图片,Twitter 图片等。

这时候,就需要使用 generateMetadata,来根据当前路由参数和页面数据,动态生成 metadata。

Metadata 生成示例

最常见的写法如下:

import type { Metadata } from "next";

type Props = {
  params: Promise<{
    courseSlug: string;
  }>;
};

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { courseSlug } = await params;
  const course = await getCourseBySlug(supabaseStaticClient, courseSlug);
  return {
    title: course?.name,
    description: course?.description?.slice(0, 160),
    alternates: { canonical: `/courses/${courseSlug}` },
    openGraph: {
      images: [
        {
          url: `/courses/${courseSlug}/opengraph-image`,
          width: 1200,
          height: 630,
          alt: course?.name,
        },
      ],
    },
  };
}

export default function Page() {
  return <div>Course Page</div>;
}