為什么前端路由會成為 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 都還有別的路可以進来。
發現路径可以被前端改造,但不该只依赖前端。让不执行脚本的通道也能走通,是單頁站点最實际的兜底。