以往我們說某一功能跨多端,往往是指在諸如 PC、移動等不同類型的設備之間都能實現;或者更加具體一點,指的是「跨平台」,可能是大到跨操作系統,比如 Windows、macOS、Linux、iOS 與 Android 等,可能是小到跨某個具體技術的不同實現庫。

但是今天我們要介紹的是關於跨 MVVM 架構模式各種環境的場景。

Chameleon 是一套開源跨端解決方案,它的目標是讓 MVVM 跨端環境大一統,實現任意使用 MVVM 架構設計的終端,都能使用其進行開發並運行。

在這樣一個 MVVM 環境中,涉及到了 Weex、React-Native、WebView/瀏覽器與 Flutter 等各種跨端技術,還有它們實現的具體業務產品,比如微信小程序、快應用、支付寶小程序、百度智能小程序、今日頭條小程序與其它各類小程序。

也許你發現了,這裡提到了許多種「小程序」,雖然最早微信小程序的概念甚至早期版本出現的時候,有過不少不看好的聲音,但是隨著它不斷發展,目前已經成為了大眾生活不可或缺的應用形態。

馬化騰透露過,截至 2018 年 11 月有 150 萬微信小程序開發者,小程序應用數量超過 100 萬,覆蓋 200 多個細分行業,日活用戶達到 2 億。這樣的成功經驗與幾乎觸及到生活方方面面的巨大流量入口,大家都想入場,於是可以看到後來其它公司紛紛給出了類似的小程序方案。

另一方面,除了小程序百花齊放,2018 年小米、華為、OPPO 等 10 家安卓手機廠商還結成了快應用聯盟,並且先後發布了一系列快應用。

Chameleon 目標就是要跨這些端,而隨著各家不同實現越來越多,跨端場景也不斷變得更加複雜。我們採訪了 Chameleon 創始人張楠,請他為讀者具體分享了 Chameleon 在這個過程中的成長。

項目地址:github.com/didi/chamele

本文是 Chameleon 首次對外公開實現原理!

乾貨超多,包括:

  • 終端開發未來的開發模式
  • Chameleon 跨端實現原理
  • 當前各種跨端方案原理對比(各種小程序、快應用等)
  • 與 Taro 的對比
  • 演進過程中遇到的困難與思考

當初為什麼去研發 Chameleon?

關於這個問題可以從行業背景講起。

中國互聯網路信息中心(CNNIC)發布的《中國互聯網路發展狀況統計報告》顯示,截至 2018 年 6 月,我國網民規模達 8.02 億人,微信月活 10 億 、支付寶月活 4 億、百度月活 3.3 億;另一方面,2018 Q3 中國 Android 手機占智能手機整體的比例超過 80%,月活約 6 億。

BAT 與 Android 成為了中國互聯網真正的用戶入口。但凡流量高的入口級別 APP 都希望做平台,成為一個生態平台和互聯網流量入口,大量第三方應用的接入,從業務層讓公司 APP 關聯上更多企業的利益,並且擁有更強的生命力;從技術層面可以利用「本地能力介面層」收集大量用戶數據,從消費互聯網到產業互聯網需要大量各行各業基礎用戶數據線索進行驅動和決策。

在這麼一種背景下,再結合計算機技術的發展歷史,我們知道每一種新技術的出現都會經歷「各自為政」的階段,小程序技術也不例外,所以我們看到了其它各種小程序平台出現。

微信小程序作為首創者,雖然其它小程序都有在技術實現原理、介面設計上刻意模仿,但是作為一線開發者在不同平台發布小程序,往往還是需要重複開發、測試,從前 1 單位的工作量變成了 N 單位的工作量。而這還沒算上快應用等其它入口。

這種情況下,滴滴的研發工程師是其中最顯著的「受害者」之一,滴滴出行在微信錢包、支付寶、Android 快應用都有相關入口,而且用戶流量佔比不低。

研發同學在端內既追求 H5 的靈活性,也要追求性能趨近於原生。面對入口擴張,主端、獨立端、微信小程序、支付寶小程序、百度小程序、安卓廠商聯盟快應用,單一功能在各平台都要重複實現,開發和維護成本成倍增加。

迫切需要一個只維護一套代碼就可以構建多入口的解決方案,於是我們著手去打造了 Chameleon(CML,卡梅龍)這麼一個項目,真正專註於讓一套代碼運行多端。

Chameleon 核心是運用了 MVVM 架構,為什麼它可以實現跨多端?

MVVM 也就是 Model View ViewModel,它本質上是 MVC( Model View Controller)的進化版本,將 View 的狀態和行為抽象化,使得視圖 UI 和業務邏輯分開。

它是一種讓數據驅動反射視圖的模式,發展到現在可能會偏離它的初衷了,更像是一個視圖數據間的「通信協議」,讓終端開發變得更加單純,這是一種趨勢,面向未來框架都採用這種模式。

Facebook 在 2013 年開源 React,React 這個項目本身是一個 Web UI 引擎,隨著不斷發展,它衍生出 React Native 項目,用來編寫原生移動應用。正是它給跨端方向帶來了 MVVM 模式。

Vue.js 於 2014 年左右發布,逆流而上佔據了大量用戶群體,2016 阿里巴巴也基於它發布了 Weex 項目,使得可以用 Vue 編寫 Native App。

Google 在 2018 年末正式發布了面向未來的跨 Android、iOS 端的 Flutter 1.0.0。

原理

我們知道終端開發離不開三大要素——界面表現(結構、外觀)層、邏輯處理層與系統介面層(網路、存儲與媒體等)。

開發者編寫代碼時在初始化階段(生命周期)調用「界面表現層」界面模型的介面繪製界面,當用戶觸摸界面時,「界面表現層」將事件發送給用戶「邏輯處理層」,後者經過條件判斷再處理並反饋到用戶界面,處理過程可能需要調用「系統介面層」,反饋過程需要調用「界面表現層」的介面。

常規的終端開發架構模式下,無論是 Web 端、Android 端還是 iOS 端的項目開發,都強依賴各端的環境介面,特別是依賴界面相關模型設計。

iOS 系統下繪製界面基於 Objective-C 語言環境下的 UIKit 框架;Android 系統下用戶繪製界面基於 Java 語言環境,由 LayoutInflater 處理 XML 結構層次樹;Web 端使用 DOM 模型和 CSS 來描述繪製界面。

MVVM 中的關鍵是它通過 ViewModel 這一層將界面和邏輯層徹底隔離開來,負責關聯界面表現和邏輯處理層的響應事件(update/notify)關係,這一「隔離層」上下通信足夠規範、足夠純凈單一。

Model 進行邏輯處理是純業務響應邏輯,任何一種語言都可以實現,你可以用 Android 的 Java,也可以用 iOS 的 Objective-C,你心情好用「世界第一語言 PHP」也能實現。

之所以普遍選擇 JavaScript,很大程度是因為在這個領域內它的優點顯著,如學習成本低、天生具備跨端屬性、虛擬機(V8、JavaScriptCore)和各方向組件建設較好、生態活躍。

而系統介面層則更簡單了,只需窮舉統一基礎介面+可擴展介面能力即可。

各種 MVVM 方案

具體來看看各種 MVVM 方案都是怎麼樣的。

React Native、Weex 與快應用的 MVVM

開發者編寫的代碼在虛擬機(V8、JavaScriptCore)裡面運行,虛擬機容器裡面包含擴展的系統基礎介面。運行時,將描述界面的數據(主要是 CSS+DSL 所描述內容)通過通信層傳遞給 Android、iOS 端的渲染引擎,用戶觸摸界面時,通過通信層傳遞給虛擬機裡面的業務處理代碼,業務處理代碼可能調用網路、儲存與媒體等介面,最後再次反饋到界面。

Flutter 的 MVVM

Flutter 和 RN 的最大區別在於將「JavascriptCore/V8+JS」替換成「C++ 實現的 engine+Dart 實現的 Framework+靜態類型 Dart+編譯成機器碼」。

Flutter 的方案如下圖所示:

Service 其實就是本地能力介面層,Widget 樹是視圖層模型。

Flutter 和 RN 的使用面設計上類似,Flutter 文檔中提到「In Flutter, almost everything is a widget.」,widget 的調用從 RN 的 JSX 變成 Flutter 的 widget 調用,UI 的外觀描述從 RN 的 CSS(文本樣式、布局模型、盒模型)到定製化 Flutter Widget(textStyle 、Layout Widget、Widget)。

本質上 Flutter 也是 MVVM 架構,邏輯層通過 setState 通知視圖層更新,一定程度上這也是為什麼 Flutter 敢說能轉成 Web 框架的原因,核心還是基於這類數據驅動視圖架構模式,業務代碼不會深度依賴任何一端特有的「視圖模型」。

各類小程序的 MVVM

小程序本質上和 Weex、React Native 的設計思路基本一樣,最大區別在於前者還是用瀏覽器 WebView 做渲染引擎,而後者是單獨實現了渲染引擎(所以大量的 CSS 布局模型不支持)。

具體到 Chameleon 上是怎麼實現的?

首先任何一份應用層的高級語言代碼塊分成幾層:語言層(Language)、框架層(Framewrok)與庫層(Library):

  • Language —— 通俗來說,實現程序所需的基本邏輯命令:邏輯判斷(if)、循環(for)與函數調用(foo())等。
  • Framewrok —— 通俗來說,完成一個 App 應用交互任務所需規範,例如生命周期(onLoad、onShow)、模塊化與數據管理等。
  • Library —— 可以理解就是「方法封裝集合」。比如 Web 前端中 Vue 更適合叫框架,而 jQuery 更適合叫庫;Android 系統下 activity manager + window Manager View System 等的集合叫框架,而 SQLite 、libc 更適合叫庫。

對應到 Chameleon 就是這樣:

具體到實現原理全景架構圖如下:

你可以理解 Chameleon 為了實現「讓 MVVM 跨端環境大統一」的目標做了以下工作:

  • 定義了標準的 Language(CML DSL)、Framework 與 Library(內置組件和 API)協議層。
  • 在線下編譯時將 DSL 轉譯成各端 DSL,只編譯 Language 層面足夠基礎且穩定的代碼。
  • 在各個端運行時分別實現了 Framework 統一,在各個端盡量使用原有框架,方便利用其生態,這樣很多組件可以直接用起來。
  • 在各個端運行時分別實現了 Library(內置組件和 API)。
  • 為用戶提供多態協議,方便擴展以上幾方面的內容,觸達底層端特殊屬性,同時提升可維護性。

實現思路很簡單,所有設計為了 MVVM 標準化,不做多餘設計,所以宏觀的角度就像 Node.js(libuv)同時運行在 Windows 和 macOS 系統,都提供了一個跨平台抽象層。

從 MVVM 角度來看的話:

  • View(展現層)
    • 第三方 Render Engine:各類框架已有框架,瀏覽器的 Vue、Webview 里的小程序引擎、Android、iOS 裡面的 React Native/Weex 引擎、甚至 Flutter 裡面的 Dart Framework。
    • Chameleon 內置組件庫:多態協議定義統一組件 view、input、text、block 與 cell 等,它是界面組層的原始基類,衍生出多複雜界面功能。
  • ViewModel(關聯層)Chameleon 語法轉譯
    • 組件調用
    • 循環
    • 條件判斷
    • 事件回調關聯
    • 父子關係
    • ……
  • Model(邏輯響應層)
    • JavaScript 代碼
    • CML Runtime 框架
    • Chameleon API:多態協議定義統一介面,cml.request、cml.store 等

Chameleon 的跨多端方案給開發者的開發帶來了極大的便利,具體表現是怎麼樣的?

一句話:基於 Chameleon 開發,效率會越來越高

各個端的湧現,讓原本是 1 的工作量因為多端存在而變成 N 倍,使用 Chameleon,工作量會變回 1.2。這多出來的 0.2 工作量是要處理各端的差異化功能,比如以下場景:

  • 某業務線遷入 Chameleon 時,發現沒有「passport登錄組件」,在各類小程序裡面能免密登錄了,在 Web、Native 端是彈出登錄框登錄,不同業務用戶交互形態不一樣所以 Chameleon 沒有提供組件;開發者需要基於多態協議擴展單獨一個登錄組件<passport/>,無論如何最後返回一個登錄後的回調 token 即可,外部無需組件關心裏面如何操作。
  • 用戶需要分享功能,發現沒有「share組件」,在微信 Web 端可以引導右上角分享,在小程序直接分享,不同業務用戶交互形態不一樣,用戶需要基於多態協議擴展單獨一個登錄組件<share/>。

這種各端差異較大的例子,隨著業務的積累,可以變成了一個個業務組件單獨維護,後面也不需要重複開發了,且反推產品體驗一致化,組件三層結構「CML框架內置組件->CML擴展組件->業務開發者自己擴展的多態組件」達成 100% 統一。

隨著組件積累業務開發工作量越來少,工程師可以專註做更加有意義的事情,這就是 Chameleon 存在的目的。

基於統一的跨端抽象,用戶在 Chameleon 項目持續維護過程中,Chameleon 發布新增一個端之後,你的業務代碼基本不用改動即可無縫發布成新端。

比如這個 cml-yanxuan 項目開發時支持 3 個端,後面新增了百度、支付寶小程序端,原有代碼直接能跑起來運行 5 個端,一端所見即多端所見。

開發時只能跑 3 個端

原有代碼無縫支持 5 個端

另外特彆強調的是,對於大公司團隊,如果有很強的技術能力,希望開發的代碼掌控在自己手裡,對輸出結果有更好控制能力。其實 Chameleon 內置組件和內置 API 是可以替換的,那麼所有組件都是業務方自己開發了,哪天不想用了直接導出原生組件即可離開 Chameleon,如下圖:

目前跨多端統一的方案中,Taro 是比較亮眼的,能否具體對比一下 Chameleon 與 Taro。

我們覺得 Chameleon 與其它解決方案的最大區別在於其它框架都是小程序增強,即用 Vue 或者 React 寫小程序,這些框架官方給的已接入例子也都是跑微信小程序。

它們更加類似 Chameleon 的前身 MPV(Mini Program View),即考慮如何增強小程序開發。2017 年微信小程序發布時,滴滴作為白名單用戶首先開始嘗試接入,開始面對重複開發的難題。

這時候我們專門成立了一個小項目組,完成一個名為 MPV 的項目,一期目標是「不影響用戶發揮,不依賴框架方的原則性實現一套代碼運行 Web 和微信小程序」。

看著很美好,用這樣的方案實現 Web 端和小程序端,也確實完成了超過 90% 代碼重用,總體上開發效率和測試效率都有了一定提升,但是卻不是真正意義上的跨多端統一。

單獨說到 Chameleon 與 Taro 的區別,總體上看,可以歸為這樣一個表:

表中每一項都是在做跨端方案時需要考慮到的。我們說除了 Chameleon,其它方案都只是在對小程序進行增強,或者說是模仿微信小程序的 API 和組件的介面設計。

Taro 是通過將 JSX 轉成小程序模板,在其它端模擬微信小程序的介面和組件,讓其它端更像微信小程序,業務開發時不一致的地方需要環境變數判斷差異分別調用,會造成端差異邏輯和產品邏輯混合在一起。

此外,它要跟隨小程序更新,業務方會有雙重依賴;其它端的和小程序不能保持一致,用戶要各種差異化兼容,不利於維護。

那 Chameleon 呢?Chameleon 把這些問題都考慮到了,所以在早期偽跨端 MiniProgram View 成型之後不斷演進的過程中,把它發展成為一個真正的跨多端方案。

前邊的表格顯示了,Chameleon 既考慮統一性,又考慮差異性,且差異性不會影響可維護性;當各端差異確實太大,那就不要用一套代碼實現多個端同一頁面,而是統一公用組件。

這還只是拿 Chameleon 與 Taro 的重合點進行了對比,但是別忘了 Chameleon 不僅僅是前端框架,它:

  • 還有統一的 Chameleon Native SDK,Chameleon 不僅僅希望統一各類小程序,還要覆蓋自家 APP,會持續通過 Native SDK 擴展 API 和組件,期望有與小程序一樣的本地能力。理想情況下,一套代碼就能在各類小程序、自家 APP 裡面無縫平滑運行。
  • 還有待開源的後台管理系統。
  • 還有待開源的 XEdtior 非研發用編輯器,可以直接編輯跨端頁面、直接發布。

另外,未來還將帶來以下能力:

  • 後端統一介面(消息推送、分享與支付等)
  • 基於統一的 MVVM 標準,更有基於 Flutter 的原生 APP

當前的各類小程序和 Native 跨端框架,類似當年多個瀏覽器時,Safari、Chrome、Firefox、IE 6/7/8/9、Android 瀏覽器等盛行的時代。以這個來類比,那麼 Chameleon 的介面組件設計上更像一個 jQuery。

網路請求有的是 XHRHttprequest 有的是 ActiveXObject,jQuery 考慮的是用戶需要什麼,需要一個網路請求介面,支持 get、post 等,所以 jQuery 寫一個既非 ActiveXObject 又非 XHRHttprequest 的名為 $.ajax 介面,提供一個封裝網路介面,你不用關心內部在不同端怎麼調用的,jQuery 內部會幫你兼容。

Chameleon 也是一樣的思路,所有的介面設計都是真正能兼容跨所有的端,沒有差異性,而且只保留當前所在端的介面調用代碼:IE 裡面只保留 ActiveXObject,Chrome 只保留 XHRHttprequest。

Chameleon 的介面設計上比 jQuery 更強的地方在於,使用標準的多態協議,保障可維護性,性能上只保留當前端代碼,且將多態協議暴露出來,讓用戶也能擴展自己想要的 API(類比 $.xxx)。

當然時代已經變了,監聽視圖不在是 $(#xxx).click(fn),而是 MVVM 數據驅動視圖方式了,所以提供了 Chameleon 雙向綁定這樣的 VM 層。

前邊講到了 Chameleon 的前身 MPV,那具體分享一下 Chameleon 的整個演進過程吧。

出生期:選擇轉譯還是模擬小程序環境?

前面講到,2017 年的時候,我們完成一個名為 MPV 的項目,一期目標是不影響用戶發揮,不依賴框架方的原則性實現一套代碼運行 Web 和微信小程序。

當時缺乏小程序資料是遇到的最大問題(就更別提今天講到的業內這麼多解決方案了),當時唯一一個可以參考的開源項目是 WEPT,WEPT 是一個微信小程序實時開發環境,它的目標是為小程序開發提供高效、穩定、友好、無限制的運行環境。它的設計思路是在 Web 端模仿小程序環境執行。

於是我們在開發 MPV 時考慮了兩種實現策略:

1、在 Web 端像 WEPT 一樣 mock 小程序環境;就像微信開發者工具裡面也模擬了小程序執行環境,WAServie、WAWebview 提供的兩套環境源碼做底層,在頁面中開啟三個獨立運行環境運行並用 iframe 通訊模擬微信小程序的 3 個 Webview 之間的聯通關係。

2、逐個轉譯代碼支持小程序,缺點是可能會有 edge case 需要處理以及潛在的 bug 會比較多。

最終在看完 WEPT 源碼和微信開發者工具的情況下,我們明確放棄了第 1 條實現策略,選擇了逐個轉譯代碼支持小程序的路線,主要原因是於 Web 端兼容微信所有的功能,尺寸過於龐大。

經過三個月緊鑼密鼓的開發終於實現了第一版本 MPV:

經過實現幾個 demo 之後,開始執行遷移計劃:

MPV 在 Webapp 上實踐最終實現效果如下:

最終實現效果挺美好,也確實完成了超過 90% 的代碼重用,總體上開發效率和測試效率都有了明顯提升。

但是在後續實踐過程中,發現存在大量的問題,並且項目越大問題越凸顯出來,總結如下:

  • 可維護性問題,沒有隔離公用代碼和各端差異代碼。項目中不止有業務邏輯,還混雜著 Web 端和小程序端產品功能差異化邏輯。比如前邊舉過的例子,分享功能 Web 端無法實現(引導分享),小程序可以實現,意味著各種環境判斷各種差異化邏輯,牽一髮動全身,還要來回測試。
  • 方向選擇錯誤,MPV 使用了小程序語法標準(小程序的生命周期、API 介面等),導致用戶使用上無法清晰理解。
  • 不能直接使用各端已有生態組件,即缺乏標準規範接入某個端已有開源組件。比如 Web 端 pick.js 組件缺乏快速接入規範,用戶要麼重新開發,或者在模板和 js 代碼中使用環境判斷的方式針對引入。最終導致同一功能不同端的調用方式、輸入與輸出不一致。
  • 業務項目依賴 MPV 框架。框架依賴微信小程序介面(模板、生命周期與介面),擴展了統一介面。例如微信小程序更新了 wx.request 時,業務項目方無法立刻使用,需要等框架更新。
  • 文件夾結構混亂,混雜著多個端代碼文件,且識別成本高。
  • 不支持 vuex、redux 等高效數據管理方式
  • 尺寸單位不統一,px 和 rpx 不一致
  • 周邊小型差異點太多:
    • 協議不一致,例如 Web 端可以用 //:didiglobal.com/passenge ,小程序只能用 https://:didiglobal.com/passenge
    • 打開一個新頁面時鏈接不統一,例如打開發單頁時,Web 端是 //:didiglobal.com/passenge,小程序是 /page/create
  • 頁面之間跳轉時,傳參不統一
  • debug 成本高,修改完代碼之後兩端需要測試
  • 兩端界面效果不一致,基礎內置組件統一性建設不足
  • 工程化建設落後,例如不支持 liveroload、數據 mock、資源定位、proxy、多端統一預覽
  • 介面設計不完整,生命周期、組件分層、本地 API 設計等
  • 模板 DSL 語法不規範

成長期:從偽統一到大一統

在 MPV 的實踐積累下,有了一定的底氣和把握,後續的規劃更加明確。2018 年 4 月我們把跨端項目規模進一步擴大,想要做一個真正跨 N 端的解決方案,目標是提供標準的 MVVM 架構開發模式統一各類終端。這就是 Chameleon 的出現契機。

Chameleon 真正想要一套代碼運行多端,總結下來要解決幾大問題:

  • 要全面完成端開發的所有細節的統一性,特別是界面統一性有大量細節要做
  • 要在完成上一條的前提下考慮差異化定製空間
  • 持續可維護

目標理想業務形態是這樣的:

圖中上半部分是傳統開發方式,下半部分 Chameleon 的模式抽象出了 UI 渲染層和本地介面能力層,業務代碼一部分簡單頁面由 XEditor(h5Editor 的前身)編輯工具產出,另一部分工程師使用 Chameleon 開發,不止解決跨端問題,還彌補改進了工程開發過程中的效率、質量、性能與穩定性問題,讓工程師專註有意義的業務,成長更快。

首個 Native 渲染引擎選擇——小程序架構、RN/Weex 架構

從 MPV 到 Chameleon,外界看來最明顯的變化是從跨 2 端(Web、小程序)升級到跨多端(Web、小程序、Android、iOS),最開始糾結於首個端上版本的渲染引擎使用小程序架構還是 RN/Weex 架構。

RN/Weex 網上有大量資料可查,但是小程序方面則不然。千辛萬苦搜索之後,根據一位知道內情的朋友的描述分享,才有了一定的了解。

這裡分享幾個印象深刻的要點:

  • 小程序展現層使用 Webview,裡面內置了一套 JS 框架用來和 Native 通信,真正業務代碼執行在單獨 JS 虛擬機容器實例中
  • JS 虛擬機容器使用情況,iOS 系統是 JavaScriptCore,Android 系統使用 QQ 瀏覽器的 X5 內核
  • 小程序的各個 TAG 組件使用的數據驅動用的是 Web Components
  • 顯而易見,部分性能要求較高的使用原生控制項(視頻、鍵盤等等)插入到 Webview 裡面。
    • 原生控制項的具體位置 Native 怎麼獲取?答案是由嵌入到 Webview 的一套小程序框架通知給原生層
    • 原生控制項怎麼保證在內部可滾動的元素(Scroll-view)裡面正常滾動?答案是 CSS 設置 -webkit-over-scroll:touch 時,iOS 的實現是原生的 UIScrollView,Native 可以通過一些黑科技找到視圖層級中的 UIScrollView,然後對原生控制項進行插入和處理;而 Android 直接繪製沒辦法做到這點。現在(截至 4 月)僅僅是直接覆蓋到 Webview 最外層的 scrollview 上,由內置到 Webview 的一套 JS 框架控制原生控制項位置

最終多方面分析如下:

雖然小程序方案看起來很簡單,但其實很多細節點需要大量打磨,從確認方案到真正可以跑起來可以線上發布,僅僅花費在終端上的研發人力為 20P*6 個月,微信小程序團隊的目標和我們跨端目標不一樣,他們投入這麼多成本是值得的,我們為了跨端沒必要投入這麼高成本。

所以我們選擇放棄小程序渲染方案,而使用已開源的 RN/Weex 方案

第一個版本最終使用 Weex,包括團隊同學去看了 Weex 源碼實現。

在整體設計上僅僅使用 Weex 渲染功能,外層包裝介面,保障後續能有更高擴展性。

Chameleon Native SDK

針對 Native SDK 我們主要從原生能力擴展、性能與穩定等三個方面做了工作。

  • 原生能力擴展:無論是 Webview 還是 React Native、Weex 甚至 Flutter 都只提供渲染能力(以及一些最基礎本地介面),更多完成業務功能所需本地環境的能力(例如分享到微信)需要 Android 和 iOS 的 Native 往容器去擴展。本地能力包含 2 種,涉及 UI 界面的統一叫組件(UI 組件如登錄、支付),涉及到純能力調用的統一叫 API(網路、存儲等)
  • 性能:界面展現和交互耗時關鍵取決於 2 塊,資源載入耗時(非打包到安裝包部分代碼)、執行耗時
  • 穩定:主要關注灰度發布(風險可控)和線上止損,主要工作是按用戶灰度發布、可以快速降級到 H5

以下是性能方向中的首屏載入時間的優化數據,原有 H5 使用 SSR(Server Side Render)已經算是最快的 Web 首屏技術方案了(不考慮優化後端多模塊耗時的 BIGPIPE),它保持在 1.5 秒以下,在優化後降到 0.5 秒左右。

性能優化中我們有一個關於執行速度的 TODO 計劃。同樣是跨端,Flutter 之所以比 Weex 和 RN 執行速度快,主要原因是前者是編譯型,客戶端機器運行前已經是 CPU 可識別的機器碼;後者是解釋型,到客戶端運行前是字元串,邊編譯邊執行,雖然做了 JIT 盡量優化,差距還是較大。其實在這中間還有一個抹平了不同 CPU 架構下機器碼差異的中間碼;當然前提是開發語言改成靜態類型,這裡不作展開。

原本分 5 次開發的 Web 端、支付寶小程序、快應用、微信小程序、Native 端變成了 1.2 次左右開發了。最重要的是隨著業務級別各端差異化的多態組件和跨端組件積累,後續 1.2 工作量也會變成 0.8,0.4 的優化主要來自兩個方面:

  • 0.2 是普通跨端組件的積累,復用度變高
  • 0.2 是各類業務級別的差異化多態組件,例如登錄功能,在 Web端、Native 端和小程序端實現和交互是不一致的,這時候業務形態不一樣,設計的 <passport> 組件也不一樣,只能各業務線去封裝。

介紹一下接下來的 roadmap。

我們的最終目標是提供標準的 MVVM 架構開發模式統一各類終端。

接下來的具體 roadmap 如下表所示:

歡迎有共同願景的同學加入我們一起共建,往倉庫貢獻自己的代碼。

項目地址:github.com/didi/chamele

QQ 群:

公眾號:

採訪嘉賓介紹

張楠,Chameleon 創始人,技術團隊負責人,前百度資深工程師,終身學習者。


推薦閱讀:
相关文章