元数据必须在服务端首次输出的HTML中存在,因爬虫只解析初始HTML字符串、不执行JS,客户端动态注入的meta不会被索引;Next.js App Router需用generateMetadata异步生成并确保字段名正确、内容为字符串、路径为绝对URL。

服务端预构建(如静态生成、SSG)时,元数据必须在 HTML 初始响应中就存在,否则搜索引擎抓取到的就是空 description、空 og:title,SEO 直接失效。
为什么 SSR/SSG 里 meta 标签不能靠客户端 JS 补?
爬虫(尤其是 Googlebot)对 JS 执行有延迟、超时或跳过策略。你用 document.head.appendChild() 在 useEffect 或 window.onload 里加的 meta,大概率不会被索引 —— 它们只存在于浏览器运行时 DOM,不在原始 HTML 字符串里。
- Google Search Console 的「URL 检查」工具显示“已抓取但未渲染”,就是典型信号
- Next.js App Router 中若只用
useEffect改document.title,generateMetadata不定义,页面源码里就真没<title> - 即使框架支持 hydration,
<head>内容也必须由服务端首次输出,JS 只能做补充或微调(如 PWA 状态更新)
Next.js App Router 的 generateMetadata 怎么写才不踩坑?
这是当前最主流的 SSG 元数据控制方式,但字段名大小写、嵌套结构、异步逻辑都容易出错。
-
openGraph是合法字段名,opengraph或og都无效 → 最终不会输出<meta property="og:title"> -
description必须是字符串,不能是 Promise 或 undefined;若从 CMS API 异步 fetch,需在generateMetadata内await,且要有 fallback -
icons数组里每个对象必须含url(绝对路径)和type,相对路径会被忽略 - 动态路由参数(如
app/blog/[slug]/page.tsx)必须通过params参数解构获取,不能读useRouter().params
示例(正确):
立即学习“前端免费学习笔记(深入)”;
export async function generateMetadata({ params }: { params: { slug: string } }) {
const post = await getPostBySlug(params.slug);
return {
title: post.title,
description: post.excerpt?.slice(0, 155) || '缺省描述',
openGraph: {
title: post.title,
description: post.excerpt,
images: [{ url: `https://example.com${post.ogImage}` }],
},
};
}
Webpack + html-webpack-plugin 动态注入 meta 的边界在哪?
它适合构建时已知、无需运行时变化的元信息,比如站点基础配置。但无法处理 per-page 的动态内容(如文章摘要、用户生成标题)。
-
meta配置项只接受静态对象或函数,函数内不能await异步数据(Webpack 构建阶段不执行 Promise) - 若硬要在构建时拉 CMS 数据,需配合插件(如
webpack-plugin-remote-data),但会拖慢构建、增加失败风险 - 推荐组合:用
html-webpack-plugin固定charset、viewport、基础description;页面级元数据交由后端模板或运行时 SSR 处理 - 注意:
templateParameters注入的变量,必须在模板中用<%= description %>或类似语法显式输出,不能靠 JS 运行时补
PHP 静态站如何安全拼接 meta 而不 XSS?
无数据库 PHP 站点常用 include('head.php') 统一输出 <head>,但变量直插极易引发 XSS,尤其 og:url 和 description 来自 URL 或文件内容时。
- 所有输出到
content属性的变量,必须过htmlspecialchars($str, ENT_QUOTES, 'UTF-8') -
og:url要用https://绝对路径,不能用$_SERVER['REQUEST_URI']直接拼 —— 它可能带恶意 query 参数 - 避免在
head.php里写<?php echo $page_description ?>,而应封装成函数:<?php echo esc_meta_content($page_description); ?> - Open Graph 图片路径建议加哈希(如
og-image.jpg?v=abc123),防 CDN 缓存旧图
真正难的不是写对一行 <meta name="description">,而是确保它在 HTML 字节流的第一帧就出现、内容精准、且不被后续任何逻辑覆盖或清空 —— 这要求你清楚知道每个构建环节的输出时机和控制权归属。



















