頁面效能的基礎因素 - 《Designing for Performance》

Horky發表於2016-03-07

頁面效能的基礎因素

最近讀這本小書Designing for Performance,突然想到之前一篇網路效能評價只寫了一半,在這裡也裡也算一個做個補充。

考慮頁面效能可以從兩種場景,第一個場景也是因素最多的場景,即首次訪問。第二個場景則是重複訪問,快取將起決定性作用。

不同的頁面型別的效能優化策略也是不一樣的,比如富文字頁面,富多媒體頁面,響應式設計的頁面,遊戲頁面等。

瀏覽器也提供了很多工具和外掛,比如Chrome DevTools, YSlow和PageSpeed Insight都有相應的外掛,可以為開發者提供頁面優化建議,這是最為簡捷的方式。我在這裡也主要使用Chrome進行分析,部分會配合WebPageTest工具。

要優化頁面效能,瞭解瀏覽器如何渲染頁面是非常重要的。以下是瀏覽器載入的整套流程,特別強調了對首次開啟效能影響很大的網路載入流程:
BasicsOfPageSpeed
其中如果HTTPS,建立連線的過程中還需要進行身份認證。

通過Chrome Inspect中的網路也可以看到整個載入資料量,以及耗時:
BasicOfPageSpeed_net
上圖是新浪首頁的資料,共發出415請求,收到6.5MB的資料,主要是圖片大多,果然是個大站!

點開可以看到細節的資料耗時:
BasicOfPageSpeed_net2
上面可以看到為請求建立與伺服器的連線的開銷還是比較大的。特別是在行動網路下,DNS解析,錯誤重連的成本都非常高,瀏覽器廠商也都會針對性的進行優化。

無論是以前的Pipeline, 和現在的Http2都可以達到連線複用的目的,也可以省掉這部分的開銷。

Chrome的開發者工具提供了Audit, 可以提供網路相關優化和頁面效能優化的建議, 比如:
BasicOfPageSpeed_Audit

在Chrome Web Store裡安裝YSlow和PageSpeed Insights外掛,就可以進一步分析頁面的效能,以及提供相關的建議。下圖是YSlow的顯示頁面元件的內容:
BasicOfPageSpeed_YSlow_Weight

在後面Statistics頁籤會顯示資源佔比,以及啟用快取(下次訪問)時需要傳送的請求數和資源大小:
BasicOfPageSpeed_YSlow_Stat
可惜這只是理想,新浪有些資源的url帶有隨機數,也就是每次請求的url並不相同,會導致http cache無法使用,會重新載入。

最終新浪首頁的效能顯示不怎麼樣,YSlow給出了D,附上一堆建議,點來Grade頁籤就可以看到。

PageSpeed Insights會給出相類似的建議,不過個人還是建議使用PageSpeed Insights, 它給出的建議會更加符合當前業界的標準。

影響載入的主要因素

除了TTFB這種主要由網路環境和後臺伺服器決定的因素外,頁面設計,以及包括User Agent(客戶端,如瀏覽器)可能影響的因素包括:

  • 連線管理 (連線數和複用)
    在HTTP下本來有一個Pipeline的機制,用來達到一個HTTP連線來併發獲取多個資源,但是伺服器支援的少。
    另一種方法是Keep alive的常連線。即User Agent嘗試保持若干個連線,完成一個資源的載入後,這個連線可以繼續用來載入另一個資源。這樣就沒有重新建立連線的開銷。
    而HTTP 2最大的特色就是讓每一個連線支援多個資源的併發請求。

  • 請求數
    減少請求數,就是要減少資源請求。比如將多張小圖合成一張Sprite圖片就是典型的做法。也不是請求數越少越好,極端的將所有資源都放到頁面裡,就是災難了。還要從瀏覽器解析、渲染頁面的行為上來定義。比如head中的CSS載入會阻塞頁面解析,如果使用body中的<link rel="stylesheet">,區分出可顯示共域的CSS, 頁尾的CSS屬生,讓瀏覽器只在需要時載入相應的CSS反而能獲得更好的使用者體驗。參考:The future of loading CSS

  • 請求大小
    因為網路裡上行和下行的速度差異,請求的大小也會對頁面效能有所影響, 所以要避免不必要的請求頭資訊,其中Cookie最為明顯。首先Cookie的儲存、檢索和提取就要耗費效能,再加上Cookie的應用往往是針對某個域名下或者路徑下的所有請求,會導致效能的影響被放大。

  • 資源大小
    如果資源較小,當然收取資料的時間就會減少,後續的處理也會更加有效率。比如JS可以使用一些工具簡化,圖片也可以根據不同的應用,選擇不同的圖片格式(演算法),或者壓縮比。特別是值得注意的是一些圖片常常含有一些不需要的資訊,比如EXIF,地理位置資訊,自定義調色盤等,有時會很大,也可以使用一些工具進行簡化。之前遇到過一些圖片網站裡使用者上傳的圖片超大的情況,就是因為圖片裡保留了一些Photoshop的冗餘資訊。參考: Image Optimization
    HTML5新的響應式圖片更是允許根據客戶端(User Agent)的螢幕大小,而選擇不同的圖片。

  • HTTP Cache
    網路層的快取模組,負責管理可快取的資源,儘量複用快取中已經有的可用資源。最快的請求就是不發請求,善於使用Http Cache,可以大大優化除首次開啟外頁面效能。但是一些網站遇到一些快取問題時,常常簡單的為url增加一個隨機數,讓快取失效,這樣既讓客戶端的整體快取命中率下降(快取了很多不必要的資源),強烈建議不要使用這種方法。
    Http Cache的實現各個瀏覽器並不相同,命中率也有差異。對前端開發者也是不可見的,如果需要更加細粒度的控制快取,可以使用H5提供的儲存功能,比如Local Storage, App Cache等。參考:管好頁面快取

關鍵渲染路徑 (Critical Rendering Path)

開始載入頁面,到實際顯示出內容,有一個最小的路徑,即關鍵渲染路徑。儘量縮短這條路徑才能真正優化到使用者的體驗。
最核心的流程是瀏覽器收到頁面資料後解析為DOM (Document Object Model), 載入CSS檔案,生成CSSOM,計算各個元素的排版資料生成Layout Tree, 結合者CSSOM生成Render Tree,再交由渲染模組完成渲染顯示出頁面內容。
這過程中包括很多的併發行為,因為序列完成的效能不可能達到使用者體驗的要求。

  • CSS
    在這個路徑主要是注意一些會阻塞頁面解析的元素,如CSS。前面提到CSS檔案放到head和body中的方式。

  • JavaScript
    直接出現在頁面中的JavaScript會阻塞頁面解析, 所以需要將一些JavaScript可以改為非同步載入和執行。

定義:可操作時間 (Time To Interactivity)
可操作時間是指從開始載入頁面到使用者可以在頁面進行操作(如搜尋,點選連結等)的時間。
通過優化關鍵渲染路徑可以減少可操作時間,包括以下方法:

  • 非同步載入內容
  • 優先載入可見內容
  • 遵循CSS/JS載入的最佳實踐 (看YSlow和PageSpeed Insights的報告)
  • 快取資源
  • 優先保證主要使用者行為儘早可用

比如下面這個Chrome DevTools顯示出一個Long Frame, 從前面一個Frame這裡花去了很長的時間,這一般代表卡頓的出現 (只有9fps)。
BasicOfPageSpeed_Jank
如果使用PageSpeed Insights,可以得到關於Blocking CSS的建議。

相關文章