通常來說,工程師熟悉某個系統會只要搞清楚其資料結構和資料流轉過程基本足夠了,但從商業的角度來看,前後端工程師都應該關注的另一個重要維度是系統效能,純技術角度來看效能可以認為是系統的響應速度(實際上還可以認為是執行效率等),而從使用者角度來看效能就是使用體驗。
網頁效能為什麼重要?
頁面效能差的直接後果是使用者需要等待,而等待,尤其是不確定要多長時間的等待會給使用者帶來焦慮,為了儘早的結束這種焦慮,除非訪問網頁是剛需,使用者通常會選擇直接關閉頁面。從實際資料來看,效能差是頁面高跳出率的重要原因之一。
為了搞清楚頁面效能對業務目標的影響,諸如 Yahoo、Google、Amazon 等科技公司都投入了不少資源去研究和優化,比如下面是 ThinkWithGoogle 運用神經網路分析 2017 年 1100 萬廣告落地頁載入速度和頁面跳出率關係所得到的結論:
結論顯而易見:越快越好,少即是多。
實際上,最近幾年來大型網際網路公司在頁面效能優化研發中產出了不少工具和文件,方便工程師給網站做效能分析和優化。
其中文件方面比較經典的當屬三本書:
- High Performance Websites,早期在 Yahoo 效能團隊工作的 Steve Souders 所著;
- Even Faster Websites,同上,在上冊的基礎上,列出了很多行之有效的細節優化手段;
- High Performance Browser Networks,Google 效能工程師 Ilya Grigorik 所著,可以免費線上閱讀,當然如果想支援讀者,可以選擇購買;
而工具則非常多,尤其是 2015 年開始爆發的各種應用效能管理(APM,如 New Relic)工具,對工程師來說,比較經典易用的有:
- WebPageTest,可以認為是網頁效能分析工具中的 Vim 了,純開源專案,在全球都有節點,分析思路基本與 Yahoo 效能黃金法則相貼合;
- LightHouse,已經整合在 Chrome 開發者工具中,能夠從現代 WEB 應用比較重要的幾個維度給出分析結果,比如載入速度、PWA、可用性、SEO 等,工具易用性、可得性都高於 WebPageTest,個人強烈建議;
網頁效能該怎麼衡量?
要清晰、準確的衡量網頁效能,我們先要定義頁面效能,如何定義頁面效能?
- 從後端角度看,可以是首位元組時間,即頁面發起請求到瀏覽器收到第一個響應位元組的時間,英文 Time to First Byte;
- 從瀏覽器角度看,可以是頁面所依賴的全部靜態資源載入完成所需要的時間,即常說的完全載入時間;
- 從使用者角度看,可以是敲Enter鍵開始到看到頁面開始渲染的過程所需的時間,即常說的首次渲染時間,此概念還可以細分,比如 WebPageTest 和 LightHouse 都有的 FirstMeaningfulPaint;
效能優化工作處在不同階段,或者業務場景不同,上面不同定義視角的適用性是不同的,也有把上面 3 種衡量方法加權求和得到綜合的效能指數。
要想真正開始做優化,需要搞清楚從發起請求到瀏覽器渲染頁面並呈現給使用者的過程中有哪些關鍵環節,好在現代瀏覽器提供的 Navigation Timing API 已經把這個過程標準化,方便我們做效能指標的計算,如下圖:
舉例來說上面提到的首位元組時間和完全載入時間可以用如下公式計算:
首位元組時間 = responseStart - navigationStart
完全載入時間 = loadEventEnd - navigationStart
至於首次渲染時間,準確的計算方式需要結合錄屏,篇幅原因,這裡不做展開。
PressOne 首頁效能 CaseStudy
PressOne 是基於區塊鏈的內容分發公鏈,而 https://press.one 則是專案入口,目前功能還比較簡單,主要包括賬戶建立、使用者登入、三方賬號繫結、使用者主頁、內容簽名等功能。首頁是任何網站的門戶,確保其訪問速度和體驗的重要性不言而喻,而 press.one 給筆者的初體驗除了新奇還包括慢,新使用者載入頁面平均需要 6s 以上,即使內容渲染之前有載入中提示,還是有明顯的等待感。
雖然 press.one 是基於 angular 開發的單頁應用,適用於傳統頁面的大部分效能優化方法同樣適用,下面結合 LightHouse 對 press.one 首頁做簡單的效能分析,並列出行之有效的優化行動清單。
LightHouse 可以獨立安裝使用,也可以在 Google Chrome 中使用,因為整合到了開發者工具的 Audits 皮膚中,使用方法比較簡單,建議直接閱讀文件。
下面是使用 Google Chrome 做效能診斷的結果:
百分制的效能指數結果是 18 分,3G 網路下的完全可互動時間長達 20S,通常到 10S 使用者基本都以為網站壞掉了,可見優化的空間是巨大的。
LightHouse 列出的優化手段(Opportunities)和可能的原因診斷(Diagnostics)都比較直觀:
- Enable text compression,啟用文字壓縮,針對 JS、CSS 等靜態資源是非常有效的優化手段,通常可節省 60% 以上,實施成本低,收益巨大,如果加上適當的快取,可以對重複訪問使用者更加友好;
- Reduce render-blocking stylesheets,減少阻塞渲染的樣式,需要把首屏渲染的樣式從整體樣式中剝離出來優先載入,實施成本偏高,收益中等;
- Unused CSS rules 是針對 CSS 檔案的優化,減少傳輸實際上不需要的程式碼,我仔細拔了下程式碼,專案引入的 fontawesome 貌似確實沒用到,實際上這個庫卻不小,實施成本小,收益中等;
- Serve images in next-gen formats,使用更好的壓縮演算法壓縮圖片,實施成本低,收益大;
- Proper size images,請求的圖片和使用尺寸對應,避免縮放,造成浪費,實施成本低,收益看情況;
如果上面的優化手段都落地實施,重新評估效能指數大概率可以達到及格線。
結合瀑布流分析,我們也不難發現更進一步的優化點,關鍵資源載入鏈條(Critical Request Chain)太長了,如下圖:
要開始首次渲染(對應如下瀑布流圖右側藍色的豎線)除主文件外,我們還需要額外下載 5 個 JS 檔案,1 個 CSS 檔案:
關鍵資源載入鏈條太長的問題怎麼優化呢?
- 合併資源請求,比如 elliptic 和 keythereum 的三方依賴可以直接合並,更激進的可以和 polyfill 也合併;
- 合理使用懶載入,首次渲染不需要的資源做適當的拆分,SPA 和傳統頁面都可以實現,不讓非關鍵資源阻塞頁面首次渲染;
- 合理使用 CDN,因為通常 CDN 是地理位置離使用者更近的節點,可以大大節省網路傳輸的 RTT;
關鍵資源載入鏈條的問題解決之後,重新評估的效能指數大概率能達到 80 分。
那麼接下來呢?理論上看起來效能優化是無止境的,實際上任何一個領域花 20% 的時間能達到 80% 的目的(比如把頁面首次渲染時間降到 3s 以內),然後可以收手去解決更重要的問題,當然時間允許的話,有追求的工程師會不斷的問自己,這是我能做到的極致麼?
繼續往下優化則要從頁面渲染的角度去考慮,畢竟我們已經儘可能快的把渲染頁面所需的各種資源交給了瀏覽器,怎麼讓它更快、更流暢的渲染出可互動的頁面是接下來需要重點考慮的。而渲染速度跟 DOM 節點的組織、JS 的組織、JS 和 DOM 互動的優化都有關係,篇幅原因,可以單獨寫文章介紹。
以上,希望對你有用。