天天看點

YSLOW法則中,為什麼yahoo推薦用GET代替POST?

轉至:http://blog.csdn.net/21aspnet/article/details/6668868

背景:

上上周五,公司前端工程師教育訓練,提到前端優化的一些技巧,當然不能少了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代碼:

[html]

view plaincopy

  1.  <body>  
  2. <script src="jquery.1.3.2.js"></script>  
  3. <form method="post" action="">  
  4. <select name="option" id="option">  
  5.     <option value="POST" name="POST">POST</option>  
  6.     <option value="GET" name="GET">GET</option>  
  7. </select>  
  8.     <input  id="button"  type="button" value="POST送出">  
  9. </form>  
  10. <script language="JavaScript">  
  11. <!--  
  12. $('#button').click(function(){  
  13.     var option = $('#option').val();  
  14.     $.ajax({  
  15.         type: option,  
  16.         url:"cc.php",  
  17.         data: "name=cfc4n&option="+option,  
  18.         success: function(msg){  
  19.             alert(msg);  
  20.         }  
  21.     });  
  22. });  
  23. //-->  
  24. </script>  
  25.  </body>  

抓包工具:wireshark

提示:wireshark(1.2.5版)在抓http包的時候,會預設合并packet reassembly選項,記得全部去掉。如下圖(edit–>Preferences)

YSLOW法則中,為什麼yahoo推薦用GET代替POST?

wireshark去掉 packet reassembly選項

我分别發了一個GET、一個POST的XHR(XMLHttpRequest)請求,其資料包如下:

YSLOW法則中,為什麼yahoo推薦用GET代替POST?

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部分資料:

YSLOW法則中,為什麼yahoo推薦用GET代替POST?

XHR HTTP POST 請求的DATA部分:

YSLOW法則中,為什麼yahoo推薦用GET代替POST?

結論?:

果然,如偉大的YAhoo前端團隊所說,XHR HTTP的POST請求會分為兩步,先發HTTP HEADER,再發HTTP DATA部分。

然而,新的疑問又來了。為什麼要分為兩部?誰(例如W3C這種機構)規定的?每個浏覽器都是這樣的麼?分兩次比一次的的效率更高嗎?

繼續:

帶這我新的疑問,又進行了如下嘗試:先分浏覽器,IE8、Firefox5.0、Chrome13分别發送XHR GET 、XHR POST請求,抓包對比結果。

YSLOW法則中,為什麼yahoo推薦用GET代替POST?

我驚奇的發現(細心的同學會注意到第三張圖中,有橢圓形的框标出那些結果的浏覽器是Chrome13),Firefox5發送POST的資料包确是沒有像yahoo前端優化法則中提到的那樣,分為兩次,兩個包發送,而是一次完成http headers和 http data的發送。如下圖:

YSLOW法則中,為什麼yahoo推薦用GET代替POST?

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 的前端團隊好像不太友好,哈)。

繼續閱讀