Next.js 里怎么正确设置页面的 SEO 标签?

迷人的岳阳 阅读 66

我用 Next.js 开发一个博客网站,想给每篇文章页面设置不同的 title 和 meta description,但发现直接在组件里写 <title> 标签好像没生效。官方文档提到用 next/head,但我试了之后在页面源码里看不到动态生成的标签,是不是 SSR 没处理好?

比如我这样写:

import Head from 'next/head';

export default function Post({ post }) {
  return (
    <>
      <Head>
        <title>{post.title}</title>
        <meta name="description" content={post.excerpt} />
      </Head>
      <article>{/* 内容 */}</article>
    </>
  );
}

但查看网页源代码时,title 还是默认的,meta 描述也没出现。是我用法不对,还是需要配合其他配置?

我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
Code°小敏
你的代码写法本身没问题,next/head 确实可以这么用。看不着动态标签一般是这几个原因:

1. 数据没拿到

最可能的情况是你以为 post 数据有了,但实际上可能是 undefined。检查一下你的 getStaticProps 或 getServerSideProps 返回的 props 对不对。要不先打个 console.log 看看:

export async function getStaticProps({ params }) {
const res = await fetch(/api/posts/${params.slug})
const post = await res.json()

return {
props: { post }, // 这里必须返回 post
}
}


如果 post 是空的,title 自然就是默认的。

2. 查看源码的方式不对

用浏览器 DevTools 的 Elements 面板看到的可能是 React hydration 之后的 DOM,不准确。右键 -> 查看网页源代码,这样看到的才是服务端渲染的 HTML,next/head 生成的标签应该在里面。

3. 默认 title 没配

你的 app 里面有没有配全局的 default title?如果没有,Next.js 可能会有奇怪的行为。可以在 _app.js 里加一个默认的:

import Head from 'next/head'

function MyApp({ Component, pageProps }) {
return (
<>

我的博客




)
}

export default MyApp


4. 如果你用的是新版 App Router(Next.js 13+)

那 next/head 已经不推荐用了,得用 Metadata API:

import { Metadata } from 'next'

export async function generateMetadata({ params }) {
const post = await getPost(params.slug)

return {
title: post.title,
description: post.excerpt,
}
}


你用的是 Pages Router 还是 App Router?先确认一下版本和路由方式,我再帮你看具体哪里的问题。
点赞
2026-03-12 08:16
一奥翔
一奥翔 Lv1
你的代码写法是 Pages Router(也就是 pages 目录)的标准写法,如果你现在的项目用的是 Next.js 13 以后的 App Router(即 app 目录),那 next/head 在这里是完全不起作用的,这就是你看不到标签的原因。官方文档明确指出,App Router 必须使用 Metadata API 来处理 SEO。

推荐的做法是,如果是静态页面或者简单的动态页面,直接在 page.jslayout.js 里导出 metadata 对象。如果你需要根据 post 数据动态生成标签,就得用 generateMetadata 这个异步函数。

举个例子,在 App Router 下,你应该这样写:

// app/blog/[slug]/page.js
export async function generateMetadata({ params }) {
// 这里获取你的 post 数据
const post = await getPost(params.slug);

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

export default function Post({ params }) {
// 页面组件内容
return
...
;
}


这样服务端渲染时会直接把标签注入 HTML,你在浏览器右键“查看网页源代码”就能看到了。

如果你确定自己还在用 Pages Router(pages 目录),那你那段代码其实是对的。这种情况下看不到标签,通常有两个原因:要么是 post 数据还没传过来导致渲染了空字符串,要么是你在浏览器 DevTools 里看了“Elements”面板而不是真正的“Page Source”。在 DevTools 里看的是渲染后的 DOM,有时候 hydration 过程会有延迟,但“查看网页源代码”看的是服务器返回的原始 HTML,那里如果有,说明 SEO 就没问题。

现在大部分新项目默认都是 App Router,建议先确认一下你的目录结构,别拿老皇历去套新框架,不然官方文档再全也救不回来。
点赞 3
2026-03-03 20:03