You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js 13 App Router中添加Schema脚本?

问题:Next.js 13 /app路由中为每个页面添加Schema脚本

摘要

Next.js 13的/app路由中的layout和page组件改变了我们向<head>添加内容的方式。如何为每个页面添加Schema脚本?Next.js会自动将任何layout或page中的<head>标签合并为一个单独的<head>。

需求目标

和所有注重SEO的网站一样,我希望在每个页面的head中加入Schema脚本。

过往实现方式

通常,直接在<head>中编写即可,示例如下:

<!-- index.html -->
<head>
  <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      // ... 其余内容
    }
  </script>
</head>

而在Next.js的/pages目录中,实现方式略有不同。必须使用dangerouslySetInnerHTML属性,示例如下:

// index.tsx
import Head from 'next/head'
export default function Page() {
  return (
    <Head>
      <script id="schema" type="application/ld+json" dangerouslySetInnerHTML={{__html: `
        {
          "@context": "https://schema.org",
          // ... 其余内容
        }
      `}} />
    </Head>
  )
}

当前问题

现在引入/app路由后,我们有了全新的简化方式来设置元数据,无需通过next/head直接导入<head>组件。实际上,/app路由中不应再使用next/head组件。

那么问题来了:如何在每个页面中单独访问<head>添加Schema脚本?

我原本期望Next.js团队已经考虑到这一点,将Schema添加到新的metadata变量中,甚至单独设置一个变量,但目前看来他们似乎没有这样的计划。

我尝试在page中添加<head>,但遗憾的是它无法正确合并到全局<head>中。目前我能想到的唯一方法是为每个页面单独创建layout并添加Schema,但这样做非常麻烦。


解决方案

方法1:使用generateMetadata的scripts字段(推荐)

在Next.js 13.4+的/app路由中,可通过generateMetadata函数返回的scripts数组添加内联Schema脚本,会自动合并到页面<head>,支持服务器组件:

// app/[page]/page.tsx
import type { Metadata } from 'next'

export async function generateMetadata(): Promise<Metadata> {
  const schema = {
    "@context": "https://schema.org",
    "@type": "WebPage",
    "name": "当前页面名称",
    "description": "当前页面描述"
    // 其他Schema字段
  }

  return {
    scripts: [
      {
        id: 'page-schema',
        type: 'application/ld+json',
        dangerouslySetInnerHTML: JSON.stringify(schema)
      }
    ]
  }
}

export default function Page() {
  return <div>页面内容</div>
}

方法2:在页面组件中直接使用<head>标签

若需在客户端组件中动态生成Schema,可直接在页面里添加<head>标签,Next.js会自动合并所有layout和page中的<head>内容:

// app/[page]/page.tsx
'use client'

export default function Page() {
  const schema = {
    "@context": "https://schema.org",
    "@type": "WebPage",
    // 动态生成的Schema内容
  }

  return (
    <>
      <head>
        <script
          id="page-schema"
          type="application/ld+json"
          dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
        />
      </head>
      <div>页面内容</div>
    </>
  )
}

注意:服务器组件中直接在<head>写内联脚本需用dangerouslySetInnerHTML,不能直接在<script>标签内写JSON内容。

方法3:创建可复用的Schema组件

若多个页面需添加Schema,可封装通用组件,在每个页面导入并传入对应Schema数据:

// app/components/Schema.tsx
interface SchemaProps {
  data: Record<string, any>
  id?: string
}

export default function Schema({ data, id = 'page-schema' }: SchemaProps) {
  return (
    <head>
      <script
        id={id}
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
      />
    </head>
  )
}

页面中使用:

// app/[page]/page.tsx
import Schema from '@/app/components/Schema'

export default function Page() {
  const pageSchema = {
    "@context": "https://schema.org",
    "@type": "WebPage",
    // 当前页面的Schema数据
  }

  return (
    <>
      <Schema data={pageSchema} />
      <div>页面内容</div>
    </>
  )
}

内容的提问来源于stack exchange,提问作者andrilla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:43:11