跳到主要内容

Next.js Metadata、SEO、sitemap 与 robots

如果把 SEO 理解成“改个 title”,放在 Next 项目里通常会太浅。

更完整的理解应该是:

  • 页面标题和描述
  • Open Graph / Twitter Card
  • canonical
  • robots
  • sitemap
  • manifest
  • 图标、OG 图、分享图
  • 动态页面的 metadata 生成方式

到了 App Router,这一整套已经被 Next 收成了官方 Metadata API 和 metadata file conventions。

先看最核心的两条线

1. metadata / generateMetadata

用来定义页面或布局的 <head> 信息。

2. metadata files

用来定义一些特殊文件或资源,例如:

  • robots.ts
  • sitemap.ts
  • manifest.ts
  • opengraph-image.tsx
  • icon.tsx

这两条线一起组成了现代 Next 项目里最常见的 SEO 和分享能力。

metadata 适合静态信息

import type { Metadata } from 'next';

export const metadata: Metadata = {
title: 'Docs',
description: 'Project documentation',
};

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

这适合:

  • 固定标题
  • 固定描述
  • 固定分享信息
  • 稳定页面段落

generateMetadata 适合动态信息

import type { Metadata } from 'next';

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

return {
title: post.title,
description: post.summary,
};
}

适合:

  • 博客详情页
  • 商品详情页
  • 用户资料页
  • 动态内容型页面

一个关键点是:generateMetadata 本身就是渲染的一部分。如果页面还能预渲染,而且 metadata 逻辑没有引入真正的动态行为,结果仍然可以进首屏 HTML。

这套 API 的边界

官方文档明确说明:

  • metadatagenerateMetadata 只支持 Server Components
  • 它们不是给 client component 用的

这很合理,因为 <head> 管理本来就更适合在服务端模型里完成。

最常见的 metadata 字段

标题与描述

export const metadata = {
title: 'Next.js Guide',
description: 'A detailed Next.js knowledge base',
};

metadataBase

export const metadata = {
metadataBase: new URL('https://example.com'),
};

这个字段很重要,因为很多相对路径 metadata 最终都要基于它展开。

Open Graph

export const metadata = {
openGraph: {
title: 'Next.js Guide',
description: 'A detailed Next.js knowledge base',
url: 'https://example.com/docs/next',
siteName: 'Example',
images: [
{
url: '/og/next.png',
width: 1200,
height: 630,
alt: 'Next.js Guide',
},
],
type: 'article',
},
};

Twitter Card

export const metadata = {
twitter: {
card: 'summary_large_image',
title: 'Next.js Guide',
description: 'A detailed Next.js knowledge base',
images: ['/og/next.png'],
},
};

canonical

export const metadata = {
alternates: {
canonical: 'https://example.com/docs/next',
},
};

这在多语言、分页、重复内容路径场景里尤其重要。

viewport 和旧字段的变化

较新的文档里,官方已经明确标注:

  • themeColormetadata 里已废弃
  • colorSchememetadata 里也已废弃

现在更推荐走 viewport 配置。

robots.ts 怎么理解

robots.ts 是一类特殊 metadata file。

import type { MetadataRoute } from 'next';

export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: ['/admin', '/private'],
},
sitemap: 'https://example.com/sitemap.xml',
};
}

它的价值主要是:

  • 明确告诉搜索引擎哪些路径该抓、哪些别抓
  • 把 sitemap 暴露给爬虫

常见误区是把它当成安全控制。实际上 robots.txt 只是爬虫协作协议,不是访问控制机制。

sitemap.ts 怎么理解

import type { MetadataRoute } from 'next';

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getPosts();

return [
{
url: 'https://example.com',
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
...posts.map((post) => ({
url: `https://example.com/blog/${post.slug}`,
lastModified: post.updatedAt,
changeFrequency: 'weekly' as const,
priority: 0.7,
})),
];
}

适合:

  • 文档站
  • 博客
  • 商品站点
  • 内容量较大的内容平台

较新的官方文档还提供了 generateSitemaps(),用来把超大站点拆成多份 sitemap。

manifest.ts

import type { MetadataRoute } from 'next';

export default function manifest(): MetadataRoute.Manifest {
return {
name: 'Example Docs',
short_name: 'Example',
description: 'Documentation site',
start_url: '/',
display: 'standalone',
background_color: '#ffffff',
theme_color: '#111111',
icons: [
{
src: '/icon-192.png',
sizes: '192x192',
type: 'image/png',
},
],
};
}

这和 SEO 不完全等价,但它常常和安装体验、PWA 外观、品牌感知放在一起整理,所以通常会归到这一组。

图标、OG 图、分享图

Next 还支持通过特殊文件约定处理:

  • favicon.ico
  • icon.png / icon.tsx
  • apple-icon.png
  • opengraph-image.png / opengraph-image.tsx
  • twitter-image.png / twitter-image.tsx

这类文件定义后,Next 会自动把相关 head 信息接起来。

动态页面里最容易踩的坑

1. canonical 和分享图没跟着动态路由变化

结果通常是:

  • 所有详情页看起来 title 不同
  • 但分享卡片或 canonical 还指向同一个固定地址

2. metadataBase 没设好

相对地址可能会在部署后生成错误链接。

3. sitemap 只放了静态页

内容型站点如果详情页没进 sitemap,抓取效率通常会差很多。

4. robots 当成权限控制

robots.txt 不能阻止真实访问,只能表达抓取建议。

一套比较稳的落地顺序

  1. 先在根布局补 metadataBase、全站 title template、description
  2. 再给关键详情页补 generateMetadata
  3. 再补 robots.tssitemap.ts
  4. 再补 OG 图、Twitter 图、manifest 和图标
  5. 最后处理多语言 canonical、分页 canonical、分区爬虫策略

常见页面类型怎么配

文档站

重点:

  • title template
  • canonical
  • sitemap
  • robots
  • OG 图

博客

重点:

  • 文章级 generateMetadata
  • 文章更新时间进 sitemap
  • article 类型的 openGraph

电商或商品站

重点:

  • 商品详情 metadata 动态生成
  • 分类与详情的 canonical
  • 大规模 sitemap 拆分

推荐继续往下看

  1. 图片、字体与第三方脚本
  2. 部署、自托管与 standalone

参考资料