站点运营

站点运营:搜索蜘蛛的URL发现,从单页应用的前端路由说起

单页应用的页面切换靠前端路由完成,用户觉得顺滑,但蜘蛛看到的可能只有一张 HTML。本文讨论 hash 与 history 模式的区别、首屏源码里该如何保留真实链接,以及服务端渲染、预渲染和站点地图兜底的取舍。

站点运营

站点运营:搜索蜘蛛的URL发现,从单页应用的前端路由说起

用 Vue、React 或类似框架搭建的站点,页面切换靠前端路由完成,用户点起来很顺,但换到蜘蛛的视角,可能整站只看到一张 HTML。URL 发现的前提是页面上存在能被点开、能被解析的链接,单页应用恰好最容易在这个环节掉链子。

先分清 hash 模式和 history 模式

前端路由常见的两种写法,对 URL 发现的影响完全不同。

  • hash 模式:地址形如 example.com/#/news/123。井号后面的部分不会作为独立 URL 向服务器发起请求,蜘蛛即使拿到这个地址,抓到的也只是首页那份 HTML,后面那段路由信息基本等于没有。
  • history 模式:地址形如 example.com/news/123,是真实、可请求的 URL。只要服务器做了回退配置,让未匹配的路径返回应用入口,蜘蛛就能直接拿到页面。

所以如果内容页还在用 hash 路由,优先把它改成 history 模式,这是最基础的一步。

首屏 HTML 里有没有链接

换成 history 模式只是让 URL 变真,接下来还要回答一个问题:服务器返回的这份 HTML 里,有没有下一层内容的入口?

不少单页应用的入口 HTML 只有一个空容器,导航和列表全部由 JS 挂载。蜘蛛虽然越来越能执行 JS,但执行有预算、有超时,指望它把整站渲染一遍并不划算。更稳的做法是让入口 HTML 本身就带链接。

可以这样自查

  1. 用命令行请求一个栏目页,看看返回的源码里有没有指向内容页的 href。
  2. 在浏览器里关掉 JavaScript,看看还能不能点到下一层。
  3. 对照服务端日志,确认内容页的 URL 是否被单独请求过。
判断标准很简单:把 JS 关掉,如果页面上还能顺着点下去,URL 发现基本就没有大问题。

几种务实的处理方式

服务端渲染或预渲染

对导航、栏目列表这类关键路径做服务端渲染或预渲染,输出的 HTML 里直接带 a 标签。改造范围不用铺满全站,先把主干走通即可。

首屏先输出一批真实链接

列表页不必等接口返回全部数据再渲染。首屏可以先输出十几条真实链接,剩下的再用前端路由挂载。

路由懒加载别影响链接本身

按需加载组件没问题,但链接的 href 应该在 HTML 阶段就写好,而不是点击时才用脚本跳转。用 click 事件代替 a 标签,蜘蛛拿不到入口。

用站点地图兜底

服务端渲染成本较高时,至少让 XML 站点地图覆盖全部内容 URL,作为一条独立的发现通道。它不能替代内链,但能保证内容页不至于完全没人带路。

几个常见坑

  • 所有路由都返回 200。不存在的详情页也返回应用外壳,等于给蜘蛛递了一堆内容相同的页面。
  • 路由参数被无限拼接。筛选、排序、分页参数组合出来的 URL 数量可能远超真实内容。
  • 把导航写死在 JS 数组里。链接存在,但不出现在 HTML 中。
  • 只在页面底部放一个“加载更多”按钮,却不给对应的分页 URL。

单页应用不是不能被发现,而是要把“依赖 JS 才存在”的链接,变回“HTML 里就存在”的链接。这一层理顺了,抓取和收录才有继续讨论的余地。