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

服务端预构建时,SEO元数据必须在 HTML 文件生成阶段就写死进 <title></title> 和 <meta name="description"> 标签里,任何依赖客户端 JS 修改的行为对搜索引擎完全无效。
Next.js 中 generateMetadata 必须是异步 Server Component 函数
它在 SSG/SSR 阶段执行,返回的对象直接决定最终 HTML 的 <title></title>、<meta property="og:title"> 等内容。不能写成普通函数,也不能放在 Client Component 里。
-
generateMetadata接收{ params, searchParams },可直接读取路由参数,无需手动解析useRouter() - 若数据源(如 CMS API)不可用,应调用
notFound()或redirect(),而非返回空字符串或 fallback 文本 - 不支持自定义
<meta name="robots">字段,需走other: { robots: "noindex" } - 返回的
title是字符串或 React Node,但后者在 SSG 下可能触发 hydration mismatch,建议统一用字符串
PHP 静态化站点中变量必须前置声明且转义输出
每个页面顶部第一行就要完成 $page_title、$page_description 的赋值,否则 inc/head.php 里 <title><?php echo htmlspecialchars($page_title); ?></title> 会输出空或报错。
- 禁止把变量定义写在
后面,或分散在多个include中导致执行顺序错乱 - 必须用
htmlspecialchars($page_title, ENT_QUOTES, 'UTF-8'),否则用户输入的"或会破坏 HTML 结构 - 不要用
$_SERVER['REQUEST_URI']动态拼接 title——URL 规则一改,全站元数据就崩 - 描述截断要用
mb_strimwidth($text, 0, 150, '', 'UTF-8'),避免 UTF-8 中文被切开成乱码
Vite + Vue/React 项目需靠插件注入动态 meta
vite-plugin-html 的 meta 选项只接受静态对象,无法按页面差异化。真正可行的是用 templateParameters 钩子为每个入口传入专属元数据对象。
- 在
vite.config.ts中为每个HtmlWebpackPlugin实例配置独立的templateParameters - 模板(如
index.ejs)中通过输出,而非依赖插件内置的meta - 避免在
webpack.config.js里写if (entry === 'blog')这类硬编码判断,污染构建配置且不可维护 - 若页面路径含中文或特殊字符,
canonical必须用new URL(path, origin).href生成绝对 URL,不能拼接相对路径
canonical 标签必须按页面逻辑推导,不是写死或重定向替代品
当同一内容可通过 /blog?id=123 和 /blog/123 访问时,两个预构建页面的 <link rel="canonical"> 必须各自指向 clean path(如 /blog/123),否则搜索引擎会判定为重复内容。
- 错误:所有页面都写
href="/blog/123"—— 导致/blog?id=123页面失去存在意义 - 错误:用相对路径
href="/blog/123"—— 部署在子路径(如/link/xxx)时会被解析成错误的绝对地址 - 正确做法:在构建时根据当前页面路径规则映射出规范 URL,例如将 query 参数路径统一转为 slug 形式
- Open Graph 图片必须与页面内容严格一致,否则社交平台分享时抓取到的仍是占位图或上一页的缩略图
最常被忽略的一点是:元数据是否真的出现在构建产物的 HTML 源码里。打开 dist/index.html 直接搜索 <title></title>,如果看到的是 <title>Loading</title> 或空值,说明整个链路没打通——不是框架问题,是数据没传进构建上下文。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











