新聞資訊

[轉(zhuǎn)載]雅虎35條優(yōu)化黃金守則(二)

13、Gzip壓縮文件內(nèi)容 
  網(wǎng)絡(luò)傳輸中的HTTP請(qǐng)求和應(yīng)答時(shí)間可以通過前端機(jī)制得到顯著改善。的確,終端用戶的帶寬、互聯(lián)網(wǎng)提供者、與對(duì)等交換點(diǎn)的靠近程度等都不是網(wǎng)站開發(fā)者所能 決定的。但是還有其他因素影響著響應(yīng)時(shí)間。通過減小HTTP響應(yīng)的大小可以節(jié)省HTTP響應(yīng)時(shí)間。
  從HTTP/1.1開始,web客戶端都默認(rèn)支持HTTP請(qǐng)求中有Accept-Encoding文件頭的壓縮格式:   
      Accept-Encoding: gzip, deflate 
  如果web服務(wù)器在請(qǐng)求的文件頭中檢測(cè)到上面的代碼,就會(huì)以客戶端列出的方式壓縮響應(yīng)內(nèi)容。Web服務(wù)器把壓縮方式通過響應(yīng)文件頭中的Content- Encoding來返回給瀏覽器。
      Content-Encoding: gzip 
  Gzip是目前最流行也是最有效的壓縮方式。這是由GNU項(xiàng)目開發(fā)并通過RFC 1952來標(biāo)準(zhǔn)化的。另外僅有的一個(gè)壓縮格式是deflate,但是它的使用范圍有限效果也稍稍遜色。
  Gzip大概可以減少70%的響應(yīng)規(guī)模。目前大約有90%通過瀏覽器傳輸?shù)幕ヂ?lián)網(wǎng)交換支持gzip格式。如果你使用的是Apache,gzip模塊配置和 你的版本有關(guān):Apache 1.3使用mod_zip,而Apache 2.x使用moflate。
  瀏覽器和代理都會(huì)存在這樣的問題:瀏覽器期望收到的和實(shí)際接收到的內(nèi)容會(huì)存在不匹配的現(xiàn)象。幸好,這種特殊情況隨著舊式瀏覽器使用量的減少在減少。 Apache模塊會(huì)通過自動(dòng)添加適當(dāng)?shù)腣ary響應(yīng)文件頭來避免這種狀況的出現(xiàn)。
  服務(wù)器根據(jù)文件類型來選擇需要進(jìn)行g(shù)zip壓縮的文件,但是這過于限制了可壓縮的文件。大多數(shù)web服務(wù)器會(huì)壓縮HTML文檔。對(duì)腳本和樣式表進(jìn)行壓縮同 樣也是值得做的事情,但是很多web服務(wù)器都沒有這個(gè)功能。實(shí)際上,壓縮任何一個(gè)文本類型的響應(yīng),包括XML和JSON,都值得的。圖像和PDF文件由于 已經(jīng)壓縮過了所以不能再進(jìn)行g(shù)zip壓縮。如果試圖gizp壓縮這些文件的話不但會(huì)浪費(fèi)CPU資源還會(huì)增加文件的大小。 
   Gzip壓縮所有可能的文件類型是減少文件體積增加用戶體驗(yàn)的簡(jiǎn)單方法。


14、配置ETag 
  Entity tags(ETags)(實(shí)體標(biāo)簽)是web服務(wù)器和瀏覽器用于判斷瀏覽器緩存中的內(nèi)容和服務(wù)器中的原始內(nèi)容是否匹配的一種機(jī)制(“實(shí)體”就是所說的“內(nèi) 容”,包括圖片、腳本、樣式表等)。增加ETag為實(shí)體的驗(yàn)證提供了一個(gè)比使用“l(fā)ast-modified date(上次編輯時(shí)間)”更加靈活的機(jī)制。Etag是一個(gè)識(shí)別內(nèi)容版本號(hào)的唯一字符串。唯一的格式限制就是它必須包含在雙引號(hào)內(nèi)。原始服務(wù)器通過含有 ETag文件頭的響應(yīng)指定頁面內(nèi)容的ETag。 
      HTTP/1.1 200 OK
      Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
      ETag: "10c24bc-4ab-457e1c1f"
      Content-Length: 12195
  稍后,如果瀏覽器要驗(yàn)證一個(gè)文件,它會(huì)使用If-None-Match文件頭來把ETag傳回給原始服務(wù)器。在這個(gè)例子中,如果ETag匹配,就會(huì)返回一 個(gè)304狀態(tài)碼,這就節(jié)省了12195字節(jié)的響應(yīng)。      GET /i/yahoo.gif HTTP/1.1
      Host: us.yimg.com
      If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT
      If-None-Match: "10c24bc-4ab-457e1c1f"
      HTTP/1.1 304 Not Modified
  ETag的問題在于,它是根據(jù)可以辨別網(wǎng)站所在的服務(wù)器的具有唯一性的屬性來生成的。當(dāng)瀏覽器從一臺(tái)服務(wù)器上獲得頁面內(nèi)容后到另外一臺(tái)服務(wù)器上進(jìn)行驗(yàn)證時(shí) ETag就會(huì)不匹配,這種情況對(duì)于使用服務(wù)器組和處理請(qǐng)求的網(wǎng)站來說是非常常見的。默認(rèn)情況下,Apache和IIS都會(huì)把數(shù)據(jù)嵌入ETag中,這會(huì)顯著 減少多服務(wù)器間的文件驗(yàn)證沖突。
   Apache 1.3和2.x中的ETag格式為inode-size-timestamp。即使某個(gè)文件在不同的服務(wù)器上會(huì)處于相同的目錄下,文件大小、權(quán)限、時(shí)間戳 等都完全相同,但是在不同服務(wù)器上他們的內(nèi)碼也是不同的。 
  IIS 5.0和IIS 6.0處理ETag的機(jī)制相似。IIS中的ETag格式為Filetimestamp:ChangeNumber。用ChangeNumber來跟蹤 IIS配置的改變。網(wǎng)站所用的不同IIS服務(wù)器間ChangeNumber也不相同。不同的服務(wù)器上的Apache和IIS即使對(duì)于完全相同的內(nèi)容產(chǎn)生的 ETag在也不相同,用戶并不會(huì)接收到一個(gè)小而快的304響應(yīng);相反他們會(huì)接收一個(gè)正常的200響應(yīng)并下載全部?jī)?nèi)容。如果你的網(wǎng)站只放在一臺(tái)服務(wù)器上,就 不會(huì)存在這個(gè)問題。但是如果你的網(wǎng)站是架設(shè)在多個(gè)服務(wù)器上,并且使用Apache和 IIS產(chǎn)生默認(rèn)的ETag配置,你的用戶獲得頁面就會(huì)相對(duì)慢一點(diǎn),服務(wù)器會(huì)傳輸更多的內(nèi)容,占用更多的帶寬,代理也不會(huì)有效地緩存你的網(wǎng)站內(nèi)容。即使你的 內(nèi)容擁有Expires文件頭,無論用戶什么時(shí)候點(diǎn)擊“刷新”或者“重載”按鈕都會(huì)發(fā)送相應(yīng)的GET請(qǐng)求。
   如果你沒有使用ETag提供的靈活的驗(yàn)證模式,那么干脆把所有的ETag都去掉會(huì)更好。Last-Modified文件頭驗(yàn)證是基于內(nèi)容的時(shí)間戳的。去掉 ETag文件頭會(huì)減少響應(yīng)和下次請(qǐng)求中文件的大小。微軟的這篇支持文稿講述了如何去掉ETag。在Apache中,只需要在配置文件中簡(jiǎn)單添加下面一行代 碼就可以了:
      FileETag none


15、盡早刷新輸出緩沖 
  當(dāng)用戶請(qǐng)求一個(gè)頁面時(shí),無論如何都會(huì)花費(fèi)200到500毫秒用于后臺(tái)組織HTML文件。在這期間,瀏覽器會(huì)一直空閑等待數(shù)據(jù)返回。在PHP中,你可以使用 flush()方法,它允許你把已經(jīng)編譯的好的部分HTML響應(yīng)文件先發(fā)送給瀏覽器,這時(shí)瀏覽器就會(huì)可以下載文件中的內(nèi)容(腳本等)而后臺(tái)同時(shí)處理剩余的 HTML頁面。這樣做的效果會(huì)在后臺(tái)煩惱或者前臺(tái)較空閑時(shí)更加明顯。
  輸出緩沖應(yīng)用最好的一個(gè)地方就是緊跟在<head />之后,因?yàn)镠TML的頭部分容易生成而且頭部往往包含CSS和JavaScript文件,這樣瀏覽器就可以在后臺(tái)編譯剩余HTML的同時(shí)并行下 載它們。 例子:

      ... <!-- css, js -->
          </head>
          <?php flush(); ?>
          <body>
      ... <!-- content -->

為了證明使用這項(xiàng)技術(shù)的好處,Yahoo!搜索率先研究并完成了用戶測(cè)試。


16、使用GET來完成AJAX請(qǐng)求 
  Yahoo!Mail團(tuán)隊(duì)發(fā)現(xiàn),當(dāng)使用XMLHttpRequest時(shí),瀏覽器中的POST方法是一個(gè)“兩步走”的過程:首先發(fā)送文件頭,然后才發(fā)送數(shù) 據(jù)。因此使用GET最為恰當(dāng),因?yàn)樗恍璋l(fā)送一個(gè)TCP包(除非你有很多cookie)。IE中URL的最大長(zhǎng)度為2K,因此如果你要發(fā)送一個(gè)超過2K的 數(shù)據(jù)時(shí)就不能使用GET了。
  一個(gè)有趣的不同就是POST并不像GET那樣實(shí)際發(fā)送數(shù)據(jù)。根據(jù)HTTP規(guī)范,GET意味著“獲取”數(shù)據(jù),因此當(dāng)你僅僅獲取數(shù)據(jù)時(shí)使用GET更加有意義 (從語意上講也是如此),相反,發(fā)送并在服務(wù)端保存數(shù)據(jù)時(shí)使用POST。


除此之外,JavaScript和CSS也是我們頁面中經(jīng)常用到的內(nèi)容,對(duì)它們的優(yōu)化也提高網(wǎng)站性能的重要方面:


35、避免空的圖像來源

一個(gè)src屬性為空串的圖像有兩種情況:

1. 直接的HTML

<img src="">

2. JavaScript

var img = new Image();
img.src = "";


這兩種情況都會(huì)引起同樣的效果:瀏覽器會(huì)再次向你的服務(wù)器發(fā)出請(qǐng)求。

  • Internet Explorer 將向這個(gè)頁面所在的目錄發(fā)出一個(gè)請(qǐng)求
  • Safari and Chrome 將發(fā)出對(duì)這個(gè)頁面的一個(gè)請(qǐng)求。
  • Firefox 3 和更早的版本所采取的動(dòng)作和Safari and Chrome一樣,但是 3.5版本 addressed this issue[bug 444931] and no longer sends a request.
  • Opera 不進(jìn)行任何操作。

這個(gè)行為為何是不好的?

1、 發(fā)送大量突然的請(qǐng)求將使你的服務(wù)器宕機(jī)(Cripple your servers),尤其是每天有數(shù)百萬訪問量的頁面。

2、 產(chǎn)生一個(gè)從未瀏覽過的頁面將浪費(fèi)服務(wù)器的計(jì)算周期(computing cycles)

3、 損壞用戶數(shù)據(jù)。如果你在請(qǐng)求中追蹤狀態(tài)(以cookie或是其他的方式),你可能會(huì)損壞數(shù)據(jù)。即使這個(gè)圖像請(qǐng)求并沒有返回一個(gè)圖像,所有的頭被瀏覽器讀取并接受,包括所有cookie。While the rest of the response is thrown away, the damage may already be done.

引起這種行為的根源在于瀏覽器中URI的解析方式。這種行為定義在RFC 3986 - Uniform Resource Identifiers.當(dāng)一個(gè)空串作為一個(gè)URI時(shí),它被認(rèn)為一個(gè)相對(duì)URI(relative URI)并通過定義在section 5.2中的算法被解析。這個(gè)特例,一個(gè)空串,列在section 5.4當(dāng)中。Firefox, Safari, and Chrome都是依據(jù)這一規(guī)格來解析空串,而Internet Explorer則不正確的解析這個(gè)串,符合更早的一個(gè)規(guī)范,RFC 2396 - Uniform Resource Identifiers (this was obsoleted by RFC 3986).所以技術(shù)上,瀏覽器都在做它們被期望所做的事情來解析relative URIs,問題是在這個(gè)范圍,空串不是故意造成的。


HTML5 adds to the description of the file:///C:/Users/Prayer/AppData/Local/Temp/msohtmlclip1/01/clip_image001.giftag's src attribute to instruct browsers not to make an additional request in section 4.8.2:

    The src attribute must be present, and must contain a valid URL referencing a non-interactive, optionally animated, image resource that is neither paged nor scripted. If the base URI of the element is the same as the document's address, then the src attribute's value must not be the empty string.

非常希望瀏覽器在將來不會(huì)有這樣的問題。不幸的是,沒有為<script src=""> and <link href="">的條款?;蛟S仍需要時(shí)間來做出調(diào)整以保證瀏覽器不會(huì)意外的實(shí)現(xiàn)這一行為。

這一規(guī)則是受雅虎JavaScript導(dǎo)師Nicolas C. Zakas啟發(fā)。更新信息請(qǐng)參見Empty image src can destroy your site..

三、CSS部分

  • 把樣式表置于頂部
  • 避免使用CSS表達(dá)式(Expression)
  • 用<link>代替@import
  • 避免使用濾鏡

17、把樣式表置于頂部 
  在研究Yahoo!的性能表現(xiàn)時(shí),我們發(fā)現(xiàn)把樣式表放到文檔的<head />內(nèi)部似乎會(huì)加快頁面的下載速度。這是因?yàn)榘褬邮奖矸诺?lt;head />內(nèi)會(huì)使頁面有步驟的加載顯示。
  注重性能的前端服務(wù)器往往希望頁面有秩序地加載。同時(shí),我們也希望瀏覽器把已經(jīng)接收到內(nèi)容盡可能顯示出來。這對(duì)于擁有較多內(nèi)容的頁面和網(wǎng)速較慢的用戶來說 特別重要。向用戶返回可視化的反饋,比如進(jìn)程指針,已經(jīng)有了較好的研究并形成了正式文檔。在我們的研究中HTML頁面就是進(jìn)程指針。當(dāng)瀏覽器有序地加載文 件頭、導(dǎo)航欄、頂部的logo等對(duì)于等待頁面加載的用戶來說都可以作為可視化的反饋。這從整體上改善了用戶體驗(yàn)。
  把樣式表放在文檔底部的問題是在包括Internet Explorer在內(nèi)的很多瀏覽器中這會(huì)中止內(nèi)容的有序呈現(xiàn)。瀏覽器中止呈現(xiàn)是為了避免樣式改變引起的頁面元素重繪。用戶不得不面對(duì)一個(gè)空白頁面。
   HTML規(guī)范清楚指出樣式表要放包含在頁面的<head />區(qū)域內(nèi):“和<a />不同,<link />只能出現(xiàn)在文檔的<head />區(qū)域內(nèi),盡管它可以多次使用它”。無論是引起白屏還是出現(xiàn)沒有樣式化的內(nèi)容都不值得去嘗試。最好的方案就是按照HTML規(guī)范在文 檔<head />內(nèi)加載你的樣式表。


18、避免使用CSS表達(dá)式(Expression) 
  CSS表達(dá)式是動(dòng)態(tài)設(shè)置CSS屬性的強(qiáng)大(但危險(xiǎn))方法。Internet Explorer從第5個(gè)版本開始支持CSS表達(dá)式。下面的例子中,使用CSS表達(dá)式可以實(shí)現(xiàn)隔一個(gè)小時(shí)切換一次背景顏色:
      background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" ); 
如上所示,expression中使用了JavaScript表達(dá)式。CSS屬性根據(jù)JavaScript表達(dá)式的計(jì)算結(jié)果來設(shè)置。expression 方法在其它瀏覽器中不起作用,因此在跨瀏覽器的設(shè)計(jì)中單獨(dú)針對(duì)Internet Explorer設(shè)置時(shí)會(huì)比較有用。
  表達(dá)式的問題就在于它的計(jì)算頻率要比我們想象的多。不僅僅是在頁面顯示和縮放時(shí),就是在頁面滾動(dòng)、乃至移動(dòng)鼠標(biāo)時(shí)都會(huì)要重新計(jì)算一次。給CSS表達(dá)式增加 一個(gè)計(jì)數(shù)器可以跟蹤表達(dá)式的計(jì)算頻率。在頁面中隨便移動(dòng)鼠標(biāo)都可以輕松達(dá)到10000次以上的計(jì)算量。
  一個(gè)減少CSS表達(dá)式計(jì)算次數(shù)的方法就是使用一次性的表達(dá)式,它在第一次運(yùn)行時(shí)將結(jié)果賦給指定的樣式屬性,并用這個(gè)屬性來代替CSS表達(dá)式。如果樣式屬性 必須在頁面周期內(nèi)動(dòng)態(tài)地改變,使用事件句柄來代替CSS表達(dá)式是一個(gè)可行辦法。如果必須使用CSS表達(dá)式,一定要記住它們要計(jì)算成千上萬次并且可能會(huì)對(duì)你 頁面的性能產(chǎn)生影響。


19、用<link>代替@import 
  前面的最佳實(shí)現(xiàn)中提到CSS應(yīng)該放置在頂端以利于有序加載呈現(xiàn)。
  在IE中,頁面底部@import和使用<link>作用是一樣的,因此最好不要使用它。


20、避免使用濾鏡 
  IE獨(dú)有屬性AlphaImageLoader用于修正7.0以下版本中顯示PNG圖片的半透明效果。這個(gè)濾鏡的問題在于瀏覽器加載圖片時(shí)它會(huì)終止內(nèi)容的 呈現(xiàn)并且凍結(jié)瀏覽器。在每一個(gè)元素(不僅僅是圖片)它都會(huì)運(yùn)算一次,增加了內(nèi)存開支,因此它的問題是多方面的。
  完全避免使用AlphaImageLoader的最好方法就是使用PNG8格式來代替,這種格式能在IE中很好地工作。如果你確實(shí)需要使用 AlphaImageLoader,請(qǐng)使用下劃線_filter又使之對(duì)IE7以上版本的用戶無效。


四、 JavaScript部分

  • 把腳本置于頁面底部
  • 使用外部JavaScript和CSS
  • 削減JavaScript和CSS
  • 剔除重復(fù)腳本
  • 減少DOM訪問
  • 開發(fā)智能事件處理程序

21、把腳本置于頁面底部 
  腳本帶來的問題就是它阻止了頁面的平行下載。HTTP/1.1 規(guī)范建議,瀏覽器每個(gè)主機(jī)名的并行下載內(nèi)容不超過兩個(gè)。如果你的圖片放在多個(gè)主機(jī)名上,你可以在每個(gè)并行下載中同時(shí)下載2個(gè)以上的文件。但是當(dāng)下載腳本 時(shí),瀏覽器就不會(huì)同時(shí)下載其它文件了,即便是主機(jī)名不相同。
  在某些情況下把腳本移到頁面底部可能不太容易。比如說,如果腳本中使用了document.write來插入頁面內(nèi)容,它就不能被往下移動(dòng)了。這里可能還 會(huì)有作用域的問題。很多情況下,都會(huì)遇到這方面的問題。
  一個(gè)經(jīng)常用到的替代方法就是使用延遲腳本。DEFER屬性表明腳本中沒有包含document.write,它告訴瀏覽器繼續(xù)顯示。不幸的 是,F(xiàn)irefox并不支持DEFER屬性。在Internet Explorer中,腳本可能會(huì)被延遲但效果也不會(huì)像我們所期望的那樣。如果腳本可以被延遲,那么它就可以移到頁面的底部。這會(huì)讓你的頁面加載的快一點(diǎn)。


22、使用外部JavaScript和CSS 
  很多性能規(guī)則都是關(guān)于如何處理外部文件的。但是,在你采取這些措施前你可能會(huì)問到一個(gè)更基本的問題:JavaScript和CSS是應(yīng)該放在外部文件中呢 還是把它們放在頁面本身之內(nèi)呢?
  在實(shí)際應(yīng)用中使用外部文件可以提高頁面速度,因?yàn)镴avaScript和CSS文件都能在瀏覽器中產(chǎn)生緩存。內(nèi)置在HTML文檔中的JavaScript 和CSS則會(huì)在每次請(qǐng)求中隨HTML文檔重新下載。這雖然減少了HTTP請(qǐng)求的次數(shù),卻增加了HTML文檔的大小。從另一方面來說,如果外部文件中的 JavaScript和CSS被瀏覽器緩存,在沒有增加HTTP請(qǐng)求次數(shù)的同時(shí)可以減少HTML文檔的大小。
  關(guān)鍵問題是,外部JavaScript和CSS文件緩存的頻率和請(qǐng)求HTML文檔的次數(shù)有關(guān)。雖然有一定的難度,但是仍然有一些指標(biāo)可以一測(cè)量它。如果一 個(gè)會(huì)話中用戶會(huì)瀏覽你網(wǎng)站中的多個(gè)頁面,并且這些頁面中會(huì)重復(fù)使用相同的腳本和樣式表,緩存外部文件就會(huì)帶來更大的益處。
  許多網(wǎng)站沒有功能建立這些指標(biāo)。對(duì)于這些網(wǎng)站來說,最好的堅(jiān)決方法就是把JavaScript和CSS作為外部文件引用。比較適合使用內(nèi)置代碼的例外就是 網(wǎng)站的主頁,如Yahoo!主頁和My Yahoo!。主頁在一次會(huì)話中擁有較少(可能只有一次)的瀏覽量,你可以發(fā)現(xiàn)內(nèi)置JavaScript和CSS對(duì)于終端用戶來說會(huì)加快響應(yīng)時(shí) 間。
  對(duì)于擁有較大瀏覽量的首頁來說,有一種技術(shù)可以平衡內(nèi)置代碼帶來的HTTP請(qǐng)求減少與通過使用外部文件進(jìn)行緩存帶來的好處。其中一個(gè)就是在首頁中內(nèi)置 JavaScript和CSS,但是在頁面下載完成后動(dòng)態(tài)下載外部文件,在子頁面中使用到這些文件時(shí),它們已經(jīng)緩存到瀏覽器了。


23、削減JavaScript和CSS 
  精簡(jiǎn)是指從去除代碼不必要的字符減少文件大小從而節(jié)省下載時(shí)間。消減代碼時(shí),所有的注釋、不需要的空白字符(空格、換行、tab縮進(jìn))等都要去掉。在 JavaScript中,由于需要下載的文件體積變小了從而節(jié)省了響應(yīng)時(shí)間。精簡(jiǎn)JavaScript中目前用到的最廣泛的兩個(gè)工具是JSMin和YUI Compressor。YUI Compressor還可用于精簡(jiǎn)CSS。
  混淆是另外一種可用于源代碼優(yōu)化的方法。這種方法要比精簡(jiǎn)復(fù)雜一些并且在混淆的過程更易產(chǎn)生問題。在對(duì)美國前10大網(wǎng)站的調(diào)查中發(fā)現(xiàn),精簡(jiǎn)也可以縮小原來 代碼體積的21%,而混淆可以達(dá)到25%。盡管混淆法可以更好地縮減代碼,但是對(duì)于JavaScript來說精簡(jiǎn)的風(fēng)險(xiǎn)更小。
  除消減外部的腳本和樣式表文件外,<script>和<style>代碼塊也可以并且應(yīng)該進(jìn)行消減。即使你用Gzip壓縮過腳本 和樣式表,精簡(jiǎn)這些文件仍然可以節(jié)省5%以上的空間。由于JavaScript和CSS的功能和體積的增加,消減代碼將會(huì)獲得益處。



24、剔除重復(fù)腳本 
  在同一個(gè)頁面中重復(fù)引用JavaScript文件會(huì)影響頁面的性能。你可能會(huì)認(rèn)為這種情況并不多見。對(duì)于美國前10大網(wǎng)站的調(diào)查顯示其中有兩家存在重復(fù)引 用腳本的情況。有兩種主要因素導(dǎo)致一個(gè)腳本被重復(fù)引用的奇怪現(xiàn)象發(fā)生:團(tuán)隊(duì)規(guī)模和腳本數(shù)量。如果真的存在這種情況,重復(fù)腳本會(huì)引起不必要的HTTP請(qǐng)求和 無用的JavaScript運(yùn)算,這降低了網(wǎng)站性能。
  在Internet Explorer中會(huì)產(chǎn)生不必要的HTTP請(qǐng)求,而在Firefox卻不會(huì)。在Internet Explorer中,如果一個(gè)腳本被引用兩次而且它又不可緩存,它就會(huì)在頁面加載過程中產(chǎn)生兩次HTTP請(qǐng)求。即時(shí)腳本可以緩存,當(dāng)用戶重載頁面時(shí)也會(huì)產(chǎn) 生額外的HTTP請(qǐng)求。
  除增加額外的HTTP請(qǐng)求外,多次運(yùn)算腳本也會(huì)浪費(fèi)時(shí)間。在Internet Explorer和Firefox中不管腳本是否可緩存,它們都存在重復(fù)運(yùn)算JavaScript的問題。
  一個(gè)避免偶爾發(fā)生的兩次引用同一腳本的方法是在模板中使用腳本管理模塊引用腳本。在HTML頁面中使用<script />標(biāo)簽引用腳本的最常見方法就是: 
    <script type="text/javascript" src="menu_1.0.17.js"></script> 
在PHP中可以通過創(chuàng)建名為insertScript的方法來替代: 
     <?php insertScript("menu.js") ?> 
為了防止多次重復(fù)引用腳本,這個(gè)方法中還應(yīng)該使用其它機(jī)制來處理腳本,如檢查所屬目錄和為腳本文件名中增加版本號(hào)以用于Expire文件頭等。


25、減少DOM訪問 
  使用JavaScript訪問DOM元素比較慢,因此為了獲得更多的應(yīng)該頁面,應(yīng)該做到:
緩存已經(jīng)訪問過的有關(guān)元素 
線下更新完節(jié)點(diǎn)之后再將它們添加到文檔樹中 
避免使用JavaScript來修改頁面布局 
  有關(guān)此方面的更多信息請(qǐng)查看Julien Lecomte在YUI專題中的文章“高性能Ajax應(yīng)該程序”。


26、開發(fā)智能事件處理程序 
  有時(shí)候我們會(huì)感覺到頁面反應(yīng)遲鈍,這是因?yàn)镈OM樹元素中附加了過多的事件句柄并且些事件句病被頻繁地觸發(fā)。這就是為什么說使用event delegation(事件代理)是一種好方法了。如果你在一個(gè)div中有10個(gè)按鈕,你只需要在div上附加一次事件句柄就可以了,而不用去為每一個(gè)按 鈕增加一個(gè)句柄。事件冒泡時(shí)你可以捕捉到事件并判斷出是哪個(gè)事件發(fā)出的。
  你同樣也不用為了操作DOM樹而等待onload事件的發(fā)生。你需要做的就是等待樹結(jié)構(gòu)中你要訪問的元素出現(xiàn)。你也不用等待所有圖像都加載完畢。
  你可能會(huì)希望用DOMContentLoaded事件來代替 事件應(yīng)用程序中的onAvailable方法。
  有關(guān)此方面的更多信息請(qǐng)查看Julien Lecomte在YUI專題中的文章“高性能Ajax應(yīng)該程序”。


圖片和Coockie也是我們網(wǎng)站中幾乎不可缺少組成部分,此外隨著移動(dòng)設(shè)備的流行,對(duì)于移動(dòng)應(yīng)用的優(yōu)化也十分重要。這主要包括:


五、Coockie部分

  • 減小Cookie體積
  • 對(duì)于頁面內(nèi)容使用無coockie域名

27、減小Cookie體積 
  HTTP coockie可以用于權(quán)限驗(yàn)證和個(gè)性化身份等多種用途。coockie內(nèi)的有關(guān)信息是通過HTTP文件頭來在web服務(wù)器和瀏覽器之間進(jìn)行交流的。因此 保持coockie盡可能的小以減少用戶的響應(yīng)時(shí)間十分重要。
有關(guān)更多信息可以查看Tenni Theurer和Patty Chi的文章“When the Cookie Crumbles”。這們研究中主要包括:
去除不必要的coockie

使coockie體積盡量小以減少對(duì)用戶響應(yīng)的影響 
注意在適應(yīng)級(jí)別的域名上設(shè)置coockie以便使子域名不受影響 
設(shè)置合理的過期時(shí)間。較早地Expire時(shí)間和不要過早去清除coockie,都會(huì)改善用戶的響應(yīng)時(shí)間。


28、對(duì)于頁面內(nèi)容使用無coockie域名 
  當(dāng)瀏覽器在請(qǐng)求中同時(shí)請(qǐng)求一張靜態(tài)的圖片和發(fā)送coockie時(shí),服務(wù)器對(duì)于這些coockie不會(huì)做任何地使用。因此他們只是因?yàn)槟承┴?fù)面因素而創(chuàng)建的 網(wǎng)絡(luò)傳輸。所有你應(yīng)該確定對(duì)于靜態(tài)內(nèi)容的請(qǐng)求是無coockie的請(qǐng)求。創(chuàng)建一個(gè)子域名并用他來存放所有靜態(tài)內(nèi)容。
   如果你的域名是http://www.example.org/ ,你可以在static.example.org上存在靜態(tài)內(nèi)容。但是,如果你不是在http://www.example.org/ 上而是在頂級(jí)域名example.org設(shè)置了coockie,那么所有對(duì)于static.example.org的請(qǐng)求都包含coockie。在這種情 況下,你可以再重新購買一個(gè)新的域名來存在靜態(tài)內(nèi)容,并且要保持這個(gè)域名是無coockie的。Yahoo!使用的是ymig.com,YouTube使 用的是ytimg.com,Amazon使用的是images-anazon.com等等。
  使用無coockie域名存在靜態(tài)內(nèi)容的另外一個(gè)好處就是一些代理(服務(wù)器)可能會(huì)拒絕對(duì)coockie的內(nèi)容請(qǐng)求進(jìn)行緩存。一個(gè)相關(guān)的建議就是,如果你 想確定應(yīng)該使用example.org還是http://www.example.org/ 作為你的一主頁,你要考慮到coockie帶來的影響。忽略掉www會(huì)使你除了把coockie設(shè)置到*.example.org(*是泛域名解析,代表 了所有子域名譯者dudo注)外沒有其它選擇,因此出于性能方面的考慮最好是使用帶有www的子域名并且在它上面設(shè)置coockie。


六、Image 部分

  • 優(yōu)化圖像
  • 優(yōu)化CSS Spirite
  • 不要在HTML中縮放圖像
  • favicon.ico要小而且可緩存

29、優(yōu)化圖像 
  設(shè)計(jì)人員完成對(duì)頁面的設(shè)計(jì)之后,不要急于將它們上傳到web服務(wù)器,這里還需要做幾件事:
你可以檢查一下你的GIF圖片中圖像顏色的數(shù)量是否和調(diào)色板規(guī)格一致。 使用imagemagick中下面的命令行很容易檢查:
      identify -verbose image.gif 
如果你發(fā)現(xiàn)圖片中只用到了4種顏色,而在調(diào)色板的中顯示的256色的顏色槽,那么這張圖片就還有壓縮的空間。 
  嘗試把GIF格式轉(zhuǎn)換成PNG格式,看看是否節(jié)省空間。大多數(shù)情況下是可以壓縮的。由于瀏覽器支持有限,設(shè)計(jì)者們往往不太樂意使用PNG格式的圖片,不過 這都是過去的事情了?,F(xiàn)在只有一個(gè)問題就是在真彩PNG格式中的alpha通道半透明問題,不過同樣的,GIF也不是真彩格式也不支持半透明。因此GIF 能做到的,PNG(PNG8)同樣也能做到(除了動(dòng)畫)。下面這條簡(jiǎn)單的命令可以 安全地把GIF格式轉(zhuǎn)換為PNG格式:

      convert image.gif image.png

“我們要說的是:給PNG一個(gè)施展身手的機(jī)會(huì)吧!” 
在所有的PNG圖片上運(yùn)行pngcrush(或者其它PNG優(yōu)化工具)。例如:
      pngcrush image.png -rem alla -reduce -brute result.png 
在所有的JPEG圖片上運(yùn)行jpegtran。這個(gè)工具可以對(duì)圖片中的出現(xiàn)的鋸齒等做無損操作,同時(shí)它還可以用于優(yōu)化和清除圖片中的注釋以及其它無用信息 (如EXIF信息):
      jpegtran -copy none -optimize -perfect src.jpg dest.jpg


30、優(yōu)化CSS Spirite 
  在Spirite中水平排列你的圖片,垂直排列會(huì)稍稍增加文件大?。?nbsp;
Spirite中把顏色較近的組合在一起可以降低顏色數(shù),理想狀況是低于256色以便適用PNG8格式; 
  便于移動(dòng),不要在Spirite的圖像中間留有較大空隙。這雖然不大會(huì)增加文件大小但對(duì)于用戶代理來說它需要更少的內(nèi)存來把圖片解壓為像素地圖。 100x100的圖片為1萬像素,而1000x1000就是100萬像素。


31、不要在HTML中縮放圖像 
  不要為了在HTML中設(shè)置長(zhǎng)寬而使用比實(shí)際需要大的圖片。如果你需要:
<img width="100" height="100" src="mycat.jpg" alt="My Cat" />
那么你的圖片(mycat.jpg)就應(yīng)該是100x100像素而不是把一個(gè)500x500像素的圖片縮小使用。


32、favicon.ico要小而且可緩存 
  favicon.ico是位于服務(wù)器根目錄下的一個(gè)圖片文件。它是必定存在的,因?yàn)榧词鼓悴魂P(guān)心它是否有用,瀏覽器也會(huì)對(duì)它發(fā)出請(qǐng)求,因此最好不要返回一 個(gè)404 Not Found的響應(yīng)。由于是在同一臺(tái)服務(wù)器上,它每被請(qǐng)求一次coockie就會(huì)被發(fā)送一次。這個(gè)圖片文件還會(huì)影響下載順序,例如在IE中當(dāng)你在 onload中請(qǐng)求額外的文件時(shí),favicon會(huì)在這些額外內(nèi)容被加載前下載。
  因此,為了減少favicon.ico帶來的弊端,要做到:
文件盡量地小,最好小于1K 
在適當(dāng)?shù)臅r(shí)候(也就是你不要打算再換favicon.ico的時(shí)候,因?yàn)楦鼡Q新文件時(shí)不能對(duì)它進(jìn)行重命名)為它設(shè)置Expires文件頭。你可以很安全地 把Expires文件頭設(shè)置為未來的幾個(gè)月。你可以通過核對(duì)當(dāng)前favicon.ico的上次編輯時(shí)間來作出判斷。 
Imagemagick可以幫你創(chuàng)建小巧的favicon。


七、 Mobile部分

  • 保持單個(gè)內(nèi)容小于25K
  • 打包組件成復(fù)合文本

33、保持單個(gè)內(nèi)容小于25K 
  這條限制主要是因?yàn)閕Phone不能緩存大于25K的文件。注意這里指的是解壓縮后的大小。由于單純gizp壓縮可能達(dá)不要求,因此精簡(jiǎn)文件就顯得十分重 要。
  查看更多信息,請(qǐng)參閱Wayne Shea和Tenni Theurer的文件“Performance Research, Part 5: iPhone Cacheability - Making it Stick”。


34、避免空的圖像來源