提高網站訪問速度的34條軍規一 (轉)

1 減少HTTP請求數量 (Minimize HTTP Requests)

tag:content

80%的用戶響應時間被花費在前端,而這其中的絕大多數時間是用於下載頁面中的圖片、樣式表、腳本以及Flash這些組件。減少這些組件的數量就可以減少展示頁面所需的請求數,而這是提高網頁響應速度的關鍵

樸素的頁面設計當然是減少組件的一種途徑,但有沒有能兼顧豐富的頁面內容和快速的響應速度的方法呢?下面就是一些不錯的技巧,能在提供豐富的頁面展現的同時,減少Http請求數量:

合併文件,通過把所有腳本置於一個腳本文件裏或者把所有樣式表放於一個樣式表文件中,從而減少Http請求的數量。當不同頁面需要應用不同的腳本或樣式時,合併這些文件會是一個很大的挑戰,不過在發佈網站時進行這種合併,將是提高網站響應速度的重要一步。

CSS Sprites是減少圖片請求的首選方案。把所有的背景圖片合併到一張圖中,使用CSS的background-imagebackground-position 屬性去控制展現恰當的圖片區域。

Image maps把多張圖片組合成爲一張圖片。圖片的總大小是不變的,但減少Http請求數會提高頁面的響應速度。Image maps只能用於圖片在網頁中相鄰的情況,比如導航條。制定image maps中的圖片座標是個很麻煩的過程,而且容易出錯。同時給導航使用image maps也並不易讀,所以並不推薦使用。

內聯圖片使用data: URL scheme 把圖片數據嵌入頁面,但這會增加Html文檔的大小。把內聯圖片合併到你被緩存的的樣式表中是一個能既減少HTTP請求數又不會增加頁面大小的方法。但目前並不是所有的主流瀏覽器都支持內聯圖片。

減少頁面的Http請求數量是第一步,而且對於提高用戶初次訪問體驗是最重要的一步。正如在 Tenni Theurer的blog中的Browser Cache Usage - Exposed!裏描述的,每天,有40%-60%的訪客並沒有你的網站的緩存文件。提高這些初次訪客的訪問速度是提高用戶體驗的關鍵。

 

11 避免重定向 (Avoid Redirects)

tag:content

 

重定向結束於301或302狀態碼。這裏有一個301響應的HTTP頭的例子:
      HTTP/1.1 301 Moved Permanently
      Location: http://example.com/newuri
      Content-Type: text/html

瀏覽器會自動把用戶轉向Location域中指明的Url地址。HTTP頭裏包含了重定向所需的所有信息。響應的主體一般是空的。301或者302響應都不會被實際緩存,除非添加額外的頭部,比如 Expires或者Cache-Control指明瞭它應該被緩存。meta refresh標籤和JavaScript也可以將用戶重定向到不同的URL,但如果你必須執行重定向,最好的方法是使用標準的3XX HTTP狀態代碼,以便使後退按鈕工作正常。

需要謹記的是,重定向降低了用戶體驗。在用戶和HTML文檔之間插入的重定向延誤了頁面的呈現和組件下載,因爲它們都不可能在獲得HTML文檔之前開始。

一種最浪費性能的重定向頻繁發生而網絡開發者們卻往往沒有意識到,那就是當地址中應當有一個左斜線(/)卻沒有的時候。比如,訪問http://astrology.yahoo.com/astrology會導致一個301效應並重定向到http://astrology.yahoo.com/astrology/(注意這裏加了一個左斜線)。在Apache中,這可以使用mod_rewrite,或者在Apache事件處理中使用DirectorySlash指令來修補。

使用重定向的另一個常見場景是連接舊網站和新網站。還包括連接網站的不同部分,或者在不同情況下(比如依據瀏覽器的類型,用戶的類型等)重定向用戶。使用重定向來連接兩個網站很簡單而且需要很少的額外代碼。雖然在這些情況下使用重定向減少了開發者的麻煩,但卻降低了用戶體驗。如果兩部分在同一個服務器上,可以使用Alias 和rewrite來替代重定向。如果域名變更引起了重定向,可以創建一個CNAME(一種可以創建一個別名使一個域名指向另一個的DNS記錄)結合 Alias或者mod_rewrite來替代重定向。

 

12 移除重複的腳本 (Remove Duplicate Scripts)

tag:javascript

 

在同一個頁面中包含兩個相同的腳本文件降低了性能。這並不如你想象的那麼罕見。在對美國十大網站中的檢查中,發現它們中的兩個包含了重複的腳本。有兩個主要因素增加了一個頁面包含兩個相同腳本的機率——團隊的大小和腳本的數量。當腳本被重複包含時,由於增加了不必要的HTTP請求和JavaScript的執行,影響了性能。

不必要的HTTP請求在IE中存在,而Firefox終沒有。在IE中,如果一個外部腳本被包含了兩次而且沒有被緩存,在頁面加載的過程中會產生兩次HTTP請求。即使腳本被緩存了,當用戶重載頁面時,多餘的HTTP請求也會發生。

產生多餘的HTTP請求的同時,多次執行腳本也會浪費時間。在Firefox和IE中,無論是否被緩存,腳本都會被重複執行

避免腳本被意外加載兩次的一個方法是在你的模板系統中執行一個腳本管理模塊。通常的方式是在HTML頁面中使用SCRIPT標籤來添加一個腳本:
<script type="text/javascript" src="menu_1.0.17.js"></script>

HP中,可以選擇創建一個叫做insertScript的方法:
<?php insertScript("menu.js") ?>

這個函數不僅僅能防止腳本被重複加載多次,還可以解決腳本的其他問題,比如獨立性檢測以及爲腳本添加版本號碼以應對far future Expires頭部。

 

13 設定ETags (Configure ETags)

tag:server

 

實體標籤(ETags)是服務器和瀏覽器用於確定瀏覽器中緩存的組件和服務器中的是否對應的一種機制。("entity"是組件的另一種說法:圖片、腳本、樣式表等等)添加ETags用於辨別組件提供了比單純利用“最後修改時間”更爲靈活的機制。ETag是一個唯一標識組件的特定版本的字符串。它的唯一格式規範是字符串必須被引號引用。來源服務器使用ETag響應頭來設定一個組件的ETag:
      HTTP/1.1 200 OK
      Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
      ETag: "10c24bc-4ab-457e1c1f"
      Content-Length: 12195

當瀏覽器晚些時候需要檢測一個組件時,它使用If-None-Match 頭部把ETag傳回來源服務器。如果ETag匹配了,會返回一個304狀態碼,在這個例子裏它會減少12195個字節的響應:
      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的問題是它們往往在網站的一個服務器中被設爲唯一的,當瀏覽器從一個服務器得到了組件並在稍後試圖到另一個服務器驗證時,ETag會不匹配,而這在使用多個服務器來處理請求的網站中是很常見的。默認情況下,Apache和IIS在ETag中嵌入的數據戲劇性的減少了應用多臺服務器的網站的ETag驗證成功機率。

Apache1.3和2.新版本的ETag格式是inode-size-timestamp。雖然一個給定的文件在多臺服務器中處於同一個目錄,而且有同樣的大小,權限,時間戳,但它的inode在不同服務器中是不同的。

IIS5.0和6.0有同樣的問題。IIS中ETag的格式是Filetimestamp:ChangeNumber。ChangeNumber用來跟蹤IIS配置的改變次數。一個網站的所有IIS不可能有相同的ChangeNumber。

這導致的結果是,Apache和IIS對完全相同的組件產生的ETag在不同服務器間不能匹配。如果ETags不匹配,用戶不會得到小而快的304響應,而是一個普通的200響應和組件的所有數據。如果你把你的網站放在了一個服務器裏,這不會是一個問題。但如果你的網站有多臺服務器,而且你使用了Apache和IIS默認的ETag配置,你的用戶會訪問頁面的速度會變慢,你的服務器加載的程度更高,消耗了更大的帶寬,代理服務器不能有效的緩存你的內容。即使你的組件有一個ar future Expires頭部,當用戶重載或者刷新頁面時,依然會發送一個GET請求。

如果你不打算利用ETags提供的靈活的驗證模式,你最好把ETag統統移除。Last-Modified頭部的驗證方式給予組件的時間戳。移除ETag同時減少響應和隨後的請求中的HTTP頭部大小。這篇微軟的支持文檔描述了怎樣在IIS中移除ETags。在Apache中,你只要在Apache配置文件中添加如下一行:
     FileETag none

 

2 使用內容分佈式網絡 (Use a Content Delivery Network)

tag:server

用戶連接你的網站服務器的速度影響響應的快慢。把你的網站佈置在多臺分佈於不同地域的服務器上,會讓用戶覺得你的頁面加載速度更快。那麼我們應該從哪裏開始呢?

不要一開始就把重新設計你的網站使其能夠適應分佈式結構作爲實現網站地域分佈的第一步。根據你的網站的複雜程度不同,更新網站結構的過程也許會包含諸如同步會話狀態、在服務器間複製數據庫等一系列複雜的步驟。這樣你提高用戶訪問速度的目的反而會被更新網站架構的工作耽誤。

記住,用戶80-90%的訪問時間被花費在下載頁面中的圖片、樣式表、腳本、Flash這些組件上。這是網站展示的黃金法則。那麼與其重新設計網站的結構,不如先實現這些靜態組件的分佈。這不僅僅可以大幅減少響應時間,而且由於內容分佈式網絡(content delivery networks)的存在,這將是個很簡單的工作。

內容分佈式網絡(CDN)是一系列分佈在不同地域的服務器的集合,能夠更有效的給用戶發送信息。它會根據一種衡量網域距離的方法,選取爲某個用戶發送數據的服務器。比如,到達用戶最少跳或者最快相應速度的服務器會被選中。

一些大型Internet公司擁有他們自己的CDN,但使用公用的CDN服務提供商更爲划算,比如 Akamai Technologies, Mirror Image Internet, 或者Limelight Networks。對於剛起步的公司和個人網站來說,CDN服務的花費也許會偏高。但當你的目標用戶越來越多而且趨於國際化,用CDN來降低響應時間就很必要了。在Yahoo!,把靜態的內容從自己的網絡服務器移到CDN提高了用戶20%甚至更多的訪問速度。轉向CDN會是一個只需要相對簡單的代碼更新的工作,而且那將會顯著的提高你的網站訪問速度。

 

3 給頭部添加一個失效期或者Cache-Control (Add an Expires or a Cache-Control Header)

tag:server

這條法則包含兩方面:

  • 對於靜態組件:把頭部的緩存期設爲某個遙遠的未來,使其能夠“永不過期”。
  • 對於動態組件:使用適當的Cache-Control頭部幫助瀏覽器執行特定的請求。

網頁設計越來越豐富,頁面裏包含了越來越多的腳本、樣式表、圖片和Flash。頁面的初次訪問者也許會發送多個HTTP請求,但通過給頭部添加失效期,你可以使那些組件被緩存。這會避免下次瀏覽頁面時的不必要的HTTP請求。給圖片文件的頭部設置失效時間更爲常用,但包括腳本文件、樣式表和Flash之類的所有組件的頭部都應該被設置失效時間。

瀏覽器(還有代理服務器)使用緩存以減少HTTP請求的數量和大小,提高網頁的加載速度。服務器在HTTP相應中通過頭部中的過期時間告知客戶端一個組件可以被緩存多久。下面是一個far future的過期頭部,告訴瀏覽器這個響應直到2010年4月15日纔會過期:
Expires: Thu, 15 Apr 2010 20:00:00 GMT

如果你使用的是Apache服務器,使用ExpiresDefault 指令會設置一個相對於當前時間的過期時間。這裏有一個通過ExpiresDefault 指令把過期時間設爲請求時間之後10年的例子:
ExpiresDefault "access plus 10 years"

記住,如果你使用了far future過期頭部,你必須在組件更新時更換它的名字。在Yahoo!我們通常在建設網站的過程中執行這樣的步驟:組件的名字裏包含了它的版本,比如:yahoo_2.0.6.js。

使用一個far future過期頭部只會在用戶已經訪問你的網站之後起作用。它不會影響一個沒有緩存的初次訪問者的HTTP請求數量。所以這一切的效果取決於多少用戶訪問頁面時有一份預緩存(一份"預緩存"中已經包含了頁面的所有組件)。我們對此在Yahoo!做過測試,發現擁有預緩存的用戶在 75-85%。給頭部添加far future失效期,可以增加瀏覽器緩存的組件數量並重複用於隨後的頁面瀏覽而不需要通過用戶的網絡發送哪怕一個字節。

 

4 Gzip壓縮組件(Gzip Components)

tag:server

前臺工程師的決策能夠顯著的減少在網絡上傳輸HTTP請求和響應花費的時間。確實,終端用戶的帶寬速度、Internet服務提供商和連接交換機的服務器這些因素都是開發小組所不能控制的。但還有一些其它因素會影響響應的時間,比如壓縮文件,就會減少HTTP響應的大小從而減少響應的時間。

從HTTP/1.1開始,Web客戶端就被設定爲支持HTTP請求的頭部中Accept-Encoding指定的壓縮格式:
Accept-Encoding: gzip, deflate

當服務器檢測到請求頭部中的這一代嗎,它就會使用客戶端提供的方法列表中的一個來壓縮響應內容。而服務器通過響應頭部中的Content-Encoding來告知客戶端它所使用的壓縮方式:
Content-Encoding: gzip

Gzip是當前最常用也是最有效的壓縮方式,GNU項目開發了這一方法並且符合RFC 1952標準。另外一種你可能見過的壓縮格式是deflate,但它沒有那麼有效和常用。

使用gzip壓縮通常會減少70%的響應大小。當前瀏覽器中大約90%的Internet通訊傳輸聲明支持gzip。如果你使用Apache服務器,配置gzip的模塊取決於服務器的版本:Apache 1.3 使用mod_gzip ,而Apache 2.x 使用mod_deflate

瀏覽器和代理會有一些已知的問題,可能導致瀏覽器的預期內容和獲得的實際壓縮內容不匹配。幸運的是,這種情況隨着舊瀏覽器的使用者減少而減少。Apache的模塊可以通過自動添加適當的變化響應文件頭來解決這些問題。

服務器會根據文件類型選擇gzip壓縮的內容,但一般情況下,服務器選擇壓縮的內容會過於侷限。大部分網站會壓縮它們的Html文檔,而壓縮腳本和樣式表也是值得一做的,但很多網站並沒有這樣做,事實上,壓縮在包括XML和JSON在內的任何文本響應都是值得的。圖片和PDF文件不應該被gzip壓縮,因爲它們已經是被壓縮了的文件,gzip它們不僅浪費CPU甚至還有增大文件大小的可能。

Gzip儘可能多的文件類型是減少頁面大小從而提高用戶體驗的一個簡單的方法。

 

5 把樣式表放在前面(Put Stylesheets at the Top)

tag:css

在研究Yahoo!的性能時,我們發現把樣式表挪到文檔的頭部可以讓頁面的加載顯得更快。因爲把樣式表放在頭部可以讓頁面逐步呈現。

關心網站性能的前臺工程師通常希望頁面能夠逐步加載;即,我們希望瀏覽器能夠把已經獲得的內容儘快展現。這對於內容很多的頁面以及網絡連接較慢的用戶尤爲重要。給予用戶視覺上的反饋(比如進度提示)的重要性,已經經過了很詳盡的論證。而對於我們來說,Html頁面本身就可以作爲進度提示!當瀏覽器逐步加載頁面時,頭部、導航條、頂部的logo等等這些都可以作爲對正在等待頁面的用戶的可視的反饋。而這會從整體上提高用戶體驗。

把樣式表放在文檔的最後,會導致包括IE在內的大部分瀏覽器不進行逐步呈現。瀏覽器爲了避免當樣式改變時重繪元素而中止呈現。用戶會十分無聊的看到一個空白的頁面。

Html規範明確規定樣式表應該被包含在頁面的HEAD中:“和A不同,LINK只能在文檔的HEAD部位出現,但它可以出現多次。”空白的屏幕或者由於沒有應用樣式而引起的內容的閃現都不值得去嘗試。最好的方法是遵循HTML規範,把樣式表放在文檔的HEAD部位。

 

6 把腳本放在最後(Put Scripts at the Bottom)

tag:javascript

腳本可能會堵塞併發的下載。HTTP/1.1規範建議瀏覽器在每個域名下只進行兩個併發下載。如果你把圖片放在多個域名下,可以實現多於兩個的併發下載。當腳本被下載時,即使使用不同的域名。瀏覽器也不會進行任何其它的下載。

有些情況下把腳本放到底部並不太容易。比如,腳本使用了document.write 來添加部分頁面中的內容,就不能放到頁面中更後面的位置。還可能有作用域的問題。很多情況下,還有一些變通的方法。

通常的建議是使用延遲腳本。DEFER屬性表明腳本不包含document.write,而且提示瀏覽器繼續展現。不幸的是,Firefox不支持DEFER屬性。IE中,腳本可以被延遲,但並不如你期望的那麼久。如果一個腳本可以被延遲,那麼它也可以被放在頁面的底部。這會讓你的頁面加載的更快。

 

7 不使用CSS表達式 (Avoid CSS Expressions)

tag:css

 

CSS表達式是一種有力的(同時也很危險的)動態設置CSS屬性的方法。從IE5開始支持CSS表達式。比如,使用CSS表達式可以實現背景顏色每小時變換的效果。
background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );

如上所示,表達式方法採用了Javascript的表達。CSS屬性則被設爲Javascript表達式的結果。其它的瀏覽器會忽略CSS表達式,所以對於設置專屬IE的屬性以便在不同瀏覽器間能有一致的體驗是有用的。、

而CSS表達式的問題是它比大多數人期望的執行次數更頻繁。表達式不僅僅在頁面展現和重新設置大小的時候執行,在頁面滾動,甚至用戶在頁面上挪動鼠標時都會執行。給CSS表達式添加一個計數器可以跟蹤CSS在什麼時候和怎樣執行。在頁面上移動鼠標可以輕易的產生一萬次以上的執行。

使用一次性的表達式是減少CSS表達式的執行次數的一個方法,當表達式第一次執行時,CSS表達式會被一個確定的值代替。如果在頁面生命週期中,樣式屬性必須動態的設定,使用事件處理替代CSS表達式是一個可選的方法。如果必須使用CSS表達式,要記得它們會執行上千次並影響頁面的性能。

 

8 使用外部的JavaScript和CSS (Make JavaScript and CSS External)

tag:javascript,css

 

很多性能規則都是解決怎樣處理獨立的組件的問題的。但是,考慮這些之前,你應該先考慮一個更基本的問題:JavaScript和CSS應該被放於外部的文件,還是內聯在頁面裏?

在實際應用中使用外部的文件往往產生更快的頁面,因爲瀏覽器會緩存JavaScript和CSS文件。而內聯在頁面裏的JavaScript和CSS會在每次請求頁面時下載。這會減少所需的HTTP請求數,但增大HTML文檔的體積。而另一方面,如果放在外部文件裏的JavaScript和CSS被瀏覽器緩存,則既不用增加HTTP請求的數量,HTML文檔的體積也會減少。

關鍵的問題是,外部的JavaScript和CSS的組件被緩存的頻率和HTML文檔被請求的次數相關。雖然很難去量化,但可以被用很多指標衡量。如果你的網站的用戶在每個會話中瀏覽了很多網頁而且很多頁面重用了相同的JavaSctipt和樣式表,緩存外部文件是有很大潛在的好處的。

很多網站都符合這樣的指標。對於這些網站來說,最好的解決方案是把JavaScript和CSS發佈爲單獨的文件。唯一的例外,對於主頁,內聯的文件更好一些,例如 Yahoo!'s front pageMy Yahoo!。主頁在每個會話中只有很少瀏覽(也許只有一次),你會發現內聯的JavaScript和CSS會讓終端用戶的響應更快。

對於有很多頁面瀏覽量的首頁來說,有很多能平衡內聯文件所提供的HTTP請求減少的效果與外部文件緩存獲得的好處的技巧。一種這樣的技巧就是把JavaScript和CSS內聯在說夜裏,但在頁面完成加載時動態下載外部文件。隨後的頁面會調用瀏覽器中已經緩存的外部文件。

 

9 減少DNS的查詢 (Reduce DNS Lookups)

tag:content

 

正如電話簿使人名和他們的電話號碼相對應,域名系統(DNS)能夠使域名和IP地址相對應。當你在瀏覽器中鍵入http://www.yahoo.com,瀏覽器鏈接的DNS解析器會返回服務器的IP地址。域名解析會耗費一些時間,DNS查找給定域名的IP地址一般會耗費20-120毫秒。在DNS查找結束前,瀏覽器不會從目標域名那裏下載任何東西。

DNS查詢會被緩存以便優化性能。會有一個專門的緩存服務器進行緩存,用戶的ISP或者本地網絡會維護它,但獨立用戶的電腦裏也會有緩存。DNS信息存在於操作系統的DNS緩存裏(微軟Windows操作系統裏的“DNS客戶服務”)。大部分瀏覽器有它們自己的緩存,與操作系統的緩存相獨立。當瀏覽器在自己的緩存裏保存了DNS的記錄,它不會向操作系統發出請求記錄的要求。

IE默認緩存DNS查詢30分鐘,在註冊表的DnsCacheTimeout的鍵值中設定。Firefox則緩存DNS查詢一分鐘,在配置network.dnsCacheExpiration 中設定。(Fasterfox 將它變爲一小時。)

當客戶端的DNS緩存被清空(包括瀏覽器和操作系統的緩存),DNS查詢的數量等同於網頁中單獨的域名的數量。包括頁面中的鏈接,圖片,腳本文件,樣式表,Flash對象等。減少不同域名的數量則會減少DNS查詢的數量

減少不同域名的數量可能減少頁面並行的下載數量。減少DNS查詢縮短了響應時間,但減少了並行下載數也許會增加響應時間。我的建議是將組件分佈在兩到四個域名之間。這能很好的折中減少DNS查詢提高的速度和維持較高水平的並行下載的效果。

 

10 縮小JavaScript和CSS (Minify JavaScript and CSS)

tag:javascript,css

 

縮小是指從代碼中刪除不必要的字母,減少文件體積從而提高加載速度。縮減代碼時需要移除所有的註釋,以及不需要的空白(空格,新行和tab)。這樣處理JavaScript之後,會由於下載文件的體積被減少而提高響應的性能。兩個常用的縮減JavaScript代碼的工具是JSMinYUI Compressor。YUI compressor也可以壓縮CSS。

代碼混淆是另一個可用於源代碼的優化方案。它比壓縮更爲複雜,而且在混淆的過程中更容易產生Bug。縱觀U.S.的前十大網站,壓縮獲得了21%的體積減小而代碼混淆達到了25%。雖然代碼混淆的壓縮程度更高,但壓縮JavaScript的風險更小。

不僅僅要壓縮外部的腳本和樣式表,內斂的<script>和<style>部分也可以而且應當被壓縮。即使你gzip了你的腳本和樣式,壓縮它們仍然能減少5%以上的體積。隨着JavaScript和CSS的應用和體積的增加,壓縮你的代碼獲得的收益也會越來越多。

 

11 避免重定向 (Avoid Redirects)

tag:content

 

重定向結束於301或302狀態碼。這裏有一個301響應的HTTP頭的例子:
      HTTP/1.1 301 Moved Permanently
      Location: http://example.com/newuri
      Content-Type: text/html

瀏覽器會自動把用戶轉向Location域中指明的Url地址。HTTP頭裏包含了重定向所需的所有信息。響應的主體一般是空的。301或者302響應都不會被實際緩存,除非添加額外的頭部,比如 Expires或者Cache-Control指明瞭它應該被緩存。meta refresh標籤和JavaScript也可以將用戶重定向到不同的URL,但如果你必須執行重定向,最好的方法是使用標準的3XX HTTP狀態代碼,以便使後退按鈕工作正常。

需要謹記的是,重定向降低了用戶體驗。在用戶和HTML文檔之間插入的重定向延誤了頁面的呈現和組件下載,因爲它們都不可能在獲得HTML文檔之前開始。

一種最浪費性能的重定向頻繁發生而網絡開發者們卻往往沒有意識到,那就是當地址中應當有一個左斜線(/)卻沒有的時候。比如,訪問http://astrology.yahoo.com/astrology會導致一個301效應並重定向到http://astrology.yahoo.com/astrology/(注意這裏加了一個左斜線)。在Apache中,這可以使用mod_rewrite,或者在Apache事件處理中使用DirectorySlash指令來修補。

使用重定向的另一個常見場景是連接舊網站和新網站。還包括連接網站的不同部分,或者在不同情況下(比如依據瀏覽器的類型,用戶的類型等)重定向用戶。使用重定向來連接兩個網站很簡單而且需要很少的額外代碼。雖然在這些情況下使用重定向減少了開發者的麻煩,但卻降低了用戶體驗。如果兩部分在同一個服務器上,可以使用Alias 和rewrite來替代重定向。如果域名變更引起了重定向,可以創建一個CNAME(一種可以創建一個別名使一個域名指向另一個的DNS記錄)結合 Alias或者mod_rewrite來替代重定向。

 

12 移除重複的腳本 (Remove Duplicate Scripts)

tag:javascript

 

在同一個頁面中包含兩個相同的腳本文件降低了性能。這並不如你想象的那麼罕見。在對美國十大網站中的檢查中,發現它們中的兩個包含了重複的腳本。有兩個主要因素增加了一個頁面包含兩個相同腳本的機率——團隊的大小和腳本的數量。當腳本被重複包含時,由於增加了不必要的HTTP請求和JavaScript的執行,影響了性能。

不必要的HTTP請求在IE中存在,而Firefox終沒有。在IE中,如果一個外部腳本被包含了兩次而且沒有被緩存,在頁面加載的過程中會產生兩次HTTP請求。即使腳本被緩存了,當用戶重載頁面時,多餘的HTTP請求也會發生。

產生多餘的HTTP請求的同時,多次執行腳本也會浪費時間。在Firefox和IE中,無論是否被緩存,腳本都會被重複執行

避免腳本被意外加載兩次的一個方法是在你的模板系統中執行一個腳本管理模塊。通常的方式是在HTML頁面中使用SCRIPT標籤來添加一個腳本:
<script type="text/javascript" src="menu_1.0.17.js"></script>

HP中,可以選擇創建一個叫做insertScript的方法:
<?php insertScript("menu.js") ?>

這個函數不僅僅能防止腳本被重複加載多次,還可以解決腳本的其他問題,比如獨立性檢測以及爲腳本添加版本號碼以應對far future Expires頭部。

 

13 設定ETags (Configure ETags)

tag:server

 

實體標籤(ETags)是服務器和瀏覽器用於確定瀏覽器中緩存的組件和服務器中的是否對應的一種機制。("entity"是組件的另一種說法:圖片、腳本、樣式表等等)添加ETags用於辨別組件提供了比單純利用“最後修改時間”更爲靈活的機制。ETag是一個唯一標識組件的特定版本的字符串。它的唯一格式規範是字符串必須被引號引用。來源服務器使用ETag響應頭來設定一個組件的ETag:
      HTTP/1.1 200 OK
      Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
      ETag: "10c24bc-4ab-457e1c1f"
      Content-Length: 12195

當瀏覽器晚些時候需要檢測一個組件時,它使用If-None-Match 頭部把ETag傳回來源服務器。如果ETag匹配了,會返回一個304狀態碼,在這個例子裏它會減少12195個字節的響應:
      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的問題是它們往往在網站的一個服務器中被設爲唯一的,當瀏覽器從一個服務器得到了組件並在稍後試圖到另一個服務器驗證時,ETag會不匹配,而這在使用多個服務器來處理請求的網站中是很常見的。默認情況下,Apache和IIS在ETag中嵌入的數據戲劇性的減少了應用多臺服務器的網站的ETag驗證成功機率。

Apache1.3和2.新版本的ETag格式是inode-size-timestamp。雖然一個給定的文件在多臺服務器中處於同一個目錄,而且有同樣的大小,權限,時間戳,但它的inode在不同服務器中是不同的。

IIS5.0和6.0有同樣的問題。IIS中ETag的格式是Filetimestamp:ChangeNumber。ChangeNumber用來跟蹤IIS配置的改變次數。一個網站的所有IIS不可能有相同的ChangeNumber。

這導致的結果是,Apache和IIS對完全相同的組件產生的ETag在不同服務器間不能匹配。如果ETags不匹配,用戶不會得到小而快的304響應,而是一個普通的200響應和組件的所有數據。如果你把你的網站放在了一個服務器裏,這不會是一個問題。但如果你的網站有多臺服務器,而且你使用了Apache和IIS默認的ETag配置,你的用戶會訪問頁面的速度會變慢,你的服務器加載的程度更高,消耗了更大的帶寬,代理服務器不能有效的緩存你的內容。即使你的組件有一個ar future Expires頭部,當用戶重載或者刷新頁面時,依然會發送一個GET請求。

如果你不打算利用ETags提供的靈活的驗證模式,你最好把ETag統統移除。Last-Modified頭部的驗證方式給予組件的時間戳。移除ETag同時減少響應和隨後的請求中的HTTP頭部大小。這篇微軟的支持文檔描述了怎樣在IIS中移除ETags。在Apache中,你只要在Apache配置文件中添加如下一行:
     FileETag none

 

14 讓Ajax可以緩存 (Make Ajax Cacheable)

tag:content

 

Ajax的好處之一是它能給用戶提供瞬間的響應,因爲它從服務端異步請求數據。但Ajax不能保證用戶在等候那些異步的JavaScript和XML響應返回時什麼都不做。在應用程序中,用戶是否繼續等待取決於Ajax怎樣應用。比如,在一個基於Web的Email客戶端用戶會等候Ajax返回他們所搜索的郵件信息。記住異步並不代表“即刻”。

爲了提高性能,優化Ajax響應很重要。提高Ajax性能最重要的方式是使響應緩存,正如“添加一個過期期限和緩存控制頭”這一節討論的。這些原則同樣適用於Ajax

  • Gzip組件
  • 減少DNS查詢
  • 壓縮JavaScript
  • 避免重定向
  • 設定ETag

我們看一個例子。一個Web2,0的郵件客戶端可能會用Ajax自動下載用戶地址簿。如果用戶從上次使用郵件網站以來沒有修改她的地址簿,那麼如果Ajax響應使用了長期失效時間或者緩存控制頭部,地址簿就可以從緩存中讀取出來。瀏覽器必須被告知“使用之前的緩存地址簿”而不是“請求一個新的地址簿”。可以在地址簿Ajax的URL中添加一個標識用戶最後一次修改地址簿的時間戳,比如,&t=1190241612。如果地址簿從最後一次下載後沒有被更改,時間戳將相同而地址簿將會從瀏覽器的緩存中得到來替代額外的HTTP傳輸。如果用戶更改了她的地址簿,時間戳會保證新的URL不會和緩存中的匹配,而且瀏覽器會請求會請求更新的地址簿記錄。

即使你的Ajax響應時動態創建的,而且只適用於一個用戶,它們依然會被緩存。這樣做會讓你的Web2.0應用程序更快。

 

15 更早的刷新緩衝區 (Flush the Buffer Early)

tag:server

 

當用戶請求一個頁面,服務端會花費200至500毫秒的時間組合HTML頁面。在這期間,瀏覽器會靜靜等待數據到來。PHP中有flush()函數,它允許你向瀏覽器發送部分就緒的HTML響應,這樣瀏覽器可以在服務器處理餘下的HTML頁面時去獲取組件。這樣的好處主要在忙碌的後臺和輕鬆的前臺間可以看到。

在HEAD後面是放置刷新操作的好地方,因爲頭部的HTML代碼更容易產生,而且可以讓你放置任何CSS和JavaScript文件,以便瀏覽器在後臺工作依然進行時並行開始獲取組件。

例子:

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

Yahoo! search先行研究並且進行了真人測試證明了使用這項技術的好處。

 

16 在Ajax請求中使用GET方法 (Use GET for AJAX Requests)

tag:server

 

Yahoo! Mail 團隊發現進行XMLHttpRequest的時候,POST方法在瀏覽器中分兩步執行:先發送頭部,然後發送數據。所以最好使用只發送一個TCP包(除非你有很多的cookie)的GET方法。IE中URL的最大長度是2000,所以如果你發送超過2000的數據就不能使用GET方法。

一個有趣的現象是,POST方法並不像GET那樣實際發送數據(而Get則名副其實)。基於HTTP規範,GET方法意味着取回數據,所以當你只是請求數據時使用GET方法更爲有意義(從語義上來說),而在發送需要儲存在服務器端的數據時則相反使用POST。

 

17 後加載組件 (Post-load Components)

tag:content

 

你可以仔細端詳下你的頁面然後自問:“什麼是在頁面初始化時必須的?”那麼其餘的內容和組件可以放在後面。

JavaScript是理想的用來分割onload事件之前和之後的選擇。例如你有執行拖放、下拉和動畫的JavaScript代碼和菜單,它們可以稍後加載,因爲用戶在初始呈現之後纔會在頁面上拖動元素。其他的可以被後加載的地方包括隱藏的內容(當用戶做某項操作纔會展現的內容)和被摺疊的圖片。

可以幫助你的工具有: YUI Image Loader能幫助你延緩加載摺疊的圖片,而且YUI Get utility 能夠很簡單的包裝運行中的JS和CSS。比如,打開Firebug的網絡選項卡去查看Yahoo! Home Page。

當性能指標和其它網站開發的好的實踐一致時是不錯的。漸進增強的觀念告訴我們當支持JavaScript時,會提高用戶體驗,但你必須確保在沒有JavaScript時頁面也能工作。所以當你確保頁面工作正常時,你會通過延後加載的那些更花哨的腳本比如拖放和動畫,來增強你的頁面。

 

 

轉自:http://www.cnblogs.com/smjack/archive/2008/08/23/1274846.html

發佈了180 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章