PJAX 深入淺出

HTML5 History API


在講 pushState 之前,先來回顧一下 HTML History 的歷史操作功能

History

上一頁
history.back()
history.go(-1)

下一頁
history.forward()
history.go(1)

查看歷史瀏覽總數
window.history.length

HTML5 新增
history.pushState()
history.replaceState()


What is pushState ?

  1. pushState = history.pushState
  2. 它和 location.hash 相似
  3. 用來操作歷史瀏覽紀錄
  4. HTML5 在 history 事件新加入
    history.pushState()
    history.replaceState()

支援度


使用 history.pushState()後,會改變 XMLHttpRequest 時 HTTP 標頭中 referrer 的值。
referrer 會是創造 XMLHttpRequest 物件時的當前視窗文件(this)的 URL。

這樣可能不太瞭解什麼意思
來個範例看看

DEMO1

先連到此網址 http://mozilla.org/foo.html
打開 Chrome Develop Tools
輸入以下程式碼

history.pushState({ foo: "bar" }, "test", "bar.html");

可以看到網址列已經變成 https://www.mozilla.org/zh-TW/bar.html
此時隨便連到別的網站https://www.google.com.tw
再按上一頁
可以看到網址仍然是 https://www.mozilla.org/zh-TW/bar.html
但內容仍然跟原本的 http://mozilla.org/foo.html 一模一樣
但是我們沒有對連結特別去做處理
重整之後抓不到 bar.html 這個連結的資料
照理說應該會導到 404 頁面
但由於我們測試的頁面本來就是 404 頁面,所以看起來以為沒變其實它已經失去連結了

這就是 pushState 有趣的地方


DEMO2


先連到此網址 http://example.com/example.html
打開 Chrome Develop Tools
輸入以下程式碼

window.onpopstate = function(e) {
alert(JSON.stringify(e.state));
};
history.pushState({page: 1}, “title 1”, “?page=1”);
history.pushState({page: 2}, “title 2”, “?page=2”);
history.replaceState({page: 3}, “title 3”, “?page=3”);

我們給予一個 onpopstate 事件在我們換頁的時候能 alert 出 history.state 現在的值以讓我們驗證我們現在的狀態

接下來照順序一行一行輸入

history.back(); // alert {page: 1}
history.back(); // alert null
history.go(2); // alert {page: 3}

結果跟想像中的不太一樣
第二次的 history.back() 為什麼沒有跳出 {page: 2} 的結果?

可以往上看 DEMO2 的那張圖
得知 replaceState 會蓋掉上一次的 state 狀態
於是乎 {page: 2} 的狀態被蓋掉
只剩下 {page: 3} 且上一頁的狀態為 {page: 1}

AJAX With SEO

我們都知道,AJAX 動態資料很難被搜尋引擎搜尋到,必須經過重重的關卡與處理才能有一個好的 SEO 條件

GOOGLE

GOOGLE 做了一個方式,在網址列後方加上 #!

http://example.com#!1
搜尋引擎會由 GOOGLE 轉譯成
http://example.com/?_escaped_fragment_=1

Twiter

Twitter 曾經實行此計畫
將網址 http://twitter.com/ruanyf
改成 http://twitter.com/#!/ruanyf
但由於網址實在又臭又長,實行了大約半年就被使用者罵爆
於是就又改成其它方式了


Google建議 AJAX 使用 PushState而非 hashbang

Matt Cutts說Google對於兩者的AJAX方式都「能夠」處理,但是如果你使用PushState,對於抓取而言不需要特別處理,因此我們鼓勵使用PushState。

如我們之前所說的,不要太相信Google「能夠」處理各種Javascript,因為「能夠」處理與「願意」處理是兩回事。

因為Google需要處理太多事情,並且每處理一件事情都會耗費很多資源,例如電力、CPU、記憶體、儲存空間、時間 … 等等。因此如果你只是小咖的網站,但是使用很繁複的Javascript,Google可能花了很大力氣去抓取出來,但是最後發現只是一堆沒有人想看的垃圾,因此如果你不是天王級的網站,千萬不要相信Google「能夠」處理各種Javascript,你必須讓網站非常容易抓取。


PJAX(PJAX = pushState + ajax


PJAX 技術隨著 HTML5 的出現開始展露頭角
它擁有以下優點

  1. 更好的 SEO 優化
  2. 無整頁刷新動態改變 url
  3. 用戶體驗提升
  4. 減少重複的資源再次送出請求

誰在使用 PJAX 技術

  1. GitHub
  2. Facebook
  3. Twiter
  4. Youtube

可以這幾個業界龍頭網站看到,點選了內容連結,內容更新了,導覽列的狀態仍然存在,頁面也沒刷新,但是已經取得了別頁的資料,且重整也能取得此連結的頁面資訊 (深度連結)

現在追求快速的時代,重整頁面已經不敷需求,於是催生了 AJAX,但是我們又想要做更好的 SEO 搜尋,此時 PJAX 技術就是你的不二選擇