記一段SPA的SEO歷程:Html5 History Api 大顯神通!

背景

想當年,我作了一個新媒體網站項目(AIISPO,已下線)。跟普通資訊網站不同的是,老闆要求PC端前臺的文章閱讀模式必定得是瀑布流+模態框瀑布流指的是以瀑布流的形式將文章羅列出來,而模態框則指的是點擊瀑布流中表明文章的某個文塊時,直接在當前頁面彈出模態框來顯示文章正文。javascript

瀑布流式的文章列表

瀑布流式的文章列表

利用模態框直接顯示文章正文

點擊瀑布流的某個文塊後,直接在當前頁面彈出模態框來顯示正文以及文章相關內容,可依稀透過模態框背景看到底層的瀑布流。點擊模態框背景可關閉模態框,至關於回到瀑布流。
利用模態框直接顯示文章正文html

日常的開始

其時,我正癡迷於MVVM框架avalon,因而,理所固然地用avalon來渲染瀑布流的DOM樹。至於文章正文嘛,就用avalon給瀑布流中的各文塊綁定個click事件,順便把文章id給傳到click事件的callback裏,執行callback時就ajax讀一下文章正文,最後放到模態框裏顯示就是了。
至此,老闆要的「用戶體驗」就達成了,老闆誇我厲害還給我漲工資,我內心美美噠 n(≧▽≦)n前端

問題初現

官網上線了幾天,老闆給我提出了一個很是「實際」的問題,他無法把文章的網址分享出去呀,這是由於:官網原本就沒有獨立的文章頁面,更勿論文章的網址了!。當務之急是建立出可供分享的文章網址。java

Hashbang登場

老闆不接受「跳轉新頁面」打開文章正文的方案,堅持必定要瀑布流+模態框,我只好琢磨別的思路了。首先我試用window.location.href="/article/1",這是必定會使瀏覽器跳轉而沒法保持在當前頁面的,pass。接下來我查資料就搜到這Hashbang的方案:利用改變錨點#不會致使頁面跳轉這一特色,並加上!這一獨特的標識,造成形如http://aiispo.cn/#!/article/1的網址。ajax

具體的方案是這樣的:後端

  1. 大致上跟最初的方案一致。
  2. 不同的地方在於,打開模態框的同時window.location.href="/#!/article/1",這時地址欄的地址便變爲http://aiispo.cn/#!/article/1,也能保持不跳轉。
  3. 另外,給document.load綁上callback,也就是在頁面加載好後取當前的hash(window.location.hash),會獲得形如#!/article/1的字符串。正則匹配該字符串把文章ID取出,就能夠直接顯示文章正文了。
  4. 在關閉模態框時,應把地址欄恢復回來。

如此一來,用戶在閱讀文章時地址欄裏的正是文章的「網址」,而當用戶把網址分享給別人,別人複製到瀏覽器一打開,就能看到那篇文章了。老闆又誇我了,我內心又美美噠 n(≧▽≦)n瀏覽器

問題再現

官網上線月餘,百度僅收錄了首頁,我打開首頁的快照一看,可只有avalon的模板標籤,我一會兒就醒悟過來了:百度根本就沒能爬到任何的文章,由於首頁根本沒有任何文章的連接!
這時候我才意識到在SEO方面出了大問題了,這對一個新媒體網站來講但是致命的呀,把問題報告老闆後就趕忙開動腦筋想解決方案了。框架

小嚐試

把心一橫,把本來用avalon渲染的瀑布流,所有改回用PHP來渲染,同時給瀑布流的文塊加上<a>標籤,例如<a href="/#!/article/1">。因爲加上了<a>標籤,地址欄就不須要手動去改了。網站

問題未解

又過了幾天,各個搜索引擎仍是沒有動靜,我便又開始查資料:原來,國內的搜索引擎在抓取頁面的時候,是不執行js的。換句話說,搜索引擎從http://aiispo.cn/#!/article/1這樣的網址進去,只能看到瀑布流而看不到文章正文,由於文章正文是後面用js渲染的,不執行js就無法渲染,而瀑布流是用PHP渲染成html的,搜索引擎能看獲得。聽說Google是會執行js的,不過做爲一個國內的網站,仍是得優先保證國內的搜索引擎。this

Html5 History Api

思量良久,問題仍是出在文章沒有獨立的頁面上,另外Hashbang這種URL也不可靠,沒法被後端識別。痛定思痛,此次必定要完全解決問題。

改造以下:

  1. 仿照模態框的UI,我給作了文章的獨立頁面,URL形如http://aiispo.cn/article/1
  2. Hashbang不成,我就找其它能修改地址欄但不跳轉的方案,結果就找到了Html5 History Api

    1. 把瀑布流文塊裏的<a href="/#!/article/1">改成<a href="/article/1">
    2. 改這href會致使用戶點擊後跳轉,所以須要用js攔截<a>不讓其跳轉,並改成用window.history.pushState()來設置地址欄,此時用戶的地址欄應爲http://aiispo.cn/article/1
    $('#article-list a').on('click', function() {
      var url = $(this).attr('href');
      window.history.pushState(null, null, url);
      return false;
    });
    1. 照樣用正則匹配出文章ID,並用模態框顯示文章正文。

如此一來,便兼顧了三方的需求:

  1. SEO的需求,搜索引擎抓取瀑布流能抓到文章獨立頁面的URL(形如http://aiispo.cn/article/1),經過此URL進入文章獨立頁面能抓取到文章正文。
  2. 用戶體驗的需求,完美地保留了瀑布流+模態框的閱讀模式。
  3. 用戶分享文章網址的需求,用戶在瀑布流打開文章時,地址欄正是文章獨立頁面的URL。

兼容性修正

上述方案依賴於Html5 History Api,而IE9及如下版本都是不支持Html5 History Api的,須要進行兼容性修正。
在權衡利弊後,最終決定放棄IE9-用戶的用戶體驗

  1. 檢測當前瀏覽器是否支持Html5 History Api
  2. 不支持的話,就不攔截瀑布流文塊的<a href="/article/1">,也就是直接讓其跳轉。

總結

個人這套方案,本質上跟Prerender沒有區別,都是讓後端模擬前端渲染的方式生成一個獨立的頁面供搜索引擎抓取,既兼顧用戶體驗,又不失SEO

相關文章
相關標籤/搜索