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