Next.js 应用路由器中的技术 SEO:元数据、站点地图与 JSON-LD
了解共享元数据辅助工具、默认根布局、robots.ts文件、动态站点地图、规范的JSON-LD格式以及页面审计如何为Next.js应用奠定良好的SEO基础。
一个 Next.js 应用看似已经完成,但搜索引擎仍可能难以理解其内容:页面缺乏规范 URL,爬虫规则未定义,新内容也从未被加入站点地图。本指南以一个包含大量资源页面的模拟数据 API 网站为例,从首次 Lighthouse SEO 检测时的低分逐步提升至 100 分,展示了如何利用 App Router 内置的元数据 API 完成这七项改进。
通过一个辅助函数生成页面元数据
在每个页面中手动编写元数据容易导致问题,比如某个页面缺少规范 URL,另一个页面的 Open Graph 标题过时。一个简单的工具可以解决这个问题:每个页面只需提供标题、描述、路径以及可选的 noIndex 标志,该辅助函数便会将其扩展为规范 URL、机器人协议设置和 Open Graph 相关字段:
export function createPageMetadata({
title,
description,
path,
noIndex = false,
}: PageMetadata) {
return {
title,
description,
alternates: {
canonical: path,
},
robots: noIndex ? "noindex, nofollow" : "index, follow",
openGraph: {
title,
description,
url: path,
type: "website",
},
};
}
索引设置是可选的:通过一个标志即可将页面设置为noindex, nofollow状态。由于path是相对路径,该辅助功能依赖于根布局中定义的基准URL。
将全站默认值放在根布局中
所有需要在整个站点中共用的内容都应包含在layout.tsx的metadata导出中:
metadataBase- 标题模板
- 默认描述
- Open Graph默认设置
- Twitter卡片配置
- robots协议默认值
<html>元素上的lang属性
该导出的简化版本如下:
export const metadata: Metadata = {
metadataBase: new URL("https://mockdata.ir"),
title: {
default: "MockData",
template: "%s | MockData",
},
description: "...",
};
使用 %s | MockData 模板时,标题为“Users API”的页面会显示为“Users API | MockData”,而无标题的页面则使用 default 值。metadataBase 负责将辅助函数中的相对 canonical 和 Open Graph url 值转换为绝对 URL。需要注意的是,lang 并非元数据字段;应在布局渲染的 <html> 标签上设置该值。
使用 robots.ts 定义爬虫规则
无需让爬虫规则保持未定义状态,只需从返回类型为 MetadataRoute.Robots 对象的 app/robots.ts 文件中生成 robots.txt 即可:
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: "/",
},
sitemap: "https://mockdata.ir/sitemap.xml",
};
}
该文件被刻意设计得极为简单:所有用户代理均可爬取所有内容,同时还会标注站点地图的位置。
根据数据生成站点地图
由于存在针对用户、文章、产品等内容的资源页面,手动维护的 XML 站点地图难以扩展。sitemap.ts 的默认导出可以是 async 类型,这样它就可以查询这些页面所使用的同一数据源:
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const resources = await getPublicResources();
return [
{
url: "https://mockdata.ir",
lastModified: new Date(),
},
...resources.map((resource) => ({
url: `https://mockdata.ir/${resource.slug}`,
lastModified: resource.updatedAt,
})),
];
}
每个资源都会对应一个 URL,其中 updatedAt 被用作 lastModified,因此新的公开资源会自动加入站点地图。还有一个改进点:首页使用 new Date() 会声称每次生成时都有变化,而使用真实的内容时间戳则更为准确。
仅在确实需要时添加结构化数据
结合 Schema.org 词汇表的 JSON-LD 能让搜索引擎了解页面的含义。该应用本身被描述为 SoftwareApplication,所使用的类型包括:
WebSiteOrganizationSoftwareApplication
BreadcrumbList要追求准确性而非数量:标记内容必须描述页面上实际存在的元素。编造的评论、评分或其他虚构属性具有误导性,可能违反搜索引擎规范。
确保界面与结构化数据中的面包屑路径一致
嵌套的文档页面会显示如首页 → 文档 → 用户API这样的可见路径,而BreadcrumbList结构化数据也会输出相同的层级结构。可见路径与标记内容应始终描述同一结构。
手动审核每一个可索引页面
最后,需逐一检查每个公开页面:
- 它是否有且仅有一个明确的H1标题?
- 标题是否准确描述了该页面的内容?
- 描述内容是否与实际内容相符?
- 该页面是否有有用的内链指向其他页面或来自其他页面?
并非所有路径都适合出现在搜索结果中;使用noindex通常是正确的选择。关于标题结构,可参考这篇关于语义化HTML的指南以了解相关标记方法。
完美的Lighthouse SEO评分意味着什么以及不意味着什么
完成这些修复后,Lighthouse显示的SEO评分为100分。该分数用于检测标题、描述和可爬取性等技术基础问题,但与页面排名无关。排名取决于内容质量、用户搜索意图、网站权威性、外链数量、竞争情况、性能以及许多其他因素。
真正的价值在于打好了基础。在发布任何Next.js应用之前进行审计成本很低,却能发现许多小错误。
核心要点
- 将每页的元数据集中管理在辅助函数中,并在根布局中设置共享的默认值,包括
metadataBase。 - 使用
robots.ts和异步的sitemap.ts,以确保爬虫规则与URL能与数据保持同步。 - 仅添加能够真实描述页面的结构化数据,并确保界面与模式中的导航路径完全一致。
- 对于不应出现在搜索结果中的页面,可将
noindex视为一种合理的选择。 - 将Lighthouse评分100视为“技术上合格”,而非排名有保障的标志。