单页应用的 SEO:预渲染、结构化数据与站点地图 | 拾音
SPA 的收录困境
Vue 单页应用的首屏 HTML 只有一个空的 <div id="app">,标题、描述、正文都依赖 JavaScript 执行后生成。虽然主流搜索引擎已经能执行 JS,但抓取预算有限,社交平台的分享卡片更是完全不执行 JS。
为文章详情单独提供一条服务端路由。爬虫访问 /p/:slug 时,服务端读取文章并返回带完整 meta 的 HTML 外壳,浏览器端再挂载 Vue 应用:
<title>文章标题 | 拾音</title>
<meta name="description" content="摘要">
<meta property="og:title" content="文章标题">
<meta property="og:type" content="article">
<link rel="canonical" href="http://jyyyyy.com/p/slug">
这样既不引入完整的 SSR 复杂度,又能满足搜索与分享的需要。
方案二:结构化数据
在详情页注入 JSON-LD,帮助搜索引擎理解内容类型、作者与发布时间:
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "文章标题",
"datePublished": "2026-09-12",
"author": { "@type": "Person", "name": "Jy" }
}
方案三:sitemap 与 robots
/sitemap.xml 动态生成所有已发布文章、标签页与媒体详情页,并附带 lastmod;robots.txt 指向 sitemap,同时禁止抓取后台与 API。
<url>
<loc>http://jyyyyy.com/p/vue3-composition-api-refactor</loc>
<lastmod>2026-11-03</lastmod>
<changefreq>weekly</changefreq>
</url>
方案四:语义化 HTML
即便内容由 JS 渲染,结构仍然重要:每页唯一的 h1、层级正确的 h2/h3、<article> 与 <time datetime>、图片的 alt。这些是爬虫理解页面结构的基础。
效果
上线一个月后,站点在搜索引擎的收录页面从 3 条增长到 47 条,文章分享卡片能正确显示标题、摘要与封面图。Lighthouse 的 SEO 项保持 100 分。
小结
个人博客不需要为了 SEO 引入沉重的 SSR 框架。服务端 meta 注入 + 结构化数据 + sitemap 的组合成本低、收益直接,足以覆盖搜索引擎与社交平台的需要。