天天看點

Yahoo!網站性能最佳體驗的34條黃金守則

英文位址:http://developer.yahoo.com/performance/rules.html

中文位址:http://www.dudo.org/article.asp?id=214

Yahoo!的Exceptional Performance團隊為改善Web性能帶來最佳實踐。他們為此進行了一系列的實驗、開發了各種工具、寫了大量的文章和部落格并在各種會議上參與探讨。最佳實踐的核心就是旨在提高網站性能。

Excetional Performance團隊總結出了一系列可以提高網站速度的方法。可以分為7大類34條。包括内容、伺服器、cookie、CSS、JavaScript、圖檔、移動應用等七部分。

其中内容部分一共十條建議:

一、内容部分

盡量減少HTTP請求

減少DNS查找

避免跳轉

緩存Ajxa

推遲加載

提前加載

減少DOM元素數量

用域名劃分頁面内容

使frame數量最少

避免404錯誤

1、盡量減少HTTP請求次數

終端使用者響應的時間中,有80%用于下載下傳各項内容。這部分時間包括下載下傳頁面中的圖像、樣式表、腳本、Flash等。通過減少頁面中的元素可以減少HTTP請求的次數。這是提高網頁速度的關鍵步驟。

減少頁面元件的方法其實就是簡化頁面設計。那麼有沒有一種方法既能保持頁面内容的豐富性又能達到加快響應時間的目的呢?這裡有幾條減少HTTP請求次數同時又可能保持頁面内容豐富的技術。

合并檔案是通過把所有的腳本放到一個檔案中來減少HTTP請求的方法,如可以簡單地把所有的CSS檔案都放入一個樣式表中。當腳本或者樣式表在不同頁面中使用時需要做不同的修改,這可能會相對麻煩點,但即便如此也要把這個方法作為改善頁面性能的重要一步。

CSS Sprites是減少圖像請求的有效方法。把所有的背景圖像都放到一個圖檔檔案中,然後通過CSS的background-image和background-position屬性來顯示圖檔的不同部分;

圖檔地圖是把多張圖檔整合到一張圖檔中。雖然檔案的總體大小不會改變,但是可以減少HTTP請求次數。圖檔地圖隻有在圖檔的所有組成部分在頁面中是緊挨在一起的時候才能使用,如導航欄。确定圖檔的坐标和可能會比較繁瑣且容易出錯,同時使用圖檔地圖導航也不具有可讀性,是以不推薦這種方法;

内聯圖像是使用data:URL scheme的方法把圖像資料加載頁面中。這可能會增加頁面的大小。把内聯圖像放到樣式表(可緩存)中可以減少HTTP請求同時又避免增加頁面檔案的大小。但是内聯圖像現在還沒有得到主流浏覽器的支援。

減少頁面的HTTP請求次數是你首先要做的一步。這是改進首次通路使用者等待時間的最重要的方法。如同Tenni Theurer的他的部落格Browser Cahe Usage - Exposed!中所說,HTTP請求在無緩存情況下占去了40%到60%的響應時間。讓那些初次通路你網站的人獲得更加快速的體驗吧!

2、減少DNS查找次數

域名系統(DNS)提供了域名和IP的對應關系,就像電話本中人名和他們的電話号碼的關系一樣。當你在浏覽器位址欄中輸入www.dudo.org時,DNS解析伺服器就會傳回這個域名對應的IP位址。DNS解析的過程同樣也是需要時間的。一般情況下傳回給定域名對應的IP位址會花費20到120毫秒的時間。而且在這個過程中浏覽器什麼都不會做直到DNS查找完畢。

緩存DNS查找可以改善頁面性能。這種緩存需要一個特定的緩存伺服器,這種伺服器一般屬于使用者的ISP提供商或者本地區域網路控制,但是它同樣會在使用者使用的計算機上産生緩存。DNS資訊會保留在作業系統的DNS緩存中(微軟Windows系統中DNS Client Service)。大多數浏覽器有獨立于作業系統以外的自己的緩存。由于浏覽器有自己的緩存記錄,是以在一次請求中它不會受到作業系統的影響。

Internet Explorer預設情況下對DNS查找記錄的緩存時間為30分鐘,它在系統資料庫中的鍵值為DnsCacheTimeout。Firefox對DNS的查找記錄緩存時間為1分鐘,它在配置檔案中的選項為network.dnsCacheExpiration(Fasterfox把這個選項改為了1小時)。

當用戶端中的DNS緩存都為空時(浏覽器和作業系統都為空),DNS查找的次數和頁面中主機名的數量相同。這其中包括頁面中URL、圖檔、腳本檔案、樣式表、Flash對象等包含的主機名。減少主機名的數量可以減少DNS查找次數。

減少主機名的數量還可以減少頁面中并行下載下傳的數量。減少DNS查找次數可以節省響應時間,但是減少并行下載下傳卻會增加響應時間。我的指導原則是把這些頁面中的内容分割成至少兩部分但不超過四部分。這種結果就是在減少DNS查找次數和保持較高程度并行下載下傳兩者之間的權衡了。

3、避免跳轉

跳轉是使用301和302代碼實作的。下面是一個響應代碼為301的HTTP頭:

HTTP/1.1 301 Moved Permanently

Location: http://example.com/newuri

Content-Type: text/html

浏覽器會把使用者指向到Location中指定的URL。頭檔案中的所有資訊在一次跳轉中都是必需的,内容部分可以為空。不管他們的名稱,301和302響應都不會被緩存除非增加一個額外的頭選項,如Expires或者Cache-Control來指定它緩存。<meat />元素的重新整理标簽和JavaScript也可以實作URL的跳轉,但是如果你必須要跳轉的時候,最好的方法就是使用标準的3XXHTTP狀态代碼,這主要是為了確定“後退”按鈕可以正确地使用。

但是要記住跳轉會降低使用者體驗。在使用者和HTML文檔中間增加一個跳轉,會拖延頁面中所有元素的顯示,因為在HTML檔案被加載前任何檔案(圖像、Flash等)都不會被下載下傳。

有一種經常被網頁開發者忽略卻往往十分浪費響應時間的跳轉現象。這種現象發生在當URL本該有斜杠(/)卻被忽略掉時。例如,當我們要通路http://astrology.yahoo.com/astrology 時,實際上傳回的是一個包含301代碼的跳轉,它指向的是http://astrology.yahoo.com/astrology/ (注意末尾的斜杠)。在Apache伺服器中可以使用Alias 或者 mod_rewrite或者the DirectorySlash來避免。

連接配接新網站和舊網站是跳轉功能經常被用到的另一種情況。這種情況下往往要連接配接網站的不同内容然後根據使用者的不同類型(如浏覽器類型、使用者賬号所屬類型)來進行跳轉。使用跳轉來實作兩個網站的切換十分簡單,需要的代碼量也不多。盡管使用這種方法對于開發者來說可以降低複雜程度,但是它同樣降低使用者體驗。一個可替代方法就是如果兩者在同一台伺服器上時使用Alias和mod_rewrite和實作。如果是因為域名的不同而采用跳轉,那麼可以通過使用Alias或者mod_rewirte建立CNAME(儲存一個域名和另外一個域名之間關系的DNS記錄)來替代。

4、可緩存的AJAX

Ajax經常被提及的一個好處就是由于其從背景伺服器傳輸資訊的異步性而為使用者帶來的回報的即時性。但是,使用Ajax并不能保證使用者不會在等待異步的JavaScript和XML響應上花費時間。在很多應用中,使用者是否需要等待響應取決于Ajax如何來使用。例如,在一個基于Web的Email用戶端中,使用者必須等待Ajax傳回符合他們條件的郵件查詢結果。記住一點,“異步”并不異味着“即時”,這很重要。

為了提高性能,優化Ajax響應是很重要的。提高Ajxa性能的措施中最重要的方法就是使響應具有可緩存性,具體的讨論可以檢視Add an Expires or a Cache-Control Header。其它的幾條規則也同樣适用于Ajax:

Gizp壓縮檔案

減少DNS查找次數

精簡JavaScript

避免跳轉

配置ETags

讓我們來看一個例子:一個Web2.0的Email用戶端會使用Ajax來自動完成對使用者位址薄的下載下傳。如果使用者在上次使用過Email web應用程式後沒有對位址薄作任何的修改,而且Ajax響應通過Expire或者Cacke-Control頭來實作緩存,那麼就可以直接從上一次的緩存中讀取位址薄了。必須告知浏覽器是使用緩存中的位址薄還是發送一個新的請求。這可以通過為讀取位址薄的Ajax URL增加一個含有上次編輯時間的時間戳來實作,例如,&t=11900241612等。如果位址薄在上次下載下傳後沒有被編輯過,時間戳就不變,則從浏覽器的緩存中加載進而減少了一次HTTP請求過程。如果使用者修改過位址薄,時間戳就會用來确定新的URL和緩存響應并不比對,浏覽器就會重要請求更新位址薄。

即使你的Ajxa響應是動态生成的,哪怕它隻适用于一個使用者,那麼它也應該被緩存起來。這樣做可以使你的Web2.0應用程式更加快捷。

5、推遲加載内容

你可以仔細看一下你的網頁,問問自己“哪些内容是頁面呈現時所必需首先加載的?哪些内容和結構可以稍後再加載?

把整個過程按照onload事件分隔成兩部分,JavaScript是一個理想的選擇。例如,如果你有用于實作拖放和動畫的JavaScript,那麼它就以等待稍後加載,因為頁面上的拖放元素是在初始化呈現之後才發生的。其它的例如隐藏部分的内容(使用者操作之後才顯現的内容)和處于折疊部分的圖像也可以推遲加載

工具可以節省你的工作量:YUI Image Loader可以幫你推遲加載折疊部分的圖檔,YUI Get utility是包含JS和 CSS的便捷方法。比如你可以打開Firebug的Net頁籤看一下Yahoo的首頁。

當性能目标和其它網站開發實踐一緻時就會相得益彰。這種情況下,通過程式提高網站性能的方法告訴我們,在支援JavaScript的情況下,可以先去除使用者體驗,不過這要保證你的網站在沒有JavaScript也可以正常運作。在确定頁面運作正常後,再加載腳本來實作如拖放和動畫等更加花哨的效果。

6、預加載

預加載和後加載看起來似乎恰恰相反,但實際上預加載是為了實作另外一種目标。預加載是在浏覽器空閑時請求将來可能會用到的頁面内容(如圖像、樣式表和腳本)。使用這種方法,當使用者要通路下一個頁面時,頁面中的内容大部分已經加載到緩存中了,是以可以大大改善通路速度。

下面提供了幾種預加載方法:

無條件加載:觸發onload事件時,直接加載額外的頁面内容。以Google.com為例,你可以看一下它的spirit image圖像是怎樣在onload中加載的。這個spirit image圖像在google.com首頁中是不需要的,但是卻可以在搜尋結果頁面中用到它。

有條件加載:根據使用者的操作來有根據地判斷使用者下面可能去往的頁面并相應的預加載頁面内容。在search.yahoo.com中你可以看到如何在你輸入内容時加載額外的頁面内容。

有預期的加載:載入重新設計過的頁面時使用預加載。這種情況經常出現在頁面經過重新設計後使用者抱怨“新的頁面看起來很酷,但是卻比以前慢”。問題可能出在使用者對于你的舊站點建立了完整的緩存,而對于新站點卻沒有任何緩存内容。是以你可以在通路新站之前就加載一部内容來避免這種結果的出現。在你的舊站中利用浏覽器的空餘時間加載新站中用到的圖像的和腳本來提高通路速度。

7、減少DOM元素數量

一個複雜的頁面意味着需要下載下傳更多資料,同時也意味着JavaScript周遊DOM的效率越慢。比如當你增加一個事件句柄時在500和5000個DOM元素中循環效果肯定是不一樣的。

大量的DOM元素的存在意味着頁面中有可以不用移除内容隻需要替換元素标簽就可以精簡的部分。你在頁面布局中使用表格了嗎?你有沒有僅僅為了布局而引入更多的<div>元素呢?也許會存在一個适合或者在語意是更貼切的标簽可以供你使用。

YUI CSS utilities可以給你的布局帶來巨大幫助:grids.css可以幫你實作整體布局,font.css和reset.css可以幫助你移除浏覽器預設格式。它提供了一個重新審視你頁面中标簽的機會,比如隻有在語意上有意義時才使用<div>,而不是因為它具有換行效果才使用它。

DOM元素數量很容易計算出來,隻需要在Firebug的控制台内輸入:

document.getElementsByTagName('*').length

那麼多少個DOM元素算是多呢?這可以對照有很好标記使用的類似頁面。比如Yahoo!首頁是一個内容非常多的頁面,但是它隻使用了700個元素(HTML标簽)。

8、根據域名劃分頁面内容

把頁面内容劃分成若幹部分可以使你最大限度地實作平行下載下傳。由于DNS查找帶來的影響你首先要確定你使用的域名數量在2個到4個之間。例如,你可以把用到的HTML内容和動态内容放在www.example.org上,而把頁面各種元件(圖檔、腳本、CSS)分别存放在statics1.example.org和statics.example.org上。

你可在Tenni Theurer和Patty Chi合寫的文章Maximizing Parallel Downloads in the Carpool Lane找到更多相關資訊。

9、使iframe的數量最小

ifrmae元素可以在父文檔中插入一個新的HTML文檔。了解iframe的工作理然後才能更加有效地使用它,這一點很重要。

<iframe>優點:

解決加載緩慢的第三方内容如圖示和廣告等的加載問題

Security sandbox

并行加載腳本

<iframe>的缺點:

即時内容為空,加載也需要時間

會阻止頁面加載

沒有語意

10、不要出現404錯誤

HTTP請求時間消耗是很大的,是以使用HTTP請求來獲得一個沒有用處的響應(例如404沒有找到頁面)是完全沒有必要的,它隻會降低使用者體驗而不會有一點好處。

有些站點把404錯誤響應頁面改為“你是不是要找***”,這雖然改進了使用者體驗但是同樣也會浪費伺服器資源(如資料庫等)。最糟糕的情況是指向外部JavaScript的連結出現問題并傳回404代碼。首先,這種加載會破壞并行加載;其次浏覽器會把試圖在傳回的404響應内容中找到可能有用的部分當作JavaScript代碼來執行。

繼續閱讀