前端感官性能的衡量和优化实践
本文已發表在2017年8月《程序員》雜志。
我們為什么需要關注站點的性能,性能為什么如此重要呢?如今任何互聯網產品首先重要的都是流量,流量最終會轉換為商業價值。所以在互聯網產品中,流量、轉化率和留存率基本上是產品經理或者業務非常關注的幾個因素,而性能則會直接影響到用戶的轉化和留存(在一定階段之后影響較大,產品初期功能的因素占比更大)。所以換言之性能,其實是錢,我們關注和監測性能并非是為了數據而數據。產品的使用體驗我認為包含三大要素:產品功能、交互視覺、前端性能,而我們做性能優化的最終目的是提升前端性能,從而提升產品體驗。
值得慶幸的是,前端的性能優化有諸多有跡可循的理論和方法,比如 Yahoo!性能軍規(Best Practices for Speeding Up Your Web Site)、Google PageSpeed Insights Rules(https://developers.google.com/speed/docs/insights/rules)。萬變不離其宗,諸如此類的性能優化準則都可以對應到 Browser Processing Model 的不同階段。
根據圖 1 的 Processing Model,我們可以統計得到以下性能指標:
redirect: timing.fetchStart - timing.navigationStart dns: timing.domainLookupEnd - timing.domainLookupStart connect: timing.connectEnd - timing.connectStart network: timing.connectEnd - timing.navigationStart load: timing.loadEventEnd - timing.navigationStart domReady: timing.domContentLoadedEventStart - timing.navigationStart interactive: timing.domInteractive - timing.navigationStart ttf: timing.fetchStart - timing.navigationStart ttr: timing.requestStart - timing.navigationStart ttdns: timing.domainLookupStart - timing.navigationStart ttconnect: timing.connectStart - timing.navigationStart ttfb: timing.responseStart - timing.navigationStart firstPaint: timing.msFirstPaint - timing.navigationStart
這些指標對于前端而言都司空見慣,基本上核心關注的無外乎是:首字節時間(用于衡量網絡鏈路和服務器響應性能)、白屏時間(firstPaint)、可交互時間(interactive)、完全加載時間(load)。我們在很長一段時間里都是根據這些指標來量化分析我們的站點性能,似乎不曾認真想過這些指標是否能夠真正的反映用戶的感官性能。
顯然,這些指標絕大部分都屬于非視覺指標(Non-Visual Metrics),是體驗優化的常規指標,更是體驗和性能優化中逃不開的關鍵因素,但卻并非感官指標,也并不能完全衡量出用戶的感官性能(Perceptual Performance)。
所謂感官性能,即用戶直觀感知到的性能,用戶感受是一種非常主觀的判斷,那么如何衡量和統計感知性能?通常我們針對用戶感知會通過用研分析的方式(眼動儀、用戶溝通、用戶反饋、調研問卷、專家評估)來評估和衡量。但感官性能不同于用戶感受,是否有方式可以量化和衡量呢?筆者經過一些調研和了解后,發現感官性能是可以通過一定方式進行衡量、分析和對標的,因為對性能的感受更多反映在視覺的變化上,因此我們可以通過一些視覺指標來衡量感官性能:
First Paint Time First Contentful Paint Time First Meaningful Paint Time First Interactive Time Consistently Interactive Time Fisrt Visual Change Last Visual Change Speed Index Perceptual Speed Index
First Paint 又稱之為 First Non-Blank Paint,表示文檔中任一元素首次渲染的時間。First Contentful Paint 代表文檔中內容元素(文本、圖像、Canvas,或者 SVG)首次渲染的時間。它通常情況下是無意義的渲染,比如頭部和導航條。First Meaningful Paint Time 代表首次有意義的渲染時間(它的統計在重大的布局變化之后,往往代表了用戶所關心的首次渲染時間),First Interactive Time、Consistently Interactive Time 分別表示首次可交互時間和持續可交互時間。
如圖 2 的流程圖展示了 Blink 內核中 Time-to-first-X-paint 的分析原理和上報路徑(其他 first-X-paint 的指標類似)。
Fisrt Visual Change、Last Visual Change 分別表示首次和最后一次視覺發生變化的時間點,Speed Index、Perceptual Speed Index 均為視覺速度,兩者的區別在于背后所用到的算法不同,前者采用了 Mean Pixel-Histogram Difference 算法,后者則采用了 Structural Similarity Image Metric 算法,其中 Perceptual Speed Index 的統計結果更貼近用戶的真實感受。Speed Index 的算法如下,它代表了我們頁面在加載過程中視覺上的變化速度,其值越小代表感官性能越好:
通過 FCP(First Contentful Paint)、FMP(First Meaningful Paint)、PSI(Perceptual Speed Index),我們可以實現跨平臺的感官性能分析和對標(比如可以實現 HTML5 和 Hybrid 對比,HTML5 和原生應用的對比等),如圖 3 所示為我們項目中某列表頁的 SI 和 PSI 柱狀圖。
提及性能優化分析工具,在開發階段我們擁有眾多的選擇(比如 Chrome 自帶的 Dev Tools、老牌的 YSlow、以及 Google 推出的 PageSpeed Insights),這里筆者強烈推薦的是 Lighthouse。Lighthouse 是一個開源的自動化工具,運行 Lighthouse 的方式有兩種:一種是作為 Chrome 擴展程序運行;另一種作為命令行工具運行。 Chrome 擴展程序提供了一個對用戶更友好的界面,方便讀取報告。通過命令行工具可以將 Lighthouse 集成到持續集成系統。
通過 Lighthouse 我們可以對頁面從 PWA、性能、可訪問性、最佳實踐幾個方面進行多維度的分析,并給出結果和建議,上文中提到的 FMP(First Meaningful Paint)、FI(First Interactive),CI(Consistently Interactive),PSI(Perceptual Speed Index)都可以從其中的性能報告中分析得到。
由于篇幅所限,對于 Lighthouse 的細節說明、原理及使用在此不再贅述,基本上在開發階段通過 Chrome Dev Tools、Lighthouse 完全可以進行全面的性能體驗和分析,已經能夠為我們的優化提供足夠多的指導建議。
僅僅在開發階段擁有可用的分析檢測工具還遠遠不夠,通常情況下,我們更希望在產品上線后,和競對的產品進行感官性能的對標分析,而這里往往會涉及到跨平臺(因為競對的產品實現可能是通過 HTML5 實現,也可能是諸如 Weex、React Native 的混合開發形式,當然還有很大一部分可能是原生的實現)。
如何進行跨平臺的感官性能對標,在筆者看來非常重要,現在行業內大家普遍采用的對標方式是視頻對比,通過兩個視頻的時間軸對比來說明感官性能的提升。個人認為這種方式無法做到量化和自動化,因此可能會出現不同的人對比得出的結果并不能夠對齊,同時效率較低。
我們需要做的僅僅是更進一步,將視頻對比的過程量化和自動化。因此筆者在充分調研了現有社區的一些實現后,和同事封裝了一個簡單易用的小工具(Twilight)用于感官性能的跨平臺對標。我們需要做的僅僅是錄制視頻,然后點選關鍵幀,之后便能夠自動的將 SI(Speed Index)、PSI(Perceptual Speed Index)、FVC(First Visual Change)、FCP(FirstContentful Paint)、FMP(First Meaningful Paint)、LVC(Last Visual Change)等指標可視化的呈現出來。
在業務項目上我們也針對國際機票進行了一系列的摸索和實踐。國際機票在客戶端內以及純瀏覽器中都可能被訪問,采用了 Vue 2.0 作為基礎框架,并通過純靜態化的方式開發并部署至 CDN。起初國際機票的頁面加載白屏明顯(首次內容渲染時間長),用戶體驗較差。因此我們通過上述提到的一些工具進行了分析,發現網絡請求、應用啟動、接口請求是影響列表頁性能加載的三大因素。
針對上述問題,我們采用了以下關鍵的優化策略:
純前端離線化(在瀏覽器中通過純前端的手段進行資源文件的離線化); 客戶端離線化(在客戶端容器內通過離線包的方式實現資源文件及頁面的離線化); 頁面組件化并按需加載(通過組件化方式對頁面細粒度拆分并按需加載); 預渲染提升感官性能(在框架啟動之前,通過預渲染的方式確保頁面框架最快呈現)。
通過上述優化策略優化后,效果顯著,純前端離線化上線后可交互和完全加載時間提升 50%,客戶端離線化上線后,首字節時間基本為 0(降低 500 毫秒),可交互和完全加載時間相較純前端離線化進一步提升 30%至 50%,按需加載和預渲染上線后頁面的 FMP(First Meaningful Paint)提升 80%。
如圖 5 所示為列表頁在 Chrome 瀏覽器中模擬 4G 并將 CPU 模擬 4 倍降速(CPU Throttling 4x slowdown)的表現(不包含客戶端離線化的效果)。
總結一下,前端的性能分析和優化方式,無論是傳統性能還是感官性能完全有跡可循。開發階段可以使用 Dev Tools、Lighthouse,借助非視覺指標(Non-Visual Metrics)和視覺指標(Visual Metrics)進行分析,遵循傳統性能優化軍規以及 Google PRPL Pattern 進行性能優化。通過我們提供的工具 Twilight 可以便捷的實現感官性能的跨平臺對標分析。雖然我們在業務項目中的實踐取得了一定的效果,但優化之路漫漫,還有很多空間的可能性。歡迎對性能優化感興趣的同行一同交流,Do Better Web。
郭凱,美團點評酒旅前端高級技術專家、高級技術經理,目前負責美團點評酒旅事業群境內度假終端研發團隊,致力于終端技術體系的完善和基礎設施的建設,培養人才精進團隊,服務業務創造科技價值,譯作有《編寫可維護的 JavaScript》、《第三方 JavaScript 編程》等。
總結
以上是生活随笔為你收集整理的前端感官性能的衡量和优化实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop YARN:调度性能优化实践
- 下一篇: 前端可用性保障实践