云音樂前端體驗優(yōu)化實踐
(給前端大學(xué)加星標(biāo),提升前端技能.)
作者:賀文超
https://www.yuque.com/binfe/cquxg7/rh12qe
本次分享主要圍繞云音樂在 C 端性能體驗的部分實踐經(jīng)歷,包括評估標(biāo)準(zhǔn)和監(jiān)控能力建設(shè),以及在網(wǎng)絡(luò)、容器等方面的性能優(yōu)化實踐。
團隊面臨的挑戰(zhàn)
云音樂從19年初開始,前端從落地頁、APP 內(nèi)長尾頁面的開發(fā),逐步承擔(dān)起 APP 內(nèi)部分新業(yè)務(wù)場景的開發(fā)職責(zé)。

這個階段,網(wǎng)頁的使用體驗也逐漸受到外部的關(guān)注。由于網(wǎng)頁和客戶端頁面的原生體驗上有所差別,加之前端團隊的體驗意識尚弱,部分業(yè)務(wù)上線后收到了一些負(fù)面反饋,前端在技術(shù)選型上也受到諸多挑戰(zhàn)。
因此我們意識到,團隊急需思考和解決頁面體驗的問題。而面對多產(chǎn)品和業(yè)務(wù)線的團隊結(jié)構(gòu),要做到體驗問題在整個團隊 有標(biāo)準(zhǔn)、能發(fā)現(xiàn)、快解決,對于工程化能力會有較高的要求。
體驗工程化
為了解決前端交付體驗問題,我們首要的事情是統(tǒng)一體驗的度量標(biāo)準(zhǔn),并輔以自動化的發(fā)現(xiàn)、反饋、追蹤流程,包括:
前端應(yīng)用能夠自動接入性能監(jiān)控,以達到100%的監(jiān)控覆蓋率
監(jiān)控系統(tǒng)實時收集網(wǎng)頁上報的性能數(shù)據(jù),并對頁面的收錄和實驗室環(huán)境測試,結(jié)合度量標(biāo)準(zhǔn)對頁面進行評估,針對不達標(biāo)的頁面實時預(yù)警。
監(jiān)控系統(tǒng)對問題進行持續(xù)追蹤和反饋,推進開發(fā)解決體驗問題。
我們希望通過這個流程逐步建立起從發(fā)現(xiàn)問題到解決問題、復(fù)盤沉淀的良性循環(huán),持續(xù)提高團隊優(yōu)秀體驗應(yīng)用的交付能力。
體驗度量標(biāo)準(zhǔn)化
度量標(biāo)準(zhǔn)的選擇
一套完善的度量評估標(biāo)準(zhǔn),首先要有對好壞的定義。由于用戶感官性能是當(dāng)下首要關(guān)注的內(nèi)容,因此在標(biāo)準(zhǔn)的選擇上我們對比了與此相關(guān)的度量模型和工具鏈:
Lighthouse 5.x(19年)
Lighthouse 這款工具基于預(yù)設(shè)環(huán)境來提供性能評估模型和分析。其中 5.x 版本的評估模型包含6個維度,不同維度在性能上權(quán)重不同。它的特點是:
在預(yù)設(shè)環(huán)境進行測試,排除各種設(shè)備、環(huán)境因素,關(guān)注純代碼側(cè)性能。
評估模型盡量體現(xiàn)用戶真實的感官體驗,而不是單純的加載速度。另外模型和算法會不斷優(yōu)化完善。
能夠評估第三方頁面(可以幫助我們對比和外部頁面的差異)。
提供包含優(yōu)化建議的分析報告。
為了解決開發(fā)在本地測試中硬件、網(wǎng)絡(luò)情況不一致導(dǎo)致的問題,我們搭建了內(nèi)部的 Lighthouse 測試服務(wù),用相同配置的一組測試機進行前后一致的測試。同時設(shè)置了統(tǒng)一的 CPU 和網(wǎng)絡(luò)模擬限制,來達到較好的結(jié)果對比度。

Performance API
W3C 定義的三個 Performance API 提供真實環(huán)境中各階段時間節(jié)點:
Navigation Timing,網(wǎng)頁各個階段的時間節(jié)點
Resource Timing,頁面靜態(tài)資源的加載時間
Long Tasks,長耗時任務(wù)
例如我們前期最關(guān)注的 Navigation Timing,包含了如下圖所示的網(wǎng)頁訪問時各個階段的時間節(jié)點。

Performance API 的特點是:
體現(xiàn)真實環(huán)境下,各種綜合因素下的性能表現(xiàn)。
維度為各個階段時間的具體開銷,相對 Lighthouse 指標(biāo)更加穩(wěn)定。
需要主動上報,適用于內(nèi)部頁面測試。
Lighthouse 為主的度量標(biāo)準(zhǔn)
我們選擇了以 Lighthouse 為主進行度量,Performance API 和其他手段為輔的方式。
其中體驗基線(及格線)的定義是在如下 CPU 和網(wǎng)絡(luò)統(tǒng)一限制環(huán)境下,Lighthouse 測試穩(wěn)定達到80分+:

由于基線只能反映前端研發(fā)側(cè)的性能質(zhì)量,而無法評估到容器、網(wǎng)絡(luò)等真實環(huán)境因素。因此在及格線之外,我們補充了其他指標(biāo),以便結(jié)合數(shù)據(jù)進行網(wǎng)絡(luò)、容器等方面的通用能力優(yōu)化。包括 Performance API 各個階段數(shù)據(jù)、頁面秒開率、容器初始化時間等。
選擇 Lighthouse 為主的度量標(biāo)準(zhǔn)主要依據(jù)是:
易于理解。由于 Lighthouse 排除真實環(huán)境中硬件、網(wǎng)絡(luò)等干擾因素,關(guān)注純開發(fā)側(cè)性能, 能夠拿到開發(fā)易于理解、對優(yōu)化有直觀幫助的指標(biāo)數(shù)據(jù)。
關(guān)注用戶真實體驗。Lighthouse 面向感官性能,而不只關(guān)注加載快慢,這和我們關(guān)注用戶真實體驗的原則一致。
有助于團隊快速形成正向循環(huán)。性能分析報告和優(yōu)化建議有助于團隊在之前積累不足的背景下快速獲得體驗優(yōu)化的正向反饋。
由于能夠評估第三方頁面,方便我們了解當(dāng)前行業(yè)的整體情況,進行橫向評估和對比。
基于 Web Vitals 的新標(biāo)準(zhǔn)
標(biāo)準(zhǔn)不是一成不變的,2020年5月在 Google 提出了 Web Vitals 后,我們也補充收集了這部分?jǐn)?shù)據(jù)。
Web Vitals 是 Google 面向未來的性能度量重心。為了進一步減少開發(fā)者的理解成本,它的核心理念是網(wǎng)站開發(fā)者不一定要成為性能優(yōu)化專家。
首先, Web Vitals 基于更易標(biāo)準(zhǔn)化、更加貼近用戶真實感受的原則對指標(biāo)進行了升級,并在指標(biāo)之上定義了 Core Web Vitals,開發(fā)者只需要聚焦在最核心的三個指標(biāo)上。

另外,這些指標(biāo)被集成到了更多的工具中,包括 Lighthouse、新版本的Chromium 內(nèi)核瀏覽器等。這樣便可以統(tǒng)一線上和實驗室環(huán)境中性能測試的度量衡,解決了之前不同工具測試標(biāo)準(zhǔn)不一致而帶來的諸多問題。
目前我們已經(jīng)能夠收集到各個工具鏈的 Web Vitals 數(shù)據(jù),目前在評估觀察中。后續(xù)或許會基于 Core Web Vitals 對體驗基線進行升級。
體驗評估體系
自動接入性能監(jiān)控系統(tǒng)
由于團隊有統(tǒng)一的發(fā)布系統(tǒng)作為收斂點,在發(fā)布系統(tǒng)新建應(yīng)用時,可以為所有應(yīng)用自動接入性能監(jiān)控系統(tǒng)。

應(yīng)用創(chuàng)建時,發(fā)布系統(tǒng)自動在相關(guān)平臺上生成唯一標(biāo)志,后續(xù)每次應(yīng)用構(gòu)建時,自動在 HTML 頁面中插入相應(yīng) SDK 的下載邏輯即可。

同時,已發(fā)布的應(yīng)用也可以在發(fā)布系統(tǒng)上通過同樣的方式一鍵接入監(jiān)控系統(tǒng)。
自動收錄頁面并測試
我們希望這些接入了性能監(jiān)控 SDK 的頁面能夠被自動收錄并進行 Lighthouse 測試。
線上應(yīng)用接入性能監(jiān)控 SDK 后,真實用戶訪問頁面時會上報性能數(shù)據(jù)。我們能夠基于這些數(shù)據(jù)收集到所有被訪問過的真實 URL,并通過一定規(guī)則將同類頁面進行聚合。
對單日 PV 達到一定數(shù)量的聚類,選取任一真實鏈接進行收錄。
最后通過定時服務(wù)對收錄的頁面進行定期測試。

這樣便完成了線上頁面的全量收錄和定時測試。
頁面評估、預(yù)警、指引
每次測試后都會生成 Lighthouse 分析報告,我們針對一段時間內(nèi)多次測試未達基線的頁面推送郵件預(yù)警,并提供相應(yīng)的優(yōu)化建議,引導(dǎo)頁面負(fù)責(zé)人進行優(yōu)化改進。
持續(xù)追蹤和反饋
通過實時預(yù)警和定期的郵件推送,開發(fā)能夠持續(xù)了解到所負(fù)責(zé)前端應(yīng)用的體驗問題。
另外團隊的體驗大盤也提供了實時的團隊整體概況和走勢,并通過標(biāo)桿應(yīng)用、排行榜透出等等提高體驗問題的曝光度。
長期上,我們通過雙線組織促進團隊研發(fā)能力的養(yǎng)成:
體驗小分隊作為虛擬組織,負(fù)責(zé)平臺能力提供和橫向信息拉齊。
各業(yè)務(wù)小組負(fù)責(zé)業(yè)務(wù)內(nèi)應(yīng)用的實際優(yōu)化和能力沉淀等等。
應(yīng)用側(cè)體驗優(yōu)化效果
經(jīng)過多個季度的努力,前端應(yīng)用在體驗方面的交付質(zhì)量有了顯著的提升。

基于動靜分離的優(yōu)化實踐
前端業(yè)務(wù)側(cè)的體驗優(yōu)化是最基礎(chǔ)、也是最重要的一環(huán)。然而網(wǎng)頁的性能體驗受到網(wǎng)絡(luò)、容器等因素的綜合影響,針對代碼側(cè)的單一優(yōu)化必然存在難以跨越的性能上限。以云音樂業(yè)務(wù)來看,即使是優(yōu)化過的前端應(yīng)用,真實場景下收集到的 domReady 均值依然超過 1s。所以我們提出了全鏈路體驗優(yōu)化的計劃,關(guān)注到容器初始化開始的整個加載過程。
動靜分離是穩(wěn)定性保障和性能優(yōu)化中常見的措施。例如在前端開發(fā)中,我們?yōu)殪o態(tài)資源設(shè)置長期緩存,以便能減輕服務(wù)器壓力并縮短二次訪問的鏈路。而在容器和網(wǎng)絡(luò)階段的優(yōu)化中,我們也可以利用此思想,將相對穩(wěn)定的內(nèi)容提前下載和執(zhí)行,從而減少用戶真實操作到來時的開銷。
本次也將重點分享與動靜分離相關(guān)的兩項優(yōu)化措施。
利用 CDN 進行網(wǎng)絡(luò)優(yōu)化
通過將內(nèi)容分發(fā)至全球的海量加速節(jié)點,使用戶可以就近獲取內(nèi)容,提高網(wǎng)絡(luò)穩(wěn)定性和性能。
幾乎每個公司在靜態(tài)資源(靜態(tài)網(wǎng)頁、CSS、JS、圖片、媒體資源等)的分發(fā)上都應(yīng)用了 CDN,其實在動態(tài)應(yīng)用(或者動靜混合型應(yīng)用)中, CDN 也能夠在性能和穩(wěn)定性方面發(fā)揮很好的作用。因此我們?yōu)?SSR 應(yīng)用中動態(tài)生成的 HTML 也提供了 CDN 域名。網(wǎng)頁上 CDN 可能帶來的性能優(yōu)化包括:
建連時間優(yōu)化
回源路徑優(yōu)化(理論收益)
緩存帶來的收益(針對可緩存資源)
動靜分離
由于 SSR 應(yīng)用經(jīng)歷了服務(wù)端渲染的過程。如果要設(shè)置緩存,首先需要對頁面內(nèi)容進行動靜分離。SSR 應(yīng)用中,如果頁面上的某個內(nèi)容滿足以下條件,就可以認(rèn)為該內(nèi)容是可靜態(tài)化的:
允許一段時間的時效性問題
不因人而異(與用戶態(tài)不相關(guān))
不因設(shè)備而異
舉個例子,如果對視頻詳情頁進行動靜分離,可以將視頻基本內(nèi)容作為靜態(tài)內(nèi)容、其他內(nèi)容作為動態(tài)內(nèi)容。

遵循源站的設(shè)置
動靜混合型應(yīng)用的每個頁面可能對時效性的要求不同,如果一個頁面絕大部分內(nèi)容都是動態(tài)的則不能設(shè)置緩存。所以不同于靜態(tài)應(yīng)用可以設(shè)置固定的緩存時長,動態(tài)應(yīng)用的 CDN 緩存策略需要遵循源站,由服務(wù)端為每個頁面設(shè)置合適的緩存時長。

優(yōu)化效果
網(wǎng)頁上 CDN 的收益主要集中在建連時間和內(nèi)容傳輸時間的優(yōu)化上,內(nèi)部應(yīng)用實際上能夠帶來60-100ms左右的提升。由于這個收益覆蓋了絕大多數(shù)域名,所以整體收益還是比較可觀的。

另外在穩(wěn)定性保障和優(yōu)雅降級上,CDN 也有良好的表現(xiàn)。例如在服務(wù)不可用時,用戶也可以看到較為友好的頁面:

公共資源預(yù)加載
在云音樂 APP 內(nèi),前端應(yīng)用以 CSR 頁面為主,這使端內(nèi)有更大的空間進行預(yù)處理工作。另外云音樂分散的部署模式導(dǎo)致絕大部分前端應(yīng)用為小型應(yīng)用,每個頁面中 React 等公共代碼占了大部分。
基本思路
因此我們想到,通過代碼的動靜分離將應(yīng)用無關(guān)的公共部分單獨打包,并提前加載執(zhí)行。可以提前完成大部分代碼的下載和執(zhí)行開銷。

公共資源包會在 APP 預(yù)加載容器中提前預(yù)熱執(zhí)行,在用戶真實訪問到來時,只需要加載剩余的代碼?;玖鞒倘缦拢?/p>
APP 啟動時預(yù)創(chuàng)建 Webview
Webview 預(yù)加載引用了公共資源包代碼的空白 HTML
用戶訪問時,如果命中某個公共包則復(fù)用 Webview,后續(xù)只需要做加載剩余業(yè)務(wù)代碼、糾正地址欄等操作即可
每消耗一個 Webview 對象,就重新創(chuàng)建一個
優(yōu)化效果
目前公共資源預(yù)加載方式的應(yīng)用能夠獲得 40%+ 的時間優(yōu)化。下圖是某頁面的優(yōu)化前后對比:

擴展場景
對于應(yīng)用的性能提升效果,實際上與公共部分在業(yè)務(wù)應(yīng)用代碼中的占比有關(guān)系。由于我們可以同時支持多個公共資源包預(yù)加載,因此針對核心的垂直場景,可以擴展為完整代碼的預(yù)加載優(yōu)化,從而節(jié)省 100% 的代碼執(zhí)行開銷。

小結(jié)
今天主要和大家分享了云音樂在 C 端性能體驗的一部分實踐經(jīng)歷,包括評估標(biāo)準(zhǔn)和監(jiān)控能力建設(shè),以及在網(wǎng)絡(luò)、容器等方面的性能優(yōu)化實踐。由于篇幅原因僅包含了部分實踐內(nèi)容,歡迎大家針對前端體驗相關(guān)的問題繼續(xù)交流探討。
??愛心三連擊
點分享 點點贊 點在看



