這是一篇關(guān)于 <u>如何加快網(wǎng)站訪問速度</u> 的譯文,原文出自 雅虎開發(fā)者網(wǎng)站,原標題為 Best Practices for Speeding Up Your Web Site。
以下為譯文:
加速網(wǎng)站訪問的最佳實踐
卓越的績效團隊已經(jīng)確定了一些使網(wǎng)頁快速的最佳做法。該清單包括分為7個類別的35個最佳做法。
Content
- 最小化 HTTP 請求
最終用戶響應(yīng)時間的80%用于前端。大部分時間都是下載頁面中的所有組件:圖像,樣式表,腳本,F(xiàn)lash等。減少組件數(shù)量又減少了呈現(xiàn)頁面所需的HTTP請求數(shù)量。這是更快頁面的關(guān)鍵。
減少頁面中組件數(shù)量的一種方法是簡化頁面的設(shè)計。但是,有沒有辦法構(gòu)建更豐富內(nèi)容的頁面,同時也能實現(xiàn)快速的響應(yīng)時間?以下是減少HTTP請求數(shù)量的一些技術(shù),同時仍然支持豐富的頁面設(shè)計。
組合文件 是通過將所有腳本組合到單個腳本中以及將所有CSS組合到單個樣式表中的方式來減少HTTP請求的數(shù)量。當(dāng)腳本和樣式表從頁到頁不同時,組合文件更具挑戰(zhàn)性,但使這部分版本過程能夠改善響應(yīng)時間。
CSS Sprites是減少圖像請求數(shù)量的首選方法。將您的背景圖像合并為一個圖像,并使用CSS background-image和background-position 屬性來顯示所需的圖像段。
圖像映像將多個圖像組合成單個圖像。總體大小大致相同,但減少HTTP請求數(shù)量會加快頁面速度。如果圖像在頁面中是連續(xù)的,則圖像映射只能工作,例如導(dǎo)航欄。定義圖像映射的坐標可能很繁瑣,容易出錯。
使用導(dǎo)航圖像映射也不可訪問,因此不推薦使用。
內(nèi)聯(lián)圖像 使用data:URL方案將圖像數(shù)據(jù)嵌入到實際頁面中。這可以增加HTML文檔的大小。將內(nèi)聯(lián)圖像組合到(緩存)樣式表中是減少HTTP請求并避免增加頁面大小的一種方法。所有主流瀏覽器都不支持內(nèi)聯(lián)圖片。
減少頁面中HTTP請求的數(shù)量是開始的地方。這是提高首次訪問者效能的最重要的指導(dǎo)方針。如Tenni Theurer的博客文章中所述瀏覽器緩存使用 - 暴露!,您網(wǎng)站的每日訪問者中有40-60%的空白緩存。
使您的頁面快速為這些第一次訪問者是更好的用戶體驗的關(guān)鍵。
減少DNS查詢
域名系統(tǒng)(DNS)將主機名映射到IP地址,就像電話簿將人員姓名映射到他們的電話號碼一樣。當(dāng)您在瀏覽器中輸入www.yahoo.com時,瀏覽器聯(lián)系的DNS解析器會返回該服務(wù)器的IP地址。DNS有一個成本。DNS通常需要20-120毫秒來查找給定主機名的IP地址。在完成DNS查找之前,瀏覽器無法從此主機名下載任何內(nèi)容。
緩存DNS查找以獲得更好的性能。這種緩存可以在由用戶的ISP或局域網(wǎng)維護的特殊緩存服務(wù)器上發(fā)生,但是也存在在個人用戶的計算機上發(fā)生的緩存。DNS信息保留在操作系統(tǒng)的DNS緩存(Microsoft Windows中的“DNS客戶端服務(wù)”)中。大多數(shù)瀏覽器都有自己的緩存,與操作系統(tǒng)的緩存分開。只要瀏覽器將DNS記錄保存在自己的緩存中,就不會對操作系統(tǒng)造成記錄請求的麻煩。
默認情況下,Internet Explorer會緩存DNS查找30分鐘,由 DnsCacheTimeout注冊表設(shè)置指定。Firefox緩存DNS查找1分鐘,由network.dnsCacheExpiration配置設(shè)置控制。(Fasterfox將其更改為1小時。)
當(dāng)客戶端的DNS緩存為空(對于瀏覽器和操作系統(tǒng))時,DNS查找的數(shù)量等于網(wǎng)頁中唯一主機名的數(shù)量。這包括在頁面的URL,圖像,腳本文件,樣式表,F(xiàn)lash對象等中使用的主機名。減少唯一主機名的數(shù)量減少了DNS查找的數(shù)量。
減少唯一主機名的數(shù)量有可能減少頁面中發(fā)生的并行下載量。避免DNS查找減少響應(yīng)時間,但減少并行下載可能會增加響應(yīng)時間。我的準則是將這些組件分成至少兩個但不超過四個主機名。這導(dǎo)致減少DNS查找并允許高度并行下載之間的良好折中。避免重定向
使用301和302狀態(tài)代碼完成重定向。以下是301響應(yīng)中HTTP頭的示例:
HTTP/1.1 301 Moved Permanently
Location: http://example.com/newuri
Content-Type: text/html
瀏覽器自動將用戶帶到該Location字段中指定的URL。重定向所需的所有信息都在頭文件中。響應(yīng)的身體通常是空的。盡管他們的名字,在實踐中也不會緩存301和302的響應(yīng),除非額外的標題,例如 Expires或者Cache-Control表明它應(yīng)該是。元刷新標簽和JavaScript是將用戶引導(dǎo)到其他URL的其他方法,但如果必須執(zhí)行重定向,首選技術(shù)是使用標準的3xx HTTP狀態(tài)代碼,主要是為了確保后退按鈕正常工作。
要記住的是重定向會減慢用戶體驗。在用戶和HTML文檔之間插入重定向會延遲頁面中的所有內(nèi)容,因為頁面中的任何內(nèi)容都不能被渲染,并且在HTML文檔到達之前不會開始下載任何組件。
最浪費的重定向之一是頻繁發(fā)生的,Web開發(fā)人員通常不會意識到這一點。當(dāng)URL中缺少尾部斜線(/)時,會發(fā)生這種情況,否則應(yīng)該有一個。
例如,去 http://astrology.yahoo.com/astrology 得到一個包含重定向到 http://astrology.yahoo.com/astrology/ (注意添加的尾部斜杠)的301響應(yīng)。如果您使用Apache處理程序,則使用Aliasormod_rewriteor DirectorySlash指令在Apache中進行修復(fù)。
將舊網(wǎng)站連接到新的網(wǎng)站是重定向的另一個常見用途。其他包括連接網(wǎng)站的不同部分,并根據(jù)某些條件(瀏覽器類型,用戶帳戶類型等)指導(dǎo)用戶。使用重定向連接兩個網(wǎng)站很簡單,只需要很少的附加編碼。盡管在這些情況下使用重定向會降低開發(fā)人員的復(fù)雜性,但會降低用戶體驗。這種使用重定向的替代方案包括使用Alias和mod_rewrite如果兩個代碼路徑托管在同一臺服務(wù)器上。如果域名變化是使用重定向的原因,一種替代方法是創(chuàng)建一個CNAME與組合(即建立了一個從域名指向另一個別名DNS記錄)Alias或mod_rewrite。
- 使用 Ajax Cacheable
Ajax的一個引人注意的好處是它為用戶提供即時反饋,因為它從后端Web服務(wù)器異步請求信息。但是,使用Ajax不能保證用戶不會等待他們等待異步JavaScript和XML響應(yīng)返回的大拇指。在許多應(yīng)用中,用戶是否保持等待取決于Ajax的使用方式。例如,在基于Web的電子郵件客戶端中,用戶將不斷等待Ajax請求的結(jié)果來查找與其搜索條件匹配的所有電子郵件。重要的是要記住,“異步”并不意味著“瞬時”。
為了提高性能,重要的是優(yōu)化這些Ajax響應(yīng)。提高Ajax性能的最重要的方法是使響應(yīng)可緩存,如添加到期或緩存控制頭。
一些其他規(guī)則也適用于Ajax:
- Gzip組件
- 減少DNS查找
- 縮小JavaScript
- 避免重定向
- 配置ETag
我們來看一個例子。
Web 2.0電子郵件客戶端可能會使用Ajax下載用戶的自動完成地址簿。
如果用戶上次使用電子郵件網(wǎng)絡(luò)應(yīng)用程序后用戶沒有修改她的地址簿,如果Ajax響應(yīng)可以使用未來的Expires或Cache-Control標頭進行緩存,則可以從緩存讀取以前的地址簿響應(yīng)。必須通知瀏覽器何時使用先前緩存的地址簿響應(yīng),而不是請求新的地址簿響應(yīng)。這可以通過向地址簿Ajax URL添加一個時間戳來表示,例如,用戶最后一次修改她的地址簿&t=1190241612。如果地址簿自上次下載以來沒有被修改,則時間戳將是相同的,并且地址簿將從瀏覽器的緩存中讀取,從而消除額外的HTTP往返。
即使您的Ajax響應(yīng)是動態(tài)創(chuàng)建的,并且可能僅適用于單個用戶,但仍可緩存它們。這樣做會使您的Web 2.0應(yīng)用程序更快。
- 后負載組件
你可以仔細看看你的頁面,問問自己:“為了最初渲染頁面絕對需要什么?” 其余的內(nèi)容和組件可以等待。
JavaScript是在onload事件之前和之后拆分的理想候選者。
例如,如果您有JavaScript代碼和庫進行拖放和動畫,那么可以等待,因為在初始呈現(xiàn)之后拖動頁面上的元素。
其他尋找候選人進行后期加載的地方包括隱藏的內(nèi)容(用戶操作后出現(xiàn)的內(nèi)容)以及下方的圖像。
幫助您解決問題的工具:YUI Image Loader允許您將圖像延遲到折疊位置,YUI Get實用程序是一個簡單的方法,可以即時包括JS和CSS。舉個例子,在野外看看
Yahoo!主頁與Firebug的網(wǎng)絡(luò)面板打開了。
當(dāng)性能目標與其他Web開發(fā)最佳實踐相一致時,這是很好的。
在這種情況下,漸進增強的想法告訴我們,當(dāng)JavaScript被支持時,可以改善用戶體驗,但是您必須確保頁面的工作即使沒有JavaScript。
所以在確定頁面工作正常之后,您可以使用一些后加載腳本來增強它,從而為您提供更多鈴聲和口哨,如拖放和動畫。
- 預(yù)加載組件
預(yù)加載可能看起來與后期加載相反,但實際上具有不同的目標。通過預(yù)加載組件,您可以利用瀏覽器空閑的時間,并請求將來需要的組件(如圖像,樣式和腳本)。這樣當(dāng)用戶訪問下一頁時,您可以將大部分組件放在緩存中,并且您的頁面將為用戶加載更快。
實際上有幾種類型的預(yù)加載:
- 無條件預(yù) 加載 - 一旦加載啟動,您就可以繼續(xù)提取一些額外的組件。
檢查google.com,了解如何請求一個精靈圖像的加載。
這個精靈圖片不需要在google.com主頁上,但在連續(xù)的搜索結(jié)果頁面上是需要的。 - 有條件的預(yù)加載 - 基于用戶操作,您做出有根據(jù)的猜測,用戶在哪里下一步,并相應(yīng)地預(yù)加載。在search.yahoo.com上,您可以看到在輸入框中輸入后,如何請求一些額外的組件。
- 預(yù)計預(yù)加載 - 在啟動重新設(shè)計之前提前預(yù)加載。
經(jīng)常重新設(shè)計后,您會發(fā)現(xiàn):“新網(wǎng)站很酷,但比以前更慢”。
問題的一部分可能是用戶正在使用完整緩存訪問您的舊站點,但新的站點始終是空緩存體驗。您可以在啟動重新設(shè)計之前預(yù)先加載某些組件來減輕這種副作用。您的舊網(wǎng)站可以使用瀏覽器空閑的時間,并請求新網(wǎng)站將使用的圖像和腳本
- 減少DOM元素的數(shù)量
復(fù)雜的頁面意味著更多的字節(jié)下載,也意味著JavaScript中的DOM訪問速度較慢。如果您想要添加事件處理程序,例如,如果循環(huán)訪問500或5000個頁面上的DOM元素,這將有所作為。
大量的DOM元素可能是一些癥狀,應(yīng)該使用頁面的標記進行改進,而不必刪除內(nèi)容。您是否使用嵌套表進行布局?你是否<div>只投入更多的東西來解決布局問題?也許有更好的和更語義上正確的方式來做你的標記。
對于布局來說,很大的幫助是YUI CSS實用程序:grids.css可以幫助您整體布局,fonts.css和reset.css可以幫助您剝離瀏覽器的默認格式。這是一個機會,開始新鮮和思考你的標記,例如,<div>只有當(dāng)它有意義的語義,而不是因為它呈現(xiàn)一個新的行。
DOM元素的數(shù)量很容易測試,只需輸入Firebug的控制臺:
document.getElementsByTagName('*').length
DOM元素有多少?檢查其他具有良好標記的類似頁面。例如,Yahoo!主頁是一個非常繁忙的頁面,仍然低于700個元素(HTML標簽)。
- 分割跨域的組件
分割組件允許您最大程度地并行下載。由于DNS查詢損失,請確保您使用的不超過2-4個域。例如,您可以承載你的HTML和動態(tài)內(nèi)容www.example.org之間分裂靜電元件static1.example.org和static2.example.org
有關(guān)更多信息,請參閱Tenni Theurer和Patty Chi的“最大化拼車車道中的并行下載 ”。
- 最小化iframe的數(shù)量
iframe允許在父文檔中插入一個HTML文檔。了解iframe的工作原理,以便有效的使用非常重要。
<iframe> 優(yōu)點:
幫助緩慢的第三方內(nèi)容,如徽章和廣告
安全沙箱
并行下載腳本<iframe> 缺點:
成本高,即使空白
阻止頁面加載
非語義
- 沒有404s
HTTP請求是昂貴的,所以發(fā)出HTTP請求并獲得無用的響應(yīng)(即404 Not Found)是完全不必要的,并且會減慢用戶體驗,沒有任何好處。
一些網(wǎng)站有幫助404s“你的意思是X?”,這對用戶體驗非常好,但也會浪費服務(wù)器資源(如數(shù)據(jù)庫等)。特別糟糕的是當(dāng)鏈接到外部JavaScript是錯誤的,結(jié)果是404.首先,這個下載將阻止并行下載。接下來,瀏覽器可能會嘗試解析404響應(yīng)體,就像它是JavaScript代碼,試圖找到可用的東西。