generatemetadata 是 next.js app router 中唯一可靠的元数据注入方式,必须在 server component 中定义为异步函数,在 ssr/ssg 阶段执行,返回包含 title、description 等字段的对象,确保爬虫获取真实 html 中的元数据。

服务端预构建时,generateMetadata 是唯一可靠的元数据注入方式
Next.js App Router 中,generateMetadata 必须在 Server Component 中定义,且必须是异步函数——它在 SSR 或 SSG 阶段执行,爬虫拿到的就是最终渲染的 <title></title> 和 <meta> 标签。任何在客户端用 useEffect + document.title 修改的行为,对搜索引擎完全无效。
常见错误现象包括:页面显示标题正确,但 Google 查看源码发现仍是占位符(如 <title>Loading...</title>);或社交平台分享时抓取到空描述。
-
generateMetadata接收{ params, searchParams },可直接读取路由参数和查询字符串,无需额外解析 - 必须返回对象,支持
title、description、openGraph、twitter等字段,不支持自定义<meta>属性名(如name="robots"需走other字段) - 若数据请求失败,应抛出
notFound()或redirect(),不能返回空/默认值糊弄爬虫
PHP 静态站点中靠变量驱动元数据,require_once 统一入口是关键
无数据库的 PHP 站点(如产品单页、文档站),元数据靠 $page_title、$page_description 这类变量注入,但变量必须在 渲染前就已定义——否则输出为空或报错。
容易踩的坑是:把变量定义写在 后面,或分散在多个 include 文件里导致顺序混乱;还有直接 echo 变量却不做 htmlspecialchars() 转义,引发 XSS 或标签断裂。
- 每个页面顶部统一
require_once 'inc/page-config.php',该文件集中声明所有元数据变量 -
<title><?php echo htmlspecialchars($page_title); ?></title>必须出现在内,且不能有前置输出(如空格、BOM) - Open Graph 标签需用
property属性,不是name:<meta property="og:title" content="<?php echo htmlspecialchars($page_title); ?>">
<link rel="canonical"> 是处理动态 URL 的核心元数据,不是重定向替代品
当页面可通过多个路径访问(如 /product?id=123、/product/123、/en/product/123),meta refresh 不解决 SEO 问题,反而制造索引混乱。真正该用的是 <link rel="canonical">,它告诉搜索引擎“以这个 URL 为准”。
错误做法包括:写相对路径(href="/product/123"),导致不同子域下 canonical 解析错误;或让所有页面都指向首页,等于放弃长尾词。
- canonical 必须用绝对 URL:
<link rel="canonical" href="https://example.com/product/123"> - 服务端生成时,需根据当前请求动态计算规范地址,比如从
$_GET['id']构建,而不是硬编码 - 它不触发跳转,也不影响用户,只作用于爬虫——所以必须和服务端逻辑强绑定,不能靠 JS 注入
HTML 标题层级(<h1></h1>~<h6></h6>)必须在服务端直出,且仅一个 <h1></h1>
SEO 工具常报“缺失 <h1></h1>”或“多个 <h1></h1>”,根本原因在于:JS 动态插入的标题,爬虫看不到;而 CMS 模板嵌套、组件复用又容易让页头和正文各带一个 <h1></h1>。
例如 Next.js 中用 useEffect 设置 document.querySelector('h1').textContent = data.title,浏览器能看到,但 Googlebot 抓到的仍是初始 HTML 中的占位 <h1>Loading</h1>。
- SSR/SSG 页面中,
<h1></h1>必须由服务端直接写入 HTML,不能依赖客户端补全 - 每个页面只允许一个
<h1></h1>,且内容应自然包含搜索意图(如<h1>Vue 3 中 reactive 和 ref 的区别与使用场景</h1>) - 层级必须连续:
<h1></h1>→<h2></h2>→<h3></h3>,跳级(如<h1></h1>后直接<h3></h3>)会被视为结构缺陷
<title></title>、每一个 <link rel="canonical">、甚至第一个 <h1></h1>,都在 HTML 响应体里真实存在——爬虫不执行 JS,也不等你加载完 API。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











