Taro 小程序開發性能優化實踐

‍我們團隊在利用 Taro 進行秒送頻道小程序的同時,一直在探索性能優化的最佳實踐。隨着需求的不斷迭代,項目中的性能問題難免日積月累,逐漸暴露出來影響用戶體驗。適逢雙十一大促,我們趁着這個機會統一進行了 Taro 性能優化實踐,現總結如下,希望能爲大家在日程的開發中提供借鑑,助力大促。

優化前性能表現

性能表現主要從兩方面進行衡量,第一個是頁面加載時間,其次是頁面流暢程度。

頁面加載時間我們通過兩個維度進行量化,其一是關鍵點位打點記錄時長,具體的點位有:

tdPIHt

記錄點位並計算時間間隔,統計出的量化時間表如下:

冷啓動(初次加載小程序包)

熱啓動(已安裝小程序包,退出微信後重新進入)

其二,實際上通過代碼 log 打點存在很多問題,比如有些關鍵時間點沒有時機進行上報,無法真實地反映出用戶體驗的實際情況,所以最真實的使用場景還是親自掐表進行時間統計。

掐秒錶:分段 1(分包加載),分段 2(緩存佔位獲取定位,發起 cms 請求),分段 3(cms 加載完成),總時長。

設備:中端 (iPhone11)

問題分析

根據統計結果,很可以看出容易,目前秒送頻道頁存在的主要問題主要集中於以下幾個方面:

  1. 分包加載速度慢,導致首屏耗時偏長。

  2. 接口請求時長過長。

  3. feeds 渲染耗時偏長。

需要根據存在的問題,針對性地採取對應處理方案。

優化實踐

1. 切換 Skyline 渲染引擎

爲了解決首屏耗時較長的問題,我們經過調研,決定採用 Skyline 引擎來進行優化。

Skyline 是微信官方提供的渲染引擎,目標是進一步優化小程序性能,提供更爲接近原生的用戶體驗。其使用更精簡高效的渲染管線,並帶來諸多增強特性,讓 Skyline 擁有了更接近原生渲染的性能體驗。

Skyline 創建了一條渲染線程來負責渲染任務,並在 AppService 中劃出一個獨立的上下文,來運行之前 WebView 承擔的 JS 邏輯、DOM 樹創建等邏輯。

這種新的架構相比原有的 WebView 架構,有以下特點:

• 界面更不容易被邏輯阻塞,進一步減少卡頓

• 無需爲每個頁面新建一個 JS 引擎實例(WebView),減少了內存、時間開銷

• 框架可以在頁面之間共享更多的資源,進一步減少運行時內存、時間開銷

• 框架的代碼之間無需再通過 JSBridge 進行數據交換,減少了大量通信時間開銷

而與此同時,這個新的架構能很好地保持和原有架構的兼容性,可以很大程度上降低首屏的渲染耗時。

在實際 Skyline 適配的過程中,我們對遇到的問題進行了記錄:

1. 利用 backgroundPosition,backgroundImage 和 height 裁剪背景圖片的時候,backgroundPosition 不可以使用 calc 運算符:

目的:裁剪圖片從底部開始,向上,高度爲 gradientHeight 的部分

原寫法:

style={{
    backgroundPosition: `center calc(100% + ${getPx(gradientHeight)})`
}} >

適配寫法:

style={{
    backgroundPosition: `center bottom -${gradientHeight}px`
}} >

2. 在需要吸頂展示的場景,position: sticky 不適用,需要改寫:

目的:滾動到距頂部 statusBarHeight 的時候吸頂展示

原寫法:

style={{
    position: sticky,
    top: statusBarHeight,    
}} >

適配寫法

<ScrollView type="list">
    <StickySection pushPinnedHeader={false}>
        <StickyHeader offsetTop={statusBarHeight}>
            <View className={styles.view}>
              ...
            </View>
        </StickyHeader>
    </StickySection>
</ScrollView>

3. 子視圖節點有用到 position: absolute 的場景,根結點需要設置 position: relative

4. 在視圖設置全圓角的時候,單獨設置某一變的顏色,會使圓角失效:

.loading {
    border-radius: 100%;
    border-top-color: transparent;
}

現象:

5.position: fixed 屬性失效:使用 position:

absolute 和 position: relative 按需代替

6.z-index 只在同層級之間有效,跨層級無效:

如果實在無法提高層級,可以考慮使用: root-portal 組件

7. 所有節點默認是 relative,可能導致 absolute 不準 / margin-top 無效:

按實際情況調整 UI。如果遇到節點下的第一個 margin-top 無效,可以在前面加一個佔位的的 view

最終適配完成後的優化效果如下

冷啓動:

熱啓動:



  1. 資源位延遲加載

feeds 樓層存在着渲染時長偏長的問題,最主要的問題集中在店帶品樓層上:

該樓層帶有商品列表,列表中的商品每一個都會渲染一個資源位,數目在 15 到 20 個不等,這樣的樓層會下發 13 個左右,且每次都會在接口下發後一次性全部渲染,導致渲染的資源位數目暴增。

本次優化對商品資源位的加載進行了優化,首屏只最多渲染 6 個:

其餘商品在滑動觸底是懶加載。

<ScrollView
 ...
 onScrollToLower={handleScrolltolower}
 ...
/>

const handleScrolltolower = useCallback(e => {
 if (loadMoreImg.current == false) {
 loadMoreImg.current = true
 //加載剩餘圖片 setDatasource)
 }
}, [loadMoreImg])

以此方式來減少渲染工作量,提高渲染速度。底部的 feeds 商品資源位也採用相同的處理方式,首屏最多加載 6 個:

3. 多團隊溝通優化

除了使用懶加載的方式,我們也積極與產品和 UED 團隊溝通,針對店帶品的使用場景溝通解決方案。最終確定可以將首屏下發的樓層數從 13 個調整爲 9 個,進一步降低渲染壓力,提升 feeds 部分的渲染速度。

在實際優化實踐中,往往與其他團隊進行溝通,是最有效的優化方式,大家可以多借鑑一下。

4. 圖片資源優化

圖片資源尺寸過大,會導致圖片下載緩慢,資源位白屏,用戶體驗差。以往網管在進行商品圖片下發的時候,無論是店帶品樓層的商品還是商品詳情頁展示的商品大圖,採用的都是同一套尺寸較大的圖片,這就導致在店帶品樓層商品列表過多時,圖片下載過程等待時間過長。經過與後端團隊,產品和 UED 團隊積極溝通,確定了一套 3 尺寸圖片方案:

產品配置圖片的時候,會配置大、中、小三種尺寸的圖片,網關在下發時會根據資源位的類型區別下發,針對店帶品樓層、feeds 商品這種樓層,僅下發小尺寸圖片,以減小接口請求數據量以及圖片下發時間,極大地提高了圖片夾雜速度。

5. 接口請求邏輯改造

秒送頻道頁涉及到兩個接口請求,分別是主接口和 feeds 數據接口,之前因爲代碼結構的原因,兩個接口採用了串行請求的方式做請求。這次的優化經過方案評審,將串行改爲並行,並將兩個接口返回的結果進行隔離,分批渲染,從而降低了整體接口請求的時長。

優化成果

經過一系列優化,在接口請求總時長,feeds 渲染提升非常明顯,首屏加載速度有了很大提升:

根據掐秒錶的結果,也能夠最直觀的感覺出整體開啓速度的提升:

結語

Taro 小程序開發的性能優化實踐,不僅涉及到前端代碼優化,還涉及到了多個團隊之間的溝通配合,好的代碼習慣也不是一朝一夕就能養成的,優化也需要日積月累,不斷持續地推進,希望這篇文章可以幫助到大家,助力大促期間的用戶體驗改進。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/fIL-wCeXinjbWmGD5pT6mg