1. 程式人生 > 實用技巧 >從“等等”到“秒開”再到“直開”,是什麼讓閒魚社群相見恨晚?

從“等等”到“秒開”再到“直開”,是什麼讓閒魚社群相見恨晚?

簡介:快讓我叉會兒腰~

作者:閒魚技術-頌晨

背景


閒魚前端頁面的效能常常被人唸叨,凡跳轉、必跳魚的印象深入人心,部分頁面甚至需要跳四五下才能開啟,最近我們對閒魚前端頁面系統性的做了些優化,由於閒魚前端技術棧相對多元,不同棧技術原理各不相同,優化方案也有所差異,本文主要介紹目前閒魚佔比較重的 Weex 頁面的優化過程。


閒魚 Weex 頁面多以前端渲染為主,其開啟過程與 Web 頁面略微相近,大致分為以下幾個階段:

我們將「從開始載入(navigationStart)到螢幕首次 paint(繪製)畫素內容」的這段時間稱為白屏時間(FP),將「從開始載入(navigationStart)到首屏內容全部渲染完成」的這段時間稱為首屏時間(FSP)

,受限於統計口徑,目前 Weex 下的首屏時間是不包含圖片下載及後續過程的。

優化前後


我們拿閒魚的直播頻道頁和玩家頻道頁作為參考,通過錄屏的方式看下優化前後的對比:





通過錄屏分幀的方式我們統計了下這兩個頻道頁在不同系統不同機型下的首屏時長:

可以看到,優化前 iOS、Android 主流機型上的首屏時間都要超過 2s,低端機甚至要 3-5s,優化後各機型的首屏時間均大幅下降,低端機首屏時長控制到了 2s 內,中高階機近乎直開。


拆解分析


確定優化方案前我們對現有的 Weex 頁面做了拆解分析,從結果來看,以下幾個因素對首屏時間的影響較大:

  1. Bundle 體積:不僅影響 Bundle 載入時長,同時也影響 Bundle 的解析執行耗時(低端機尤為明顯)
  2. 首屏資料請求:頁面渲染必須在首屏資料請求返回後,介面耗時直接影響首屏時間
  3. 首屏渲染範圍:首屏渲染量直接影響渲染時長(低端機尤為明顯)

優化方案

基於上面的分析調研,我們初步把優化方案定為四層:

按照預期優化效果,Weex 頁面的開啟過程是這樣的:



體現在上述的四層結構中,主要包含以下幾個優化點:


Bundle 離線


具體實現是將 Weex Bundle 以資源包為單位、以 URL 字首為索引,通過一定的更新策略離線到客戶端本地,之前的更新策略主要有訪問後安裝、啟動安裝** 兩種,對應的更新時機如下:







這套機制在容器層有統一的方案支撐,但是包命中率一直不高(25% - 55%),導致最終效果差強人意,分析後發現預設的更新策略(訪問後安裝)與頁面回訪率強相關,閒魚的前端頁面大都是頻道導購型的頁面,回訪率天然不高,所以包命中率相對應也不會高。


本次優化主要是對更新策略進行了擴充套件,增加了 “閒時安裝

” 的更新策略:會在定時更新期間主動安裝,如果安裝後未使用,則會在一週之後淘汰;如果一週內使用過,則進入常規的更新淘汰機制(一個月未使用淘汰)。


在 “閒時安裝” 的更新策略上線後,包命中率大幅提升(穩定後 90% 左右),頁面效能也得到了顯著提升:





不依賴首屏介面渲染的頁面甚至可以達到「直開」:



資料預取


傳統的首屏資料請求都是在 Bundle 解析完以後發起的,首屏資料返回後渲染頁面,是個典型的序列過程。


本次優化中我們把這個序列的過程並行化了:

  1. 將首屏請求的配置序列化以後作為引數配置到了 URL 上,同時支援一些動態替換的引數(譬如經緯度、城市等引數);
  2. 在 navigationStart 的時候由客戶端提取首屏請求配置,然後發起請求,並將結果以特定的 Hash Key(通過首屏配置生成的)作為索引儲存到本地;
  3. 在業務層真正發起首屏請求的時候會通過 Hash Key 進行比對,命中後將資料取出來返回給業務層;

時序圖如下:




特殊情況下的時序圖:





具體的技術細節本文不再贅述,資料預取的優化策略上線後,首屏時間也得到了一定程度的提升,如下(iOS 側由於各優化策略並行上線,沒能做到單一變數採集效能資料,暫以 Android 側為參考):



Bundle 離線、資料預取的優化策略上線後,部分頁面在中高階機型上逼近「直開」:

漸進式首屏


漸進式首屏解決的是「最後一公里」的問題,因為在上了「離線包」和「資料預取」的方案後,我們發現:頁面首屏時間一定程度上還是受限於首屏介面請求耗時,該方案就是為了降低使用者側的白屏等待時長,具體從以下三個方面著手:

  1. 以介面請求配置生成的索引對介面資料進行快取

    • 當用戶首次進入時,以骨架屏佔位來等待業務資料載入;
    • 當用戶非首次進入時,會根據介面請求配置生成的索引在本地快取中查詢快取資料,並完成首屏渲染,同時並行傳送介面請求,待新資料返回後,觸發頁面更新,完成最終渲染;

  1. 低端機降級方案

    為了使用者體驗能夠更好,在此我們嘗試了低端機降級優化方案。以直播頻道為例:

    • 只對首屏 Tab 做快取資料佔位優化
    • 減少了低端機上首屏渲染展示資料量

  1. 圖片渲染效果優化

     漸進式首屏帶來的一個問題是介面更新時的閃動(特別是圖片佔大篇幅的時候),為了優化此問題,我們將圖片從載入到出現的過程改為了漸顯過渡,一定程度上消除了圖片閃動的生硬感。
    

按需渲染


渲染頁面作為首屏鏈路中的一環,不同技術棧、不同裝置環境下,在頁面首屏時間中也會有不同的佔比。類Weex、RN 通過前端指令碼對映原生元件的技術方案,渲染路徑總結起來是:渲染前端 Virtual DOM -> 對映為 Native 指令 -> 將指令傳輸到 Native 側 -> Native 執行指令完成渲染。在前三個步驟上,較重的業務邏輯或不合理的程式碼通常會帶來較長的計算通訊耗時,中低端機器上尤為明顯。通過按需渲染可以有效解決這一問題。
按需渲染主要思路是通過只渲染首屏可見檢視來最小化首屏渲染耗時。本次優化中,主要針對以下幾個場景做了按需渲染:

  1. 多 Tab 情況下,對於有效能要求的非首屏 tab 頁,做資料預載入、頁面懶渲染處理
  2. 對帶/不帶回收機制的長列表做首屏只渲染可見條目,剩餘懶渲染處理。可減少帶回收機制列表的指令碼計算、通訊耗時,減少不帶回收機制列表的全鏈路渲染耗時。
  3. 自建或使用輕量級元件替換非必要的重量級元件,如: xSlider。

優化上線後,魚塘廣場頁中低端機型的首屏效能有了部分資料上的提升:

低端機上優化前端渲染階段對比:

Bundle 瘦身

**
Bundle 體積一方面直接影響 Bundle 下載時間,另一方面也會影響 Android 端的渲染效能(耗時隨 Bundle 體積增加 1-2ms/KB),我們在 Bundle 體積上的優化方案較為常規,包括:

  1. 通過 Webpack Bundle Analyzer 分析依賴,減少同 npm 包不同版本依賴
  2. 抽象公共模組,提高程式碼複用率
  3. 重構基礎工具類庫,支援按需載入打包

總結


閒魚前端的效能優化暫時告一段落,優化過程中沉澱了較多的通用能力,像 Bundle 離線、資料預取、漸進式首屏等等,這些能力在後續會有更大的發揮空間,一些能力也會變得更加智慧,譬如目前的資料預取是在 navigationStart 的時候發起的,這個時機已經比傳統的頁面載入時的時機提前了許多,但其實還可以更加提前,譬如可以在閒魚客戶端中常駐個 TaskSchedule,專門用來處理資料預取的 Task,同時可以結合使用者的訪問習慣做智慧資料預取。


在前端效能要求越來越高的背景下,傳統的 Web 載入流程已無法再滿足效能優化的需要,所以出現了各種新興容器 + 配套能力,所以下一代容器的標準形態應該是什麼樣的?

原文連結
本文為阿里雲原創內容,未經允許不得轉載。