提升前端性能的黃金法則

前端近幾年變化很大,各類工具,庫,框架併發。雖然如此,可是網站前端性能優化的思路基本沒變。
爲何前端性能如此重要?數據顯示:前端

  • 只有 10%~20% 的最終用戶響應時間花在了下載 HTML 文檔上。其他的 80%~90% 時間花在了下載頁面中的全部組件中;express

  • 另一點是,優化後臺須要花費比較大的成本,優化前端只須要適當地遵循一些法則會有較大的提高,相對低成本高收益。segmentfault

最近讀了 Steve Souders 的《高性能網站建設指南》,以爲很不錯在此作一下總結。Steve 是 Firebug 和 Yslow 的做者,相信你們都使用過。雖然書中的不少手段都已通過時了,可是思路基本沒變,取其精華就好。瀏覽器

本書提出了一套性能黃金法則,優先級越高排名越前,一共14則:緩存

1. 減小HTTP請求
2. 使用內容發佈網絡(CDN)
3. 添加Expires頭
4. 壓縮組件
5. 將樣式表放在頂部
6. 將腳本放在底部
7. 避免使用CSS表達式
8. 使用外部JavaScript和CSS
9. 減小DNS查找
10. 精簡JavaScript
11. 避免重定向
12. 刪除重複的腳本
13. 配置ETag
14. 使Ajax可緩存

如下分別簡單介紹每條法則的原因:性能優化


1. 減小HTTP請求

通常來講,使用外鏈的腳本和樣式表更加有利。分別把外鏈腳本和樣式表進行合併會減小HTTP請求,以節省客戶端和服務器之間的通信次數來加快頁面打開速度。可是出於開發的便利,開發的時候通常會採起模塊化的方式;這時候能夠在部署前採用一些前端構建工具把這些模塊文件合併起來再發布。服務器


2. 使用內容發佈網絡(CDN)

CDN是一組分佈在多個不一樣地理位置的Web服務器,因爲距離用戶 物理距離比較短,因此可以更加有利於用戶獲取到靜態資源;這種服務一般須要購買,也有一些免費、通用的CDN可以使用,國內的可使用 BootCDN網絡


3. 添加Expires頭

Expires頭是用來告訴瀏覽器該相應的有效期,能夠理解爲該資源的「保質期」,在期限內可使用該資源的緩存不須要從新請求。因爲瀏覽器與服務器存在時鐘同步問題,HTTP1.1還添加胡了Cache-Control和max-age來彌補Expires頭的不足。一般用於腳本,樣式表、圖片等靜態資源。併發

使用這種策略可能會遇到一個問題是,開發者可能想要在資源過時前這段時間更新它們。這時候,因爲瀏覽器的緩存還沒失效,這就須要經過更改文件名來令靜態資源 強制失效。有不少種方式給靜態資源打上版本號,能夠一本正經地打上數字版本號,根據內容生成哈希碼也行,甚至有人用π來給本身的資源打版本號(每次。框架


4. 壓縮組件

本書介紹的是gzip的方式壓縮靜態資源,實際上,這種方式會消耗額外的CPU資源。這種手段一般可以使文件大小減小70%。


5. 將樣式表放在頂部

若是把樣式表放在底部時,瀏覽器會延遲顯示任何可視化組件。另外,使用 CSS 的@import 等同於把想要加載的樣式放在底部,因此不建議使用。對於瀏覽器的渲染機制,本書並無過多說起,只是對現象作出了描述以及提供瞭解決辦法。

若是樣式表仍然在加載,構建呈現樹就是一種浪費,由於在全部樣式表加載並解析完畢以前無需繪製任何東西。不然,在其準備好以前顯示內容會遇到 FOUC(無樣式內容的閃爍,Flash of Unstyled Content)問題。

就是說,若是不把樣式表放在 <head> 中,當遇到樣式時,瀏覽器就會阻止頁面呈現,等待樣式表下載完畢。

若是把樣式表放在底部,在 IE 中還會產生白屏現象。總之,把樣式表放進 <head> 就能避免這些問題。


6. 將腳本放在底部

腳本對頁面的影響是:

  1. 阻塞對齊後面內容的呈現

  2. 阻塞後面組件的下載

瀏覽器會在下載腳本的時候阻塞並行下載,由於須要確保腳本可以順序執行。

關於這點,這裏有一篇講解的比較深刻的文章:
JS 必定要放在 Body 的最底部麼?聊聊瀏覽器的渲染機制

可是,實際開發中有時候很難徹底遵照這條準則,那隻能把可以放在最後的都放在最後。


7. 避免使用CSS表達式

使用CSS 的expression()一般會形成屢次運算。實際上,須要用到CSS 表達式的地方,一般可以找到其餘替代方案,因此避免使用CSS表達式。


8. 使用外部JavaScript和CSS

使用外部靜態文件的優勢有:

  1. 能夠被瀏覽器緩存起來

  2. 組件能夠重用

  3. 可模塊化

  4. 可以被構建(合併壓縮打版本)

  5. ...

缺點:

  1. 須要額外建立HTTP 請求

  2. ...


9. 減小DNS查找

簡單來講,DNS 查找就是輸入域名對服務器IP 地址的查找過程。DNS 緩存又分爲瀏覽器DNS 緩存、操做系統DNS 緩存。當你輸入 www.google.com 的時候,瀏覽器會先去自身的 DNS 緩存裏面查找有沒有 google 服務器的 IP 地址;若是找不到則繼續到操做系統的 DNS 緩存查找;若是瀏覽器在這兩個容器都沒有找到 google 的IP 地址記錄,則會向廣域域名體系查找。


10. 精簡JavaScript

減小JavaScript 文件大小的有幾種手段,一般被普遍使用的是 精簡。精簡就是去除JavaScript 代碼中的空格、註釋等多餘的字符,這種方式基本上沒有什麼缺點。
另一種方式是 混淆。混淆是在精簡的基礎上,把函數、變量名都用較短小的字符來替換,從而達到減小文件大小的效果。可是混淆會產生很多麻煩,頗有可能會引入錯誤,雖然有利於防止逆向工程,當同時也增長了本身在線上環境調試的難度。

如今廣泛的作法是發佈前利用 Gulp、Grunt 等自動化構建工具對資源進行壓縮。


11. 避免重定向

如下是一個重定向的過程:

瀏覽器發送請求  --  服務器返回302  --  服務器返回200  -- 瀏覽器開始呈現

就是說,在發送請求到返回200這段時間,頁面徹底是空白的;對比普通的請求多了一段空白時間。


12. 刪除重複的腳本

重複的腳本對增長HTTP 請求次數和腳本執行的時間。


13. 配置ETag

這個規則應該過期了,如今比較好的實踐是直接根據內容給靜態資源打上哈希版本號。


14. 使Ajax可緩存

適用於以上的優化,大部分一樣適用於Ajax請求。


總結:

總的來講,前端優化的整體思路是提升瀏覽器與服務器溝通的效率。

前端性能優化一味奉行「最佳實踐」有時候反而過而不及,因此針對項目的實際狀況來優化纔是明智的選擇。

相關文章
相關標籤/搜索