YSLOW法则中,为什么yahoo推荐用GET代替POST?
原文:http://www.cnxct.com/use-get-for-ajax-requests-why/
背景:
上上周五,公司前端工程師培訓,提到前端優化的一些技巧,當然不能少了yahoo yslow的優化法則。其中有這么一條“Use GET for AJAX Requests”,這些法則從最開始的14條,到現在的35條,一直都時刻關注的。可這么一條的原因我卻一點都不清楚。在提問的環節里,我對yahoo WEB前端優化法則推薦AJAX中,使用GET代替POST的原因有疑問,便請教前端工程師。我們的工程師說GET的話,瀏覽器發送一個包,POST會發兩個等等。我對這個解釋仍帶有疑問,甚至懷疑。培訓結束后,我隨便搜索了一下,并沒有得到理想的結果,可能很少人對Yahoo這么有權威的組織提出的優化法則產生懷疑,也很少人想知道為什么建議這么做,更多的人會唯命是從,墨守成規。之后,我又看了遍優化法則,看到一條是推薦開發者使用AJAX緩存的,這時,一個“偉大”的想法在我腦袋中一閃,莫非是GET請求可以緩存,而POST不可以?接著,我把我這個“偉大”的猜測告訴我的同事們,當初已經是下班時間,好多同事都離開公司,我也匆忙收拾東西下班了,沒有仔細查找答案。
周末期間,腦袋中頻繁的閃現這個問題,仍對我的想法有懷疑,Yahoo前端這么牛X的團隊的想法,豈是我這樣的菜鳥能這么容易的猜測推斷到的?我對我當初的推測的懷疑就像“小時候就懷疑小JJ絕對不是只用來撒尿那么簡單”一樣堅定。但向我這么懶惰的同學,實在找不出一點時間來驗證我這個想法,空閑的時間寧愿多打幾盤CS。一直拖到現在,臺風來了,在家宅兩天,頭都睡扁了,也找不出不寫這篇文章的理由。
驗證Yahoo推薦的理由:
驗證XHR請求中yahoo推薦用GET代替POST做法的理由
POST is implemented in the browsers as a two-step process: sending the headers first, then sending data. So it’s best to use GET
POST請求分兩步:發送http headers,再發送http data
HTML+JS代碼:
<body>
<script src="jquery.1.3.2.js"></script>
<form method="post" action="">
<select name="option" id="option"><option value="POST" name="POST">POST</option><option value="GET" name="GET">GET</option>
</select><input id="button" type="button" value="POST提交">
</form>
<script language="JavaScript">
<!--
$('#button').click(function(){var option = $('#option').val();$.ajax({type: option,url:"cc.php",data: "name=cfc4n&option="+option,success: function(msg){alert(msg);}});
});
//-->
</script></body>抓包工具:wireshark
提示:wireshark(1.2.5版)在抓http包的時候,會默認合并packet reassembly選項,記得全部去掉。如下圖(edit–>Preferences)
?
wireshark去掉 packet reassembly選項
我分別發了一個GET、一個POST的XHR(XMLHttpRequest)請求,其數據包如下:
XHR HTTP請求中GET與POST發送的數據包詳情
如上圖,GET請求發送的數據包為第一個紅框內的結果;POST請求發送的數據包為第二個紅框內結果,但多了一個第12條數據包(粉紅色框內),從10.0.0.108(我的PC)發往98.126.129.106( www.cnxct.com的服務器IP,也就是表單提交的目標服務器IP),wireshark給出的信息是“ Continuation or non-HTTP traffic”,這個提示就是說,本次數據包是接著上一次的HTTP請求發的,沒有HTTP header,只有http data。
詳情如下圖
XHR HTTP POST請求的header部分數據:
XHR HTTP POST 請求的DATA部分:
結論?:
果然,如偉大的YAhoo前端團隊所說,XHR HTTP的POST請求會分為兩步,先發HTTP HEADER,再發HTTP DATA部分。
然而,新的疑問又來了。為什么要分為兩部?誰(例如W3C這種機構)規定的?每個瀏覽器都是這樣的么?分兩次比一次的的效率更高嗎?
繼續:
帶這我新的疑問,又進行了如下嘗試:先分瀏覽器,IE8、Firefox5.0、Chrome13分別發送XHR GET 、XHR POST請求,抓包對比結果。
我驚奇的發現(細心的同學會注意到第三張圖中,有橢圓形的框標出那些結果的瀏覽器是Chrome13),Firefox5發送POST的數據包確是沒有像yahoo前端優化法則中提到的那樣,分為兩次,兩個包發送,而是一次完成http headers和 http data的發送。如下圖:
firefox5在發送XHR POST請求時的數據包
大家可以從圖中看到 line-based text data:application/x-www-from-urlcoded下面就是POST的數據。
這時,又有很多疑問產生了,其他瀏覽器呢?IE的所有版本都會分兩次發么?Firefox的其他版本呢?
當我想一個一個嘗試抓包對比的同時,幸運的搜到了關于我這個疑問的PDF( Analysis_of_browser_specific_characteristics.pdf)
其中,提到firefox大部分版本在XP、WIN7、UBUNTU、MAC OS等系統上都是以1個包來實現的,其他常見瀏覽器都是分為兩個包。
相比大家很清楚的知道,HTTP(TCP)完成一次事物,通訊次數越多,越有可能出現故障(網絡延遲等因素),開銷越大,瀏覽器(客戶端)、服務端都要再進行一次TCP通訊,而且,需要一定的時間。對于我們追求更高的用戶體驗,需要HTTP通訊都避免到這些缺點,而各大瀏覽器開發商為何仍這么做呢?firefox的做法是最好的嗎?
上面的PDF里,模擬了各種網絡環境,比如網絡延遲、網絡丟包等情況,分別來對比POST請求的1次包和2次包的優缺點。得出的結論是:當網絡環境好的情況下,1次包跟2次包的在時間上差別基本可以無視。而在網絡環境差的情況下,(2次包)TCP的驗證數據包完整性上,有非常大的優點,客戶端先告訴服務端即將發送的數據包大小,MD5等標識,當服務端告訴客戶端收到(ACK包)的時候,客戶端再次向服務端發送POST 的DATA。假如網絡環境不好,網絡延遲、丟包的時候,服務端會等待(延遲時),客戶端重發POST的DATA數據到服務單,來確保本次請求的完整性。
撰寫這個PDF的作者在他的博客里詳細的描述了寫這個博客的起因,以及結果,還有一些關于與yahoo yslow前端團隊的一些溝通過程,大家可以在這里閱讀下(yahoo 的前端團隊好像不太友好,哈)。
結論:
通過參考這個PDF,以及我自己做的抓包測試,讓我了解Yahoo YSLOW前端團隊的這個推薦(他們沒詳細的說為啥這么推薦,只是簡單的提了下GET請求產生TCP一個包;POST請求,產生2個TCP包。甚至都沒告訴我們Firefox的多數版本[可能是所有版本]都是發一個TCP包的。更詳細、更深層原因也沒說,這里還得感謝下http://loadimpact.com的作者)。
備注:
這里提供下我抓包測試時候的數據包(截圖用到的數據包中包含我的一些cookie,沒上傳。這里的是我新抓的,各位見諒),各位可以參考下,如果我的文字、方向有錯,歡迎指出。
IE8、FF5、Chrome13發起XHR請求數據包
當你讀到這里時,我承認,我騙了你,文章的內容不光是標題中所寫的,為何推薦使用POST代替GET,更多的是抓去TCP、HTTP通訊包來驗證各個瀏覽器是否如YSLOW所述的那樣分2次包的過程,以及2次包與1次包的優缺點(PDF中)。希望你看到最后的時候,忘記標題講的是什么。
總結
以上是生活随笔為你收集整理的YSLOW法则中,为什么yahoo推荐用GET代替POST?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黄山风景区早上几点可以上山
- 下一篇: Facebook的实时Hadoop系统