無線動態化解決方案總結:從WeApp到Weex

高鬆發表於2016-07-25

前言

入職阿里的兩年時間,有幸一直從事無線動態化解決方案。從最初的WeApp,到現在的Weex,經歷了WeApp的從無到有,從“輝煌”到沒落,見證了Weex的崛起,在雙十一主會場大放光彩。最近,工作方向有所變化,所以從技術角度談談個人對無線動態化的理解,同時也算是對我這兩年工作的總結。

無線動態化

業務上的變化根本等不及發版解決,這也是出現動態化方案的根本原因。一套優秀的動態化解決方案應該具備:

  • 簡單、友好、強大的DSL
  • 強大的開發工具
  1. Debug tool
  2. Native 強大的動態能力和高效能
  3. 跨平臺write once,run anywhere(Android、IOS、H5 …)
  4. 完備的釋出平臺
  5. 規範的開發文件

native動態化主要做的事情是:

  • 模板動態化和邏輯動態化
  1. 載入效能
  2. 滑動效能
  3. 水平擴充套件
  4. 接入簡單
  5. 無侵入性

WeApp

WeApp是一套基於json作為描述語言的跨平臺多終端渲染sdk,孵化於無線賣家的業務中。現在回頭來看WeApp,有了更深的體會:
在正確的時間做了恰當的事情,採用私有協議進行描述,快速落地,但是做了一年沒有調整方向(沒有轉換成標準協議,沒有徹底解決邏輯動態性),最終沒落。究其原因:

  • 技術視野,當初的技術視野受限
  1. 被業務侵入嚴重,積重難返
  2. 架構缺陷,native做的太重(自己寫了不太好用的condition等),動態性弱
  3. 沒有解決“寫”的問題,json作描述語言,很難編寫和維護
  4. 渲染效能,往往實現一個複雜點的元件需要10幾層的view,導致滑動效能下降
  5. 沒有好的開發工具

直到react native的出現才恍然大悟,原來還可以這麼玩,把動態性玩的這麼徹底,長恭老闆的破而後立,這才有了後面的Weex———欲練此功,必先自宮(葵花寶典就是這麼練成的)
最後說一句,WeApp是歷史時代的產物,它在當時也支撐了很多業務發展,同時也踩過很多坑,積累了大量無線動態化的經驗。

Weex

Weex本身不是新的技術,而是集大家之所長,react native思想和設計(非常關鍵)、flexbox佈局、v8引擎、vue.js和mvvm的思想組成了最終的Weex主體結構。Weex從最初的所有的方案設計都會拿WeApp的痛點作為參考.
Weex native總體架構(以手淘為例)

  • SDK:專注渲染,只依賴fastjson
  1. UI Kit:native的一些通用業務元件,如跑馬燈,電梯頭等
  2. Adapter:三方App的介面卡,接入自己app的網路層、埋點工具、導航系統,圖片庫等
  3. Bundle:包含頁面容器,攔截規則,模板快取等
    Weex_

                                                     Weex總體架構圖
    

Weex 渲染機制(同步和非同步)

同步機制

原理:同步機制原理比較簡單,JS Framework一次性建立所有的Dom樹,完成渲染。

不足:當進入A(Weex頁面)後,快速進入B(Weex頁面),A頁面沒法響應點選操作,返回也不能停止渲染,導致JS Thread 一直渲染髒資料。

適用場景:Native區域性使用Weex instance,並且DOM節點較少(不超過100)

非同步機制

原理:採用流式渲染和離屏渲染。

流式渲染:即JS Framework每建立一個節點,立即傳送給native,同時等待native的next tick命令的觸發才能繼續執行,這樣就有效的解決了頁面回退仍然在渲染,事件不能響應的問題。

離屏渲染:,即使用者在瀏覽頁面的過程中,後臺Dom執行緒繼續渲染更新頁面,將所有addDom、updateSytle等操作都以最小顆粒度拆分,保證所有的操作都在16ms內完成,大大提升首屏的載入效能以及滑動的流暢度。
Weex_
非同步渲染機制(摘自Weex首架@伊耆)

踩過的坑

  • json解析。同步渲染中,會將DOM資料一次性傳送至native,過大的json資料解析會大大降低載入效能(30kb資料解析需要150ms,手工加入asm後會提升20%~30%效能)
  1. 懶載入坑(潛在風險)。頁面載入只載入1屏高度的頁面,當使用者滑動底部載入下一頁資料,當使用者不滑動時,JS將某個元件給remove掉,導致不滿一屏高度,頁面滑不動。
  2. duktape引擎。最初由於包體積的問題,我們用的不是v8(arm zip1.6M,x86 zip 2M)這是一個標準的輕量級的js引擎,但是3000個節點壓測,JS執行需要8s。
  3. 滑動流暢度。懶載入會導致載入下一頁時的大幅度丟幀,因為這一操作沒辦法在16ms內完成
  4. 首屏載入體驗。首屏載入的體驗很大程度受到節點數的影響
    最終的優化方案都是通過一個個坑踩出來的。

動態JS

Weex除了做渲染之外,還可以通過註冊Module的方式,執行動態JS邏輯,比如通過JS動態規則下發等邏輯動態性,此處有潛在風險,由於Weex全域性只有一個Context,所以最好不要寫全域性的function,防止影響到Weex相關資料(這個很危險,有可能導致整個Weex不可用,問題還很難查),真要用的話,最好寫到某個Object中,如var mapping = Weitao.mapping(){}。

結尾

最後,期待@勾股和@鬼道將Weex繼續搞大,唱響全球。

Weex總體介紹有技術細節,請參考Weex總架前端大牛@勾股的三篇連載,或者直接騷擾他也行。附上鍊接


相關文章