为什么前端路由会成为 URL 发现的盲区
多页站点的链接通常直接写在 HTML 源码里,搜索蜘蛛拿到文档就能顺着锚点继续走。单页应用不一样:首屏返回的 HTML 往往只是一个空壳容器,导航、列表、正文链接都是浏览器执行脚本之后才出现的。蜘蛛能不能拿到这些链接,取决于它有没有执行脚本、执行到哪一步、以及首屏是否留下了不依赖脚本的出口。
换句话说,URL 发现这件事,在前端路由结构里被从服务端搬到了客户端。链路变长,断点自然也变多。
三种常见的入口形态及其局限
纯客户端渲染
路由跳转靠 history API 或井号路由,链接节点由脚本生成。这类结构里,URL 的发现高度依赖渲染过程。风险在于:渲染超时、接口报错、脚本被拦截,都会让页面变成一个没有出口的死胡同——用户能点,蜘蛛走不动。
服务端渲染或预渲染
首屏带完整链接,抓取路径接近传统站点,是目前对发现相对友好的做法。需要注意的是,渲染层输出的链接要与源站实际存在的路径一致;如果渲染缓存过期或路由表与后端路径脱节,就可能出现“页面里有的链接,打开是 404”的情况。
Sitemap 与静态列表兜底
不管前端怎么渲染,Sitemap、RSS、分类页的静态化列表都是不执行脚本也能读到的发现通道。它们不一定提升抓取频次,但能保证 URL 至少有一个不依赖渲染的入口。前提是里面的路径要定期与线上实际路径核对,别让兜底本身成为过期清单。
几个容易忽略的细节
- 井号路由:井号后面的部分通常不会被当成独立 URL,同一路径可能只算一个页面。要做索引的路径,尽量用 history 模式。
- 直达链接返回 404:history 模式下,从外部直接打开深层路径时,服务器若没有配置回退到入口文件,会返回 404。蜘蛛拿到 404 就不会继续往下走。
- 点击事件代替链接:用可点击的容器加脚本跳转,人能用,但没有可提取的地址。能写成原生链接的位置,就写原生链接。
- 路由懒加载:首屏只加载当前页面,其他路由的入口要么出现在导航里,要么就完全没暴露。导航、面包屑、相关推荐这些位置,最好保留真实链接。
- 渲染接口被挡:渲染依赖的数据接口若对蜘蛛请求返回空或报错,渲染出来的仍是一个空页面,链接同样拿不到。
一套可以照着走的自检顺序
- 关闭浏览器脚本,打开首页和分类页,数一数首屏还剩多少个可以点的链接。
- 查看源码而不是渲染后的 DOM,确认链接是否出现在服务器返回的 HTML 里。
- 从日志里挑几个访问次数很少或从未出现的深层路径,手动直达,确认返回状态码与首屏内容正常。
- 核对 Sitemap 中的路径与前端路由表能否一一对应,避免出现只存在于路由表、却不在任何入口中的页面。
- 确认服务器的回退规则:任意深层路径直达都返回 200 且带首屏内容,而不是 404 或空白壳。
把入口做成冗余,而不是单点
前端路由本身没有问题,问题在于把发现的责任全压在渲染上。实际运营中比较稳的搭配是:导航和列表保持真实链接,Sitemap 覆盖全量路径,服务器保证直达可用。三件事各管一段,任何一段出问题,URL 都还有别的路可以进来。
发现路径可以被前端改造,但不该只依赖前端。让不执行脚本的通道也能走通,是单页站点最实际的兜底。