Web 前端效能提升 Checklist

在調校網站效能的時候,對 Back-End 下手可能再怎麼調差別也不會很大,但如果對 Front-End 進行優化,可能原先載入頁面需要花費四秒、五秒,一調校就變成一、兩秒。

這篇文章主要是將我個人閱讀 High Performance Web Sites 以及 Best Practices for Speeding Up Your Web Site,實際操作後覺得影響最大的幾個要素列出來,如果你想要了解地更完整,還是推薦你閱讀這兩份資料。

這篇文章只談大方向跟概念,不會探討各個程式語言的細部實作內容。

1. 減少 HTTP Requests 數量

根據研究只有 10~20% 的時間是花在取得 HTML Document ,剩下 80~90% 的時間則是花在下載其他頁面所需的 components(例如:JS, Image, CSS)。

減少 HTTP Requests 數量基本上有兩種做法:

  1. CSS Sprites :簡單來說就是把圖片集合成一張,透過 CSS 調整位置顯示。可參考: CSS Sprites: Image Slicing’s Kiss of Death
  2. Combined files:把所有 JS 集合成一個檔案、把所有 CSS 集合成一個檔案。

2. 壓縮 JavaScript 和 CSS

除了將 CSS & JS 合成一個檔案之外,「壓縮」也非常重要,檔案大小變小,自然下載的時間就會縮減許多。強烈建議一定要把 JS 和 CSS 壓過!

壓縮可以使用 YUI Compressor 這個工具,非常好用。

3. Gzip Components

從 HTTP/1.1 開始,Browser 可以透過以下 HTTP Header 告訴 Server 它支援哪種壓縮方式(不過 deflate 幾乎無人使用):

 Accept-Encoding: gzip, deflate

當 Server 接受到 Browser 發送的 Request 、看見這個 HTTP Header 之後,Server 「可能」(開發者如果沒有把 Server 的設定打開就不會對內容進行 Gzip 壓縮)就會按照 Browser 列出的壓縮方法中的其中之一壓縮內容並且回傳給 Browser 、透過以下 Header 告知 Browser 使用了哪種方法:

 Content-Encoding: gzip

4. 將 Stylesheets 放置在頂端

根據 Yahoo 的研究,把 Stylesheets 放在 HTML Document 的 HEAD 有助於讓頁面更快出現,這是因為在 Stylesheets 全部下載完畢之前,Browser 都不會開始進行 render 頁面的動作。

對於擁有大量內容的網站來說,讓使用者可以越快看到內容越好,才不會讓使用者感覺「沒什麼進展」而決定跳離網站。

5. 將 Scripts 放置在尾端

HTTP/1.1 specification 建議 Browser 下載頁面所需的元件時,每個 hostname 最多不要超過兩個元件同時下載,因此實務上如果有多個元件需要下載的話,我們會把它拆成兩個 hostname 分開放。

不過 Scripts 並不適用於以上情況,下載一個 script 的時候,直到它下載完成為止,都不會下載其他元件,即使是在不同的 hostname 也一樣,會有這樣的差異主要有兩個原因:

  1. script 使用 document.write 更動網頁內容。
  2. 某些 script 彼此之前有關係性,如果不按照順序下載會發生問題。

因此如果我們將 script 放在 </BODY> 之前的話,使用者便可以更快看到內容。

6. Make JavaScript and CSS External

External files 會讓頁面產生速度變快是因為通常外部的 JavaScript 和 CSS 都會被 Browser 快取。 Inline JavaScript 和 CSS 的問題是:每次抓 HTML Document 的時候,這些內容都必須重新下載。

如果訪客瀏覽您的網站時,通常會瀏覽好幾個頁面,而且這些頁面使用到的都是相同的 JavaScript 和 CSS 的話,這個技巧便非常適用。

7. 壓縮頁面上使用到的背景圖片

圖片有否壓縮,大小差異會非常顯著。壓一下,整個 Page Size 可能會縮小好幾倍。

8. Expires, Cache-Control, Last-Modified, Etag

與 Browser 決定 cache 的時間長短相關的 HTTP Header ,有兩個: Expires 以及 Cache-Control: max-age

Server 可以傳送 Expires 這個 header 告訴 Browser 在某個日期到期之前都可以繼續使用這份 copy,如下:

 Expires: Fri, 15 Aug 2014 20:00:00 GMT

Expires 只能指定一個特定日期是其缺點,替代方案是使用 Cache-Control: max-age ,讓你直接指定「過多久」就會失效,如下(max-age 值的單位為「秒」):

 Cache-Control: max-age=1000

使用這兩個 header 雖然很方便,但對於內容時常更動的網站而言,這反而會造成不便,關於這個問題,有兩種解決方案:

  1. Server 回傳 Last-Modified header 給 Browser ,下次 Browser 要 request 這個頁面時,會傳 If-Modified-Since 這個 header 跟 Server 比對,相符的話 Server 會直接回傳 304 not modified ,告訴瀏覽器不用重抓。
  2. 另一種方式是使用 Etag header,它是代表一個元件之特定版本的獨立字串。瀏覽器第一次 request 時,Server 會產生並回傳 Etag 給瀏覽器,下次瀏覽器再請求同一個頁面時,會傳 If-None-Match 這個 header 跟 Server 比對,相符便回傳 304 not modified ,告訴瀏覽器不用重抓。不過如果你的網站是使用 Cluster ,使用 Etag 可能會發生使用者向不同台 Server 驗證 Etag 是否失效,導致其實沒有失效,卻重新抓了一遍的窘況。

9. 使用 CDN

Server 擺放的位置與訪客間距離越近,瀏覽網站的速度就會越快。

使用 CDN 的好處主要有兩點:

  1. 它會讓最靠近使用者地理位置的 Server 回傳給使用者。
  2. 可以減少 Server 的負擔。

因此,這也是提升效能蠻不錯的選項。

結語

這篇文章列出的項目是最常見、常用的手法,事實上還有許多種技巧。另外,非常推薦大家安裝 YSlow 這個工具,它可以幫助你迅速抓出前端效能問題。

comments powered by Disqus
分享至 Facebook 分享至 Google +