Seo

元标签

如何在 Nebutra-Sailor 中设置静态和动态元数据——标题模板、Open Graph、Twitter 卡片、规范 URL、robots 指令,以及页面级与 layout 级元数据的区别。

Next.js 16 中元数据的工作原理

在 Next.js App Router 中,元数据从 page.tsxlayout.tsx 文件导出。Next.js 将最近的 layout.tsx 中的元数据与当前 page.tsx 中的元数据合并,页面级元数据在任何共同字段上优先。

有两种导出形式:

形式适用场景
export const metadata不依赖路由参数或外部数据的静态标题和描述
export async function generateMetadata()依赖路由参数、数据库查询或 CMS 内容的动态标题

标题模板

在根 layout 或分段 layout 中定义标题模板,使每个页面获得统一的后缀:

import type { Metadata } from "next";

export const metadata: Metadata = {
  title: {
    template: "%s | Nebutra",
    default: "Nebutra — AI 原生 SaaS 平台",
  },
  description:
    "使用 Nebutra 更快地构建和发布 AI 驱动的 SaaS 产品。",
};

子页面只需导出 title: "定价",渲染出的 <title> 就会变成 定价 | Nebutra

静态元数据示例

import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "定价",
  description:
    "简洁透明的定价方案。免费开始,按需升级。",
  openGraph: {
    title: "定价 — Nebutra",
    description: "简洁透明的定价方案。",
    url: "https://nebutra.com/zh/pricing",
    siteName: "Nebutra",
    images: [
      {
        url: "https://nebutra.com/og/pricing.png",
        width: 1200,
        height: 630,
        alt: "Nebutra 定价",
      },
    ],
    locale: "zh_CN",
    type: "website",
  },
  twitter: {
    card: "summary_large_image",
    title: "定价 — Nebutra",
    description: "简洁透明的定价方案。",
    images: ["https://nebutra.com/og/pricing.png"],
  },
};

使用 generateMetadata 实现动态元数据

对于在请求时获取内容的页面(如博客文章),使用 generateMetadata

import type { Metadata } from "next";
import { getPost } from "@/lib/sanity";
import { notFound } from "next/navigation";

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string; lang: string }>;
}): Promise<Metadata> {
  const { slug, lang } = await params;
  const post = await getPost(slug, lang);

  if (!post) return {};

  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      type: "article",
      publishedTime: post.publishedAt,
      authors: [post.author.name],
      images: [
        {
          url: post.ogImage,
          width: 1200,
          height: 630,
          alt: post.title,
        },
      ],
    },
    twitter: {
      card: "summary_large_image",
      title: post.title,
      description: post.excerpt,
      images: [post.ogImage],
    },
    alternates: {
      canonical: `https://nebutra.com/${lang}/blog/${slug}`,
    },
  };
}

在 Next.js 16 中,params 是一个 Promise。在读取值之前,请务必 await 它。跳过 await 会返回 undefined 并导致运行时错误。

规范 URL

在每个有明确 URL 的页面上设置 alternates.canonical。这可以防止当同一内容可通过多个路径访问时(如有无语言前缀)产生重复内容惩罚。

export const metadata: Metadata = {
  alternates: {
    canonical: "https://nebutra.com/zh/pricing",
    languages: {
      en: "https://nebutra.com/en/pricing",
      zh: "https://nebutra.com/zh/pricing",
      ja: "https://nebutra.com/ja/pricing",
    },
  },
};

languages 映射为每种语言生成 <link rel="alternate" hreflang="..."> 标签,搜索引擎使用这些标签向用户提供正确的语言版本。

robots 指令

使用 robots 元数据字段按页面控制爬虫访问:

// 默认 — 索引并跟随链接
export const metadata: Metadata = {
  robots: { index: true, follow: true },
};

// 阻止索引(如管理页面、草稿预览)
export const metadata: Metadata = {
  robots: { index: false, follow: false, noarchive: true },
};

根目录的 robots.ts 文件设置全站默认值。页面级 robots 元数据仅覆盖该页面的默认设置。

元数据字段参考

字段类型用途
titlestring | TemplateString页面标题。在 layout 中使用 template,在页面中使用普通字符串。
descriptionstring元描述。建议 120–160 个字符。
openGraph.titlestringOG 标题——可与 <title> 不同。
openGraph.descriptionstringOG 描述。
openGraph.imagesOGImage[]包含 urlwidthheightalt 的图片对象数组。
openGraph.typestring页面用 website,博客文章用 article
openGraph.publishedTimestringISO 8601 日期。仅用于 type: "article"
twitter.cardstring有主图的文章使用 summary_large_image
twitter.imagesstring[]Twitter 卡片图片 URL。
alternates.canonicalstring绝对规范 URL。
alternates.languagesRecord<string, string>i18n 页面的 hreflang 映射。
robotsRobots爬虫指令:indexfollownoarchive 等。

页面级 vs layout 级元数据

关注点设置位置
默认标题模板layout.tsx
全站描述回退值layout.tsx
全站 OG siteNamelayout.tsx
页面特定的标题和描述page.tsx
动态 OG 图片page.tsx,通过 generateMetadata
规范 URLpage.tsx
hreflangpage.tsx

切勿在 layout 中设置 openGraph.images——layout 级 OG 图片会被该分段中的每个页面继承,导致有自己 OG 图片的页面产生错误的社交预览。

相关文档

How is this guide?

目录