上個星期天晚上約11點半,左耳朵耗子在新浪微博上吐槽QQ安全中心密碼修改的問題,引來不少圍觀。QQ安全中心的兄弟收到用戶反饋后,第一時間fix bug並發布,其高效着實令人佩服。
當時也圍觀了下,問題並不復雜,是由於業務代碼對於url的不恰當處理導致的(詳見本文第3點),涉及url fragment(#)的內容,於是順便重溫了下這塊的內容。
文章主要參考了httpwatch博客的一篇文章:《6 Things You Should Know About Fragment URLs》
其中1-5點的內容比較基礎,6-7點的內容對於ajax應用的開發有不錯的指導意義,可以了解下。
1、#右邊的字符,代表了一個頁面的特定位置
比如下面的url
http://www.example.com/index.html#casper
瀏覽器會尋找頁面里面,name屬性跟casper匹配的a標簽,並自動滾動定位到該位置,如下
<a name="casper">頁面會自動滾動到這個標簽所在的位置</a>
2、HTTP請求里,不會帶上#后面的部分
在地址欄里輸入http://www.cnblogs.com/#casper
,打開調試工具查看網絡請求,會發現#casper並沒有出現再網絡請求中,如圖所示
3、#后面的所有字符,都會被瀏覽當作位置標識符
關於這點,不少新手,包括老手,一不小心就掉坑里了。舉個最新的例子,前不就做耳朵耗子在微博上吐槽騰訊安全中心密碼修改的問題,如圖
果斷測試並抓了下包,一下就發現問題了:#后面的字符被截斷了,於是便得到了錯誤的校驗提示
https://aq.qq.com/cn2/ajax/get_psw_sgn?psw=Ae#ba234aaafff
4、改變#不會導致頁面重新加載,但是會改變瀏覽器歷史記錄
關於這點很容易測試,假設當前訪問的頁面是http://www.qq.com
,打開控制台,分別輸入如下命令看下區別(是否刷新),然后,再查看window.history有什么區別(歷史記錄是否變化)
location.href += '#caper'; //頁面不會刷新
location.href += '?visitor=caper'; //頁面刷新
在普通的網頁瀏覽中,我們每點擊一個網頁鏈接,就會在瀏覽器歷史記錄中新增一條瀏覽記錄,並通過瀏覽器的導航功能輕松進行'上一步'、'下一步'的操作。
但對於ajax應用,url通常是不會變化的,尤其是單頁面應用。這也就意味着,用戶習以為常的瀏覽器導航功能(上一步、下一步)失去了作用,這在體驗上是比較糟糕的。通過#,開發者可以利用不同的id,標識當前頁面所處狀態,提升用戶體驗。
5、JS中可以通過window.location.hash來讀取或改變#的值
沒什么好講的,可結上一點簡單測試下 :)
6、谷歌的網絡蜘蛛默認會忽略#后面的內容
谷歌網絡蜘蛛負責爬取網頁的內容,以及網頁里面的鏈接,它們會成為google搜索索引的一部分。網絡蜘蛛會抓取並分析HTML,但由於它並不是瀏覽器程序,也沒有javascript引擎,頁面上用來加載顯示內容的javascript並不會被執行。因此,#后面的字符會被網絡蜘蛛忽視,只抓取#前面的內容,舉例:
鏈接一:http://www.cnblogs.com/#casper
鏈接二:http://www.cnblogs.com/#chyingp
對於網絡蜘蛛來說,鏈接一、鏈接二其實是一樣的,它只會抓取http://www.cnblogs.com
的內容,盡管兩個鏈接可能展示的是不同的內容
這點無論對於開發者,還是搜索引擎都是不利的,前者辛苦創作的內容(應用)少了很多被訪問的機會,而后者則失去了進一步豐富其內容索引的機會,特別是在ajax應用越來越多的今天。
為了解決這個問題,google提供了一個解決方案:hash bang,只要將#改成#!即可,實現大致為:當網絡蜘蛛遇到#!時候,會自動將#!identifier
轉成_escaped_fragment_=identifier
形式的參數,修改下之前的鏈接
鏈接一(新):http://www.cnblogs.com/#!casper
鏈接二(新):http://www.cnblogs.com/#!chyingp
在網絡蜘蛛眼里,上面的鏈接是這樣的
鏈接一(轉化后):http://www.cnblogs.com/?_escaped_fragment_=casper
鏈接二(轉化后):http://www.cnblogs.com/?_escaped_fragment_=chyingp
這里有兩個注意點:
- 將#改成!#告訴網絡蜘蛛:我們支持這個解決方案:hash bang
- 相應的,我們的應用也需要具備相應的支持能力,對於網絡蜘蛛帶escaped_fragment=casper的GET請求,需要能夠提供相應的網頁內容
更多內容,請參考:http://support.google.com/webmasters/bin/answer.py?hl=en&answer=174992
7、補充內容:hash bang的應用(注意這里的例子有些誤導)
看了網上不少這方面的內容,都是以twitter為例子,但由於中國的特殊國情,訪問twitter略麻煩,於是舉個離我們比較近的例子:QQ空間。
應該很多人都有在用QQ空間,打開QQ空間,並點擊“日志”,觀察下當前的url
http://user.qzone.qq.com/替換成自己的QQ號碼/infocenter#!app=2&via=QZ.HashRefresh&pos=catalog_list
可以發現,infocenter后面用的是#!,按照之前的講解,我們稍稍做下修改,回車訪問,證實我們的猜想。
http://user.qzone.qq.com/替換成自己的QQ號碼/infocenter?_escaped_fragment_=app=2&via=QZ.HashRefresh&pos=catalog_list
2013/04/02添加
重新測試了下,空間目前不支持_escaped_fragment_,因此即使加了這個參數,也是會定位到個人中心
1、空間加#!的原因
1)緩存考慮
2)為可能的索引優化做准備
2、沒支持_escaped_fragment_的原因:
非技術實現上的困難,因為目前的產品性質對於這塊優化的需求不大
這塊的例子,據說twitter是做了的,但得翻牆才能測試,先TODO一下。