Cube 技術解讀 | Cube 小程式技術詳解

阿里巴巴移動技術發表於2021-12-30

作者:曾維巨集(恆實)

本文為《Cube 技術解讀》系列第三篇文章,之前上線的《支付寶新一代動態化技術架構與選型綜述》《Cube卡片技術棧解讀》歡迎大家回顧。

小程式作為動態化或者跨端開發的一種技術棧,在業界成為事實標準。Cube 作為一種輕量級小程式技術棧,具有體積小、啟動快、記憶體佔用低等特點,也比較適合“即用即走”的小程式場景。以下將重點介紹 Cube 小程式技術棧與技術演進實踐(若無特殊說明,所有的資料和圖表都是針對小程式)。

Cube 渲染小程式

模組組成

小程式視角,Cube 渲染引擎主要由以下模組組成:

  • Components:主要是小程式規範裡的元件;
  • Layout:支援 Inline,Block,Flex,Inline-Block,Inline-Flex 等多種佈局方式,還包括文字分詞,斷行等計算;
  • Style:支援樣式解析,樣式匹配,樣式繼承,偽類和偽元素等多種選擇器;
  • Rendering:管理渲染相關 Render Tree,圖片資源請求排程等;
  • Animation: JS 和 CSS 動畫實現;
  • JS Bridge:和 JS 引擎橋接;
  • JS Engine:目前支援 V8,JSC,QuickJS;其中 Android 下支援 V8,QuickJS;
  • Compositor:用於動畫和圖層的合成器(開發中)。

執行緒模型

Cube 小程式技術棧內部有這麼幾個執行緒:Bridge,Layout,Render,Paint,UI 等。

  • Bridge 執行緒:執行 JS;與 AppX 橋接的類 DOM 的 JSAPI;處理 JS 相關事件;
  • Layout 執行緒:佈局計算;樣式計算與匹配;維護 Layout Tree;
  • Render 執行緒:維護 Render Tree;繫結資料;分層;
  • Paint 執行緒:生成繪製命令;
  • UI 執行緒:平臺事件分發;UI 佈局。

小結

  • 並行佈局,非同步繪製:這裡的並行是指 JS 執行,Layout 佈局 以及 Render 三者完全並行處理。由於 Layout 和 Render,Paint 等不在一個執行緒,因此是非同步繪製;
  • 多個執行緒協同工作,有點像 CPU 的 5 級流水線。

值得注意得是:Web 渲染引擎有個特點就是和 Node 相關的 DOM 操作必須和 JS 在一個執行緒。這就導致解析 HTML,佈局,樣式計算,DOM,JS (包括垃圾回收)都在一個執行緒裡。帶來的後果就是隻有解析完文件才能看到 UI 效果,這也是 Web 渲染小程式白屏時間較長的一個原因。

Cube小程式技術棧,將“DOM操作” 和 JS 執行解耦。因此 JS 的 GC 不會影響 UI 呈現。這種實現對於加快小程式啟動非常有幫助。由於佈局計算和 JS 執行也解開耦合,因此一般不會由於 JS 執行阻塞 UI 互動。

Cube 小程式技術棧的特點

  • 體積小,啟動快:主 so 只有 2.8 MB(如果包括 Ariver,AppX,InsideSDK,整體小程式技術棧最小是 5.7MB)。另外可以享受到 OS 的紅利(包括 UI 的初始化和快取);
  • 高效能:接近於原生體驗;
  • 記憶體佔用小:小程式技術棧初始化後(包括 Inside SDK,Cube,AppX),大約只需要 7.5 MB;
  • 支援 Android,iOS 雙端。

與 Web 引擎對比

下面僅僅針對小程式場景與 Web 引擎對比:

image.png

技術演進

讓小程式業務低成本適配 Cube 渲染小程式,需要做三方面的工作:

  • 擁抱 Web 技術,補齊前端開發常用的能力:包括 CSS,小程式元件等;
  • 完善相關工具:包括開發,除錯,Profile,釋出,打包等;
  • 針對 Cube 的架構特點,深入優化,並拉開和 Web 渲染的差異。提供更好的使用者體驗。

新的流式佈局(Flow Layout)

最初 Cube 小程式使用只支援 Flex 佈局 Yoga 用於佈局計算。後面升級成支援 Block,Flex,Inline-Block等多種佈局方式的 Flow Layout。從而解決開發者只能使用 Flex 佈局的困擾。目前兩個佈局引擎 Cube 內部都支援。其中 Flow Layout 主要用在小程式,Yoga 用在卡片。兩者能力差異如下:

image.png

支援 CSS 樣式表

老版本的 Cube 只支援內聯樣式和簡單的 CSS 選擇器;然而小程式並沒有約束 CSS,因此 Cube 擴充支援 CSS 樣式表,樣式繼承,多種選擇器等。從而使得 Web 渲染切換到 Cube 渲染,適配成本大大降低。甚至部分小程式可以做到在小程式 IDE 裡基於 Web 渲染開發,然後打包成 Cube 渲染產物在真機上預覽。前端同學無需進行過多的修改和適配。

新老 Cube 版本,選擇器支援上的差異如下:

注:

  • [1] 老版本 Cube 是指:錢包 10.2.0 以前版本;
  • 新樣式能力基本上對標 Web 引擎的樣式能力;
  • 新樣式能力支援像這種複雜選擇器。
div > div.jartto p span.yellow a#t1 {}
.pixel-ratio-2 .web1px::before {}
div:nth-child(2n+1) {}
input[type="button"] {}
#blue,div > div.jartto p span.yellow a#t1 {}

支援自動分詞,斷行(Inline Text)

最初 Cube 用的是 Android 和 iOS 提供的文字計算和繪製能力。這種技術方案(以下稱為平臺層 Text)存在3個問題:

  1. 效能問題:特別是 Android 下,利用 Android 平臺層的介面實現文字佈局計算,導致在文字較多的情況下,佈局耗時在渲染整體耗時裡佔比較高;
  2. 富文字特性:富文字以及許多文字特性支援較麻煩;
  3. 各平臺上實現文字效果存在細節差異或者相容性問題。

針對上述問題,在 Flow Layout 基礎上增強支援 Inline Text 佈局計算文字。基於 Inline Text 可以較輕鬆實現以下富文字,圖文混排,分詞,自動換行等。

1.富文字

2.自動換行和分詞

Inline Text 實現前後的文字樣式對比如下:

image.png

  • 假設原有 Cube 採用平臺層介面實現的文字特性稱為:平臺層 Text
  • 表示實現細節上不完善或者不完全支援;
  • 在 Inline Text 基礎上可以實現功能豐富的富文字元件;
  • 值得一提的是:該實現非常精巧,對於 Cube 包體積只增加了 170KB。具體細節後續文章詳細探討。

文字佈局計算耗時對比(文字節點較多場景):

image.png

採用 QuickJS 替代 V8

V8 雖然是效能最高的 JS 引擎,但是存在記憶體佔用大,初始化較慢等不足。在 IoT 或者低端裝置上這些不足會被放大。因此在這些裝置上,Cube 採用 QuickJS 取代 V8。一方面降低記憶體佔用,另外一方面提升初始化效能。

Cube 內部目前適配了多個 JS 引擎,具體如下:

  • 在 Android 移動端上使用 V8 和 JSI
  • iOS 上使用 JSC
  • IoT 等低端裝置上使用 QuickJS

另外我們在開源 QuickJS 基礎上做了些優化工作。優化的結果大致如下(後續文章將詳細介紹):

image.png

支援動畫和多媒體元件

除了上述基礎元件和能力之外,動畫和多媒體也是部分小程式不可缺少的。因此我們擴充套件支援了 VideoCanvasLottieLive Player 等元件支援。並應用於 TV 大屏小程式、小遊戲以及直播場景上。

在低端裝置上,如何提高動畫幀率並且降低記憶體佔用也做了深度的優化。以下是 Video 和 Canvas 元件在小程式中的效果圖:

image.png

支援多種模式的小程式產物

目前 Cube 支援多種模式的小程式產物:NativeCubeShared

  • Native 模式:對應的是舊的 Cube 渲染小程式模式,不支援 CSS 樣式表,只能支援內聯樣式和有限的幾種 CSS 選擇器。效能最高,相容性較低;
  • Cube 模式:在 Native 模式進化而來,支援 CSS 樣式表和多種 CSS 選擇器。效能良好,支援常用的 CSS 樣式和特性(包括樣式繼承,多種 CSS 選擇器);
  • Shared 模式:為了降低 Web 渲染的小程式遷移或者過渡到 Cube 渲染而開發。在同一個小程式產物裡既支援 Web 渲染一部分頁面又支援 Cube 渲染一部分頁面。而且 Cube 渲染的頁面支援樣式表。這樣在效能和相容性平衡。小程式產物相對於 Web 渲染的小程式,產物體積增加不會超過 10%。

image.png

:如果需要 Web 產物兜底,則 Native 模式Cube 模式的小程式產物,比 Shared 模式大。

當前工作

Cube 小程式在 TV 和 POS 機上和相關團隊,一起打磨小程式技術棧(包括渲染引擎,JS 引擎,AppX,Ariver 容器)等。

在 TV 上面臨的問題:

  • 記憶體少:有的裝置只有 512MB 記憶體,長列表滾動容易卡;
  • 需要支援焦點切換;
  • CPU 主頻較低:有的只有 1GHz。

短中期目標是用小程式技術棧替代 WeeX 單頁。當前進展如下:

  • 小程式啟動效能上超過 WeeX 單頁(低端裝置上優勢更明顯);
  • 記憶體佔用上,小程式初始化後記憶體佔用小於 10MB,典型小程式整體記憶體佔用在 32MB 左右。

具體細節後續文章詳細總結。

在 POS 機上面臨的問題:

在 POS 機上跑點餐小程式,主要有面臨以下問題:

  • 記憶體少:部分裝置只有 512MB 記憶體,容易出現卡死和 OOM;
  • CPU 核心少:部分 CPU 只有雙核(硬體效能大約是主流手機的 1/5);
  • 長列表滾動卡。

短中期目標是用小程式技術棧替代 Flutter 開發的 App。當前進展如下:

  • 小程式首屏啟動效能提升了 30%+;
  • 小程式重點的互動場景的頁面,比如:購物車,商品詳情頁等,都已接近 Flutter App;
  • 首頁滾動幀率達到 50,使用者已經難以感知和 Flutter 的差異(Flutter 幀率是 60);
  • 小程式記憶體佔用下降了 30%(本地測試已無卡死和 OOM)。

該場景主要是文字節點較多的長列表。採用了非常多的優化方法,後續文章詳細總結介紹。

總結

為了適配小程式,Cube 渲染引擎在佈局計算、樣式能力、元件支援,還有開發工具等在小夥伴一起努力下取得了較大的進展。同時在低端裝置(比如:IoT 裝置)或者效能敏感場景,Cube 小程式效能優化,降低記憶體佔用也取得了不錯的效果。而未來面對多種多樣的 IoT 裝置,還需要加速技術演進以支援更多的場景。歡迎大家一起來交流討論。

關注【阿里巴巴移動技術】微信公眾號,每週 3 篇移動技術實踐&乾貨給你思考!

相關文章