如何将结构化数据(JSON-LD)添加到Next.js网站中并进行验证
结构化数据对搜索引擎来说一直都非常重要。当搜索引擎读取你的页面时,它看到的是HTML代码:标题、段落、日期以及名称等等。 结构化数据能够直接告诉搜索引擎这些内容的含义。例如,这个页面是一篇文章,这是它的标题,这篇文章是由某个人撰写的,并且发布于某个特定的日期。 对我来说,搜索引擎优化并不是一个需要简单勾选的步骤。我希望自己创建的产品和网站能够被人们找到,并且在被找到之后也能被正确理解。 因此,只要合适,我就会在每一页中添加结构化数据。而且我认为,随着人工智能系统开始根据网页内容来回答问题,结构化数据的重要性只会越来越明显,而不会减弱。 在Next.js应用程序中,没有任何工具会自动为你生成这些
结构化数据对搜索引擎来说一直都非常重要。当搜索引擎读取你的页面时,它看到的是HTML代码:标题、段落、日期以及名称等等。
结构化数据能够直接告诉搜索引擎这些内容的含义。例如,这个页面是一篇文章,这是它的标题,这篇文章是由某个人撰写的,并且发布于某个特定的日期。
对我来说,搜索引擎优化并不是一个需要简单勾选的步骤。我希望自己创建的产品和网站能够被人们找到,并且在被找到之后也能被正确理解。
因此,只要合适,我就会在每一页中添加结构化数据。而且我认为,随着人工智能系统开始根据网页内容来回答问题,结构化数据的重要性只会越来越明显,而不会减弱。
在Next.js应用程序中,没有任何工具会自动为你生成这些结构化数据。你需要自己手动在需要添加这些数据的页面中插入一段JSON代码。
在这个教程中,你将了解什么是结构化数据,以及JSON-LD是如何工作的。随后,你还会学习如何在一个Next.js应用项目中使用结构化数据:包括如何创建一个可重复使用的`JsonLd`组件,这个组件可以安全地用于处理任何类型的数据;同时,你也会了解到如何在每次构建项目后验证这些结构化数据的正确性。
目录
先决条件
要跟随本文的步骤进行学习,您需要具备以下条件:
一个使用Next.js应用框架、App Router以及TypeScript开发的网站。本文中的代码是在Next.js 16.4.0和React 19.3版本上测试过的。
对服务器组件及动态路由有基本的了解。
需要安装
schema-dts包,该包能为结构化数据提供TypeScript类型定义。
请将schema-dts作为开发依赖项进行安装,因为它仅用于提供类型定义:
npm install -D schema-dts
示例中使用了博客数据。每当出现\Post()这个代码时,请使用您自己的数据源,比如内容管理系统、数据库或Markdown文件。
开发人员所需的结构化数据基础知识
如果您之前从未接触过结构化数据,那么这一部分的内容将帮助您理解后续的代码示例。
什么是结构化数据与JSON-LD
结构化数据是一种可供机器读取的信息描述方式。它能让搜索引擎直接了解“Jane Doe”是文章作者,“2026-09-01”是发表日期,而无需用户去猜测这些信息。
所使用的术语来源于Schema.org——这是一个定义了各种数据类型(如Article、Person和Organization)及其属性(如headline、author和datePublished)的公共词汇库。该标准由谷歌、微软、雅虎和Yandex共同推出,也是搜索引擎所期望使用的格式。
JSON-LD(用于链接数据的JavaScript对象表示法)就是一种编写结构化数据的方式。它是W3C标准,在网页中,它会被放在一个带有特定类型的标签中:
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "Article", "headline": "..." }
</script>
浏览器并不会执行这段脚本。由于JSON-LD不属于JavaScript类型,因此这个标签会被HTML标准视为“数据块”,即“不会由用户代理处理,而是由开发者编写的脚本或其他工具来处理”。
除了JSON-LD之外,还有两种格式:Microdata和RDFa,它们都是通过为现有的HTML元素添加属性来实现结构化数据描述的。谷歌支持这三种格式,但建议在条件允许的情况下使用JSON-LD。对于React开发者来说,JSON-LD也是更合适的选择——因为它是一种基于数据生成的纯对象形式,与用于渲染页面的JSX代码是分离的。
如何构建JSON-LD数据块
以下是一个博客文章对应的JSON-LD数据块的示例:
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Next.js中的缓存机制是如何工作的",
"datePublished": "2026-09-01T09:00:00.000Z",
"author": {
"@type": "Person",
"name": "Jane Doe"
},
"publisher": {
"@type": "Organization",
"@id": "https://example.com/#organization",
"name": "Example Dev Blog"
}
}
以@开头的键是JSON-LD关键字,其余的则是Schema.org属性:
@context用于说明这些名称来源于哪种词汇表。对于Schema.org来说,这个词汇表就是https://schema.org。@type用于说明这是什么类型的实体。BlogPosting其实是Schema.org中Article这一类型的更具体的子类型。headline、datePublished和author都属于这种类型的属性。一个属性可以包含文本、日期、URL,或者另一个结构化对象,比如author属性中包含的Person>对象。@id为某个实体赋予一个唯一的标识符,通常是一个带有#片段的URL。在这里,它用来表示当前页面上的发布者与首页上另一个使用相同@id标记的实体属于同一个组织。
在接下来的代码中,你会用到这四个概念。
结构化数据、JSON-LD、Schema.org与丰富搜索结果
这四个术语经常被人们混淆,下面来说明它们之间的关系:
| 术语 | 含义 |
|---|---|
| 结构化数据 | 定义:一种可供机器读取的页面描述方式。 |
| Schema.org | 定义:一套可供使用的类型与属性词汇表。 |
| JSON-LD | 定义:将这种描述格式化后写入页面的具体方式。 |
| 丰富搜索结果 | 定义:谷歌搜索提供的一种功能,通过结构化数据使页面显示更丰富的信息,例如面包屑导航路径、产品价格和评价等。 |
简而言之,你使用Schema.org词汇表以JSON-LD格式编写结构化数据,而谷歌可能会利用这些数据来展示丰富搜索结果。
结构化数据对搜索的作用(以及它的局限性)
谷歌表示,它使用结构化数据“来理解页面的内容”,并收集与这些内容相关的人、书籍或公司的信息。同时,谷歌也会根据结构化数据来判断一个页面是否适合显示丰富搜索结果。
这里,“适合显示”是一个关键概念。即使JSON-LD格式正确,也不能保证一定能得到丰富搜索结果,原因有四个:
每种丰富搜索结果都有其特定的必需属性,这些属性会在谷歌的相关文档中列出。即便标记符合Schema.org规范,也可能遗漏某些必需属性。
是否显示丰富搜索结果由谷歌自行决定。它的结构化数据指南明确指出:“即使页面的标记完全正确,谷歌也不保证你的结构化数据一定会出现在搜索结果中。”
结构化标记必须描述页面上实际可见的内容。同样这些指南也提醒我们:“不要为页面上读者看不到的内容添加标记。”
有些类型的结构化数据已经不再能生成丰富搜索结果了。例如,谷歌在2026年5月7日停止了显示FAQ相关的丰富搜索结果,而在2023年也停止了显示操作指南相关的结果。
结构化数据也不会提升网站的排名。正如谷歌的约翰·穆勒在2025年所指出的:“结构化数据并不会让你的网站排名更高。”
那么人工智能搜索呢?谷歌表示,要出现在其人工智能搜索功能中,并不需要添加任何特殊的schema.org结构化数据。Bing的网站管理员指南也指出,结构化数据“虽然有助于提高信息的清晰度,但并不能保证网站能够被显示出来”。OpenAI、Anthropic和Perplexity等公司也没有在他们的文档中提及使用结构化数据;这些公司的爬虫使用说明主要关注的是爬虫如何访问网页内容,而非标记格式的问题。
目前关于人工智能搜索有很多宣传,其中一些确实是有根据的。但我的观点并不依赖于任何一家公司的承诺。
我希望我的内容能够被所有阅读它的系统清楚地理解,无论是搜索引擎还是人工智能工具。结构化数据是对页面内容的清晰、准确的描述,无论谁阅读它,这种格式都是有益的。只是不要把结构化数据当作一种获取人工智能搜索结果的捷径来使用。
在实际应用中,结构化数据的普及程度如何呢?根据我开发的网站审计工具Greadme发布的《2026年网站现状报告》,在387个被审核的首页中,有63%的页面包含了结构化数据。其中大部分数据格式都是正确的:91%的网站在验证过程中没有出现任何错误。
然而,仍有16%的网站使用了FAQPage这种类型的数据标签。而在2023年,谷歌曾将这种类型的结构化数据的使用范围限制在政府机构和健康相关网站,后来才取消了这一限制。虽然数据格式正确,并不意味着这些数据就有实际用途。
如何构建安全的JsonLd组件
Next.js的JSON-LD使用指南建议将结构化数据以标签的形式嵌入到layout.js或page.js文件中。你可以在需要使用结构化数据的页面上添加这个标签。不过,使用一个专门的组件会更为方便,因为这样可以将所有的标记格式规则集中放在一个地方。
创建components/JsonLd.tsx文件:
import type { Graph, Thing, WithContext } from "schema-dts";
type JsonLdData = WithContext | Graph;
export function serializeJsonLd(data: JsonLdData): string {
return JSON.stringify(data).replace(/</g, "\\u003c");
}
export function JsonLd({ data }: { data: JsonLdData }) {
return (
下面是各部分的功能说明:
JsonLdData这个类型来自schema-dts库。WithContext可以接受带有@context>属性的任何Schema.org数据类型,而Graph则可以接收包含多个数据类型的对象。在实际使用中,这两种类型都会被用到。serializeJsonLd函数会将这些数据转换为字符串形式,并将所有的<符号替换为\u003c字符。这样做的目的是为了确保数据在被插入到HTML页面中时,能够正确地被解析。dangerouslySetInnerHTML函数会将处理后的字符串直接写入到标签中。虽然这个函数的名称听起来有些危险,但实际上你可以完全控制输出的字符串内容,而通过使用转义字符,就可以确保从任何地方获取的数据都能被安全地显示在网页上。
该组件没有 `"use client"` 指令,因此它属于服务器端组件,而相关标签也是服务器发送的 HTML 中的一部分。
为什么不要使用 `next/script`?
Next.js 提供了一个 `Script` 组件,有些教程会用它来生成 JSON-LD 数据。但请不要这样做。JSON-LD 的官方指南明确指出,`next/script` “是专为加载和执行 JavaScript 代码而设计的”,而 JSON-LD 本身其实是一种数据结构。
更大的问题出现在 HTML 中。按照默认的 `afterInteractive` 处理策略,`Script` 组件的内容会被 “插入到 HTML 的客户端代码中”。我制作了一个页面,通过 `Script` 组件来渲染 `Product` 相关内容,并检查了 `next build` 命令生成后的 HTML 文件。
结果发现,生成的 HTML 中根本没有 `application/ld+json` 标签。那些 JSON 数据实际上只存在于 JavaScript 代码中,而 React 会在浏览器中读取这些 JavaScript 代码。
虽然 Google 仍然能够识别这些 JSON-LD 数据,因为它会读取 JavaScript 代码插入到页面中的 JSON-LD 内容。但任何仅解析 HTML 的工具都会看不到这些数据。如果直接使用普通的 `` 标签来嵌入数据,那么所有浏览器都能看到这些数据。
为什么转义字符很重要?
简单来说:`JSON.stringify` 可以生成有效的 JSON 数据,但这种格式并不适合直接插入 HTML 中。浏览器并不知道你的脚本中包含了 JSON 数据;它只会寻找 `` 标签来确定代码的结束位置,即使这些标签位于 JSON 字符串的中间也不例外。
假设产品名称是从内容管理系统中获取的,如果有人将其保存为如下格式的代码:
Blue Mug
使用普通的 `JSON.stringify` 方法后,服务器会发送如下内容的 HTML:
浏览器会将第一个 `` 标签视为 JSON 数据的结束位置,然后继续执行后面的普通 `