摘要:中國(guó)互聯(lián)網(wǎng)絡(luò)信息中心發(fā)布的中國(guó)互聯(lián)網(wǎng)絡(luò)發(fā)展?fàn)顩r統(tǒng)計(jì)報(bào)告顯示,截至年月,我國(guó)網(wǎng)民規(guī)模達(dá)億人,微信月活億支付寶月活億百度月活億另一方面,中國(guó)手機(jī)占智能手機(jī)整體的比例超過,月活約億。在年末正式發(fā)布了面向未來的跨端的。
開源中國(guó)專訪:Chameleon原理首發(fā),其它跨多端統(tǒng)一框架都是假的?
原創(chuàng): 嘉賓-張楠
開源中國(guó)
以往我們說某一功能跨多端,往往是指在諸如 PC、移動(dòng)等不同類型的設(shè)備之間都能實(shí)現(xiàn);或者更加具體一點(diǎn),指的是“跨平臺(tái)”,可能是大到跨操作系統(tǒng),比如 Windows、macOS、Linux、iOS 與 Android 等,可能是小到跨某個(gè)具體技術(shù)的不同實(shí)現(xiàn)庫(kù)。
但是今天我們要介紹的是關(guān)于跨 MVVM 架構(gòu)模式各種環(huán)境的場(chǎng)景。
Chameleon?是一套開源跨端解決方案,它的目標(biāo)是讓 MVVM 跨端環(huán)境大一統(tǒng),實(shí)現(xiàn)任意使用 MVVM 架構(gòu)設(shè)計(jì)的終端,都能使用其進(jìn)行開發(fā)并運(yùn)行。
在這樣一個(gè) MVVM 環(huán)境中,涉及到了 Weex、React-Native、WebView/瀏覽器與 Flutter 等各種跨端技術(shù),還有它們實(shí)現(xiàn)的具體業(yè)務(wù)產(chǎn)品,比如微信小程序、快應(yīng)用、支付寶小程序、百度智能小程序、今日頭條小程序與其它各類小程序。
也許你發(fā)現(xiàn)了,這里提到了許多種“小程序”,雖然最早微信小程序的概念甚至早期版本出現(xiàn)的時(shí)候,有過不少不看好的聲音,但是隨著它不斷發(fā)展,目前已經(jīng)成為了大眾生活不可或缺的應(yīng)用形態(tài)。
馬化騰透露過,截至?2018 年 11 月有 150 萬(wàn)微信小程序開發(fā)者,小程序應(yīng)用數(shù)量超過 100 萬(wàn),覆蓋 200 多個(gè)細(xì)分行業(yè),日活用戶達(dá)到 2 億。這樣的成功經(jīng)驗(yàn)與幾乎觸及到生活方方面面的巨大流量入口,大家都想入場(chǎng),于是可以看到后來其它公司紛紛給出了類似的小程序方案。
另一方面,除了小程序百花齊放,2018 年小米、華為、OPPO 等 10 家安卓手機(jī)廠商還結(jié)成了快應(yīng)用聯(lián)盟,并且先后發(fā)布了一系列快應(yīng)用。
Chameleon 目標(biāo)就是要跨這些端,而隨著各家不同實(shí)現(xiàn)越來越多,跨端場(chǎng)景也不斷變得更加復(fù)雜。我們采訪了?Chameleon 創(chuàng)始人張楠,請(qǐng)他為讀者具體分享了 Chameleon 在這個(gè)過程中的成長(zhǎng)。
項(xiàng)目地址:https://github.com/didi/chame...
本文是 Chameleon 首次對(duì)外公開實(shí)現(xiàn)原理!
干貨超多,包括:
終端開發(fā)未來的開發(fā)模式
Chameleon 跨端實(shí)現(xiàn)原理
當(dāng)前各種跨端方案原理對(duì)比(各種小程序、快應(yīng)用等)
與 Taro 的對(duì)比
演進(jìn)過程中遇到的困難與思考
當(dāng)初為什么去研發(fā) Chameleon?關(guān)于這個(gè)問題可以從行業(yè)背景講起。
中國(guó)互聯(lián)網(wǎng)絡(luò)信息中心(CNNIC)發(fā)布的《中國(guó)互聯(lián)網(wǎng)絡(luò)發(fā)展?fàn)顩r統(tǒng)計(jì)報(bào)告》顯示,截至 2018 年 6 月,我國(guó)網(wǎng)民規(guī)模達(dá) 8.02 億人,微信月活 10 億 、支付寶月活 4 億、百度月活 3.3 億;另一方面,2018 Q3 中國(guó) Android 手機(jī)占智能手機(jī)整體的比例超過 80%,月活約 6 億。
BAT 與 Android 成為了中國(guó)互聯(lián)網(wǎng)真正的用戶入口。但凡流量高的入口級(jí)別 APP 都希望做平臺(tái),成為一個(gè)生態(tài)平臺(tái)和互聯(lián)網(wǎng)流量入口,大量第三方應(yīng)用的接入,從業(yè)務(wù)層讓公司 APP 關(guān)聯(lián)上更多企業(yè)的利益,并且擁有更強(qiáng)的生命力;從技術(shù)層面可以利用“本地能力接口層”收集大量用戶數(shù)據(jù),從消費(fèi)互聯(lián)網(wǎng)到產(chǎn)業(yè)互聯(lián)網(wǎng)需要大量各行各業(yè)基礎(chǔ)用戶數(shù)據(jù)線索進(jìn)行驅(qū)動(dòng)和決策。
在這么一種背景下,再結(jié)合計(jì)算機(jī)技術(shù)的發(fā)展歷史,我們知道每一種新技術(shù)的出現(xiàn)都會(huì)經(jīng)歷“各自為政”的階段,小程序技術(shù)也不例外,所以我們看到了其它各種小程序平臺(tái)出現(xiàn)。
微信小程序作為首創(chuàng)者,雖然其它小程序都有在技術(shù)實(shí)現(xiàn)原理、接口設(shè)計(jì)上刻意模仿,但是作為一線開發(fā)者在不同平臺(tái)發(fā)布小程序,往往還是需要重復(fù)開發(fā)、測(cè)試,從前 1 單位的工作量變成了 N 單位的工作量。而這還沒算上快應(yīng)用等其它入口。
這種情況下,滴滴的研發(fā)工程師是其中最顯著的“受害者”之一,滴滴出行在微信錢包、支付寶、Android 快應(yīng)用都有相關(guān)入口,而且用戶流量占比不低。
研發(fā)同學(xué)在端內(nèi)既追求 H5 的靈活性,也要追求性能趨近于原生。面對(duì)入口擴(kuò)張,主端、獨(dú)立端、微信小程序、支付寶小程序、百度小程序、安卓廠商聯(lián)盟快應(yīng)用,單一功能在各平臺(tái)都要重復(fù)實(shí)現(xiàn),開發(fā)和維護(hù)成本成倍增加。
迫切需要一個(gè)只維護(hù)一套代碼就可以構(gòu)建多入口的解決方案,于是我們著手去打造了 Chameleon(CML,卡梅龍)這么一個(gè)項(xiàng)目,真正專注于讓一套代碼運(yùn)行多端。
Chameleon 核心是運(yùn)用了 MVVM 架構(gòu),為什么它可以實(shí)現(xiàn)跨多端?MVVM 也就是 Model View ViewModel,它本質(zhì)上是 MVC( Model View Controller)的進(jìn)化版本,將 View 的狀態(tài)和行為抽象化,使得視圖 UI 和業(yè)務(wù)邏輯分開。
它是一種讓數(shù)據(jù)驅(qū)動(dòng)反射視圖的模式,發(fā)展到現(xiàn)在可能會(huì)偏離它的初衷了,更像是一個(gè)視圖數(shù)據(jù)間的“通信協(xié)議”,讓終端開發(fā)變得更加單純,這是一種趨勢(shì),面向未來框架都采用這種模式。
Facebook 在 2013 年開源 React,React 這個(gè)項(xiàng)目本身是一個(gè) Web UI 引擎,隨著不斷發(fā)展,它衍生出 React Native 項(xiàng)目,用來編寫原生移動(dòng)應(yīng)用。正是它給跨端方向帶來了 MVVM 模式。
Vue.js 于 2014 年左右發(fā)布,逆流而上占據(jù)了大量用戶群體,2016 阿里巴巴也基于它發(fā)布了 Weex 項(xiàng)目,使得可以用 Vue 編寫 Native App。
Google 在 2018 年末正式發(fā)布了面向未來的跨 Android、iOS 端的?Flutter 1.0.0。
原理我們知道終端開發(fā)離不開三大要素——界面表現(xiàn)(結(jié)構(gòu)、外觀)層、邏輯處理層與系統(tǒng)接口層(網(wǎng)絡(luò)、存儲(chǔ)與媒體等)。
開發(fā)者編寫代碼時(shí)在初始化階段(生命周期)調(diào)用“界面表現(xiàn)層”界面模型的接口繪制界面,當(dāng)用戶觸摸界面時(shí),“界面表現(xiàn)層”將事件發(fā)送給用戶“邏輯處理層”,后者經(jīng)過條件判斷再處理并反饋到用戶界面,處理過程可能需要調(diào)用“系統(tǒng)接口層”,反饋過程需要調(diào)用“界面表現(xiàn)層”的接口。
常規(guī)的終端開發(fā)架構(gòu)模式下,無(wú)論是 Web 端、Android 端還是 iOS 端的項(xiàng)目開發(fā),都強(qiáng)依賴各端的環(huán)境接口,特別是依賴界面相關(guān)模型設(shè)計(jì)。
iOS 系統(tǒng)下繪制界面基于 Objective-C 語(yǔ)言環(huán)境下的 UIKit 框架;Android 系統(tǒng)下用戶繪制界面基于 Java 語(yǔ)言環(huán)境,由 LayoutInflater 處理?XML 結(jié)構(gòu)層次樹;Web 端使用 DOM 模型和 CSS 來描述繪制界面。 ?
MVVM 中的關(guān)鍵是它通過 ViewModel 這一層將界面和邏輯層徹底隔離開來,負(fù)責(zé)關(guān)聯(lián)界面表現(xiàn)和邏輯處理層的響應(yīng)事件(update/notify)關(guān)系,這一“隔離層”上下通信足夠規(guī)范、足夠純凈單一。 ?
Model 進(jìn)行邏輯處理是純業(yè)務(wù)響應(yīng)邏輯,任何一種語(yǔ)言都可以實(shí)現(xiàn),你可以用 Android 的 Java,也可以用 iOS 的 Objective-C,你心情好用“世界第一語(yǔ)言 PHP”也能實(shí)現(xiàn)。
之所以普遍選擇 JavaScript,很大程度是因?yàn)樵谶@個(gè)領(lǐng)域內(nèi)它的優(yōu)點(diǎn)顯著,如學(xué)習(xí)成本低、天生具備跨端屬性、虛擬機(jī)(V8、JavaScriptCore)和各方向組件建設(shè)較好、生態(tài)活躍。
而系統(tǒng)接口層則更簡(jiǎn)單了,只需窮舉統(tǒng)一基礎(chǔ)接口+可擴(kuò)展接口能力即可。
各種 MVVM 方案具體來看看各種 MVVM 方案都是怎么樣的。
React Native、Weex 與快應(yīng)用的 MVVM
開發(fā)者編寫的代碼在虛擬機(jī)(V8、JavaScriptCore)里面運(yùn)行,虛擬機(jī)容器里面包含擴(kuò)展的系統(tǒng)基礎(chǔ)接口。運(yùn)行時(shí),將描述界面的數(shù)據(jù)(主要是 CSS+DSL 所描述內(nèi)容)通過通信層傳遞給 Android、iOS 端的渲染引擎,用戶觸摸界面時(shí),通過通信層傳遞給虛擬機(jī)里面的業(yè)務(wù)處理代碼,業(yè)務(wù)處理代碼可能調(diào)用網(wǎng)絡(luò)、儲(chǔ)存與媒體等接口,最后再次反饋到界面。
Flutter 的 MVVM
Flutter 和 RN 的最大區(qū)別在于將“JavascriptCore/V8+JS”替換成“C++ 實(shí)現(xiàn)的 engine+Dart 實(shí)現(xiàn)的 Framework+靜態(tài)類型 Dart+編譯成機(jī)器碼”。
Flutter 的方案如下圖所示:
Service 其實(shí)就是本地能力接口層,Widget 樹是視圖層模型。
Flutter 和 RN 的使用面設(shè)計(jì)上類似,F(xiàn)lutter 文檔中提到“In Flutter, almost everything is a widget.”,widget 的調(diào)用從 RN 的 JSX 變成 Flutter 的 widget 調(diào)用,UI 的外觀描述從 RN 的 CSS(文本樣式、布局模型、盒模型)到定制化 Flutter Widget(textStyle 、Layout?Widget、Widget)。
本質(zhì)上 Flutter 也是 MVVM 架構(gòu),邏輯層通過 setState 通知視圖層更新,一定程度上這也是為什么 Flutter 敢說能轉(zhuǎn)成 Web 框架的原因,核心還是基于這類數(shù)據(jù)驅(qū)動(dòng)視圖架構(gòu)模式,業(yè)務(wù)代碼不會(huì)深度依賴任何一端特有的“視圖模型”。
各類小程序的 MVVM
小程序本質(zhì)上和 Weex、React Native 的設(shè)計(jì)思路基本一樣,最大區(qū)別在于前者還是用瀏覽器 WebView 做渲染引擎,而后者是多帶帶實(shí)現(xiàn)了渲染引擎(所以大量的 CSS 布局模型不支持)。
具體到 Chameleon 上是怎么實(shí)現(xiàn)的?首先任何一份應(yīng)用層的高級(jí)語(yǔ)言代碼塊分成幾層:語(yǔ)言層(Language)、框架層(Framewrok)與庫(kù)層(Library):
Language —— 通俗來說,實(shí)現(xiàn)程序所需的基本邏輯命令:邏輯判斷(if)、循環(huán)(for)與函數(shù)調(diào)用(foo())等。
Framewrok —— 通俗來說,完成一個(gè) App 應(yīng)用交互任務(wù)所需規(guī)范,例如生命周期(onLoad、onShow)、模塊化與數(shù)據(jù)管理等。
Library?—— 可以理解就是“方法封裝集合”。比如 Web 前端中 Vue 更適合叫框架,而 jQuery 更適合叫庫(kù);Android 系統(tǒng)下 activity manager + window Manager? View System 等的集合叫框架,而 SQLite 、libc 更適合叫庫(kù)。
對(duì)應(yīng)到 Chameleon 就是這樣:
具體到實(shí)現(xiàn)原理全景架構(gòu)圖如下:
你可以理解 Chameleon 為了實(shí)現(xiàn)“讓 MVVM 跨端環(huán)境大統(tǒng)一”的目標(biāo)做了以下工作:
定義了標(biāo)準(zhǔn)的 Language(CML DSL)、Framework 與 Library(內(nèi)置組件和 API)協(xié)議層。
在線下編譯時(shí)將 DSL 轉(zhuǎn)譯成各端 DSL,只編譯?Language?層面足夠基礎(chǔ)且穩(wěn)定的代碼。
在各個(gè)端運(yùn)行時(shí)分別實(shí)現(xiàn)了 Framework 統(tǒng)一,在各個(gè)端盡量使用原有框架,方便利用其生態(tài),這樣很多組件可以直接用起來。
在各個(gè)端運(yùn)行時(shí)分別實(shí)現(xiàn)了 Library(內(nèi)置組件和 API)。
為用戶提供多態(tài)協(xié)議,方便擴(kuò)展以上幾方面的內(nèi)容,觸達(dá)底層端特殊屬性,同時(shí)提升可維護(hù)性。
實(shí)現(xiàn)思路很簡(jiǎn)單,所有設(shè)計(jì)為了 MVVM 標(biāo)準(zhǔn)化,不做多余設(shè)計(jì),所以宏觀的角度就像 Node.js(libuv)同時(shí)運(yùn)行在 Windows 和 macOS 系統(tǒng),都提供了一個(gè)跨平臺(tái)抽象層。
從 MVVM 角度來看的話:
View(展現(xiàn)層)
第三方 Render Engine:各類框架已有框架,瀏覽器的 Vue、Webview 里的小程序引擎、Android、iOS 里面的 React Native/Weex 引擎、甚至 Flutter 里面的 Dart Framework。
Chameleon 內(nèi)置組件庫(kù):多態(tài)協(xié)議定義統(tǒng)一組件 view、input、text、block 與 cell 等,它是界面組層的原始基類,衍生出多復(fù)雜界面功能。
ViewModel(關(guān)聯(lián)層)Chameleon 語(yǔ)法轉(zhuǎn)譯
組件調(diào)用
循環(huán)
條件判斷
事件回調(diào)關(guān)聯(lián)
父子關(guān)系
……
Model(邏輯響應(yīng)層)
JavaScript 代碼
CML Runtime 框架
Chameleon API:多態(tài)協(xié)議定義統(tǒng)一接口,cml.request、cml.store 等
Chameleon 的跨多端方案給開發(fā)者的開發(fā)帶來了極大的便利,具體表現(xiàn)是怎么樣的?一句話:基于 Chameleon 開發(fā),效率會(huì)越來越高。
各個(gè)端的涌現(xiàn),讓原本是 1 的工作量因?yàn)槎喽舜嬖诙兂?N 倍,使用 Chameleon,工作量會(huì)變回 1.2。這多出來的 0.2 工作量是要處理各端的差異化功能,比如以下場(chǎng)景:
某業(yè)務(wù)線遷入 Chameleon 時(shí),發(fā)現(xiàn)沒有“passport登錄組件”,在各類小程序里面能免密登錄了,在 Web、Native 端是彈出登錄框登錄,不同業(yè)務(wù)用戶交互形態(tài)不一樣所以 Chameleon 沒有提供組件;開發(fā)者需要基于多態(tài)協(xié)議擴(kuò)展多帶帶一個(gè)登錄組件
用戶需要分享功能,發(fā)現(xiàn)沒有“share組件”,在微信 Web 端可以引導(dǎo)右上角分享,在小程序直接分享,不同業(yè)務(wù)用戶交互形態(tài)不一樣,用戶需要基于多態(tài)協(xié)議擴(kuò)展多帶帶一個(gè)登錄組件
這種各端差異較大的例子,隨著業(yè)務(wù)的積累,可以變成了一個(gè)個(gè)業(yè)務(wù)組件多帶帶維護(hù),后面也不需要重復(fù)開發(fā)了,且反推產(chǎn)品體驗(yàn)一致化,組件三層結(jié)構(gòu)“CML框架內(nèi)置組件->CML擴(kuò)展組件->業(yè)務(wù)開發(fā)者自己擴(kuò)展的多態(tài)組件”達(dá)成 100% 統(tǒng)一。
隨著組件積累業(yè)務(wù)開發(fā)工作量越來少,工程師可以專注做更加有意義的事情,這就是 Chameleon 存在的目的。
基于統(tǒng)一的跨端抽象,用戶在 Chameleon 項(xiàng)目持續(xù)維護(hù)過程中,Chameleon 發(fā)布新增一個(gè)端之后,你的業(yè)務(wù)代碼基本不用改動(dòng)即可無(wú)縫發(fā)布成新端。
比如這個(gè)?cml-yanxuan?項(xiàng)目開發(fā)時(shí)支持 3 個(gè)端,后面新增了百度、支付寶小程序端,原有代碼直接能跑起來運(yùn)行 5 個(gè)端,一端所見即多端所見。
開發(fā)時(shí)只能跑 3 個(gè)端
原有代碼無(wú)縫支持 5 個(gè)端
另外特別強(qiáng)調(diào)的是,對(duì)于大公司團(tuán)隊(duì),如果有很強(qiáng)的技術(shù)能力,希望開發(fā)的代碼掌控在自己手里,對(duì)輸出結(jié)果有更好控制能力。其實(shí) Chameleon 內(nèi)置組件和內(nèi)置 API 是可以替換的,那么所有組件都是業(yè)務(wù)方自己開發(fā)了,哪天不想用了直接導(dǎo)出原生組件即可離開 Chameleon,如下圖:
目前跨多端統(tǒng)一的方案中,Taro 是比較亮眼的,能否具體對(duì)比一下 Chameleon 與 Taro。我們覺得 Chameleon 與其它解決方案的最大區(qū)別在于其它框架都是小程序增強(qiáng),即用 Vue 或者 React 寫小程序,這些框架官方給的已接入例子也都是跑微信小程序。
它們更加類似 Chameleon 的前身 MPV(Mini Program View),即考慮如何增強(qiáng)小程序開發(fā)。2017 年微信小程序發(fā)布時(shí),滴滴作為白名單用戶首先開始嘗試接入,開始面對(duì)重復(fù)開發(fā)的難題。
這時(shí)候我們專門成立了一個(gè)小項(xiàng)目組,完成一個(gè)名為 MPV 的項(xiàng)目,一期目標(biāo)是“不影響用戶發(fā)揮,不依賴框架方的原則性實(shí)現(xiàn)一套代碼運(yùn)行 Web 和微信小程序”。
看著很美好,用這樣的方案實(shí)現(xiàn) Web 端和小程序端,也確實(shí)完成了超過 90% 代碼重用,總體上開發(fā)效率和測(cè)試效率都有了一定提升,但是卻不是真正意義上的跨多端統(tǒng)一。
多帶帶說到 Chameleon 與 Taro 的區(qū)別,總體上看,可以歸為這樣一個(gè)表:
表中每一項(xiàng)都是在做跨端方案時(shí)需要考慮到的。我們說除了 Chameleon,其它方案都只是在對(duì)小程序進(jìn)行增強(qiáng),或者說是模仿微信小程序的 API 和組件的接口設(shè)計(jì)。
Taro 是通過將 JSX 轉(zhuǎn)成小程序模板,在其它端模擬微信小程序的接口和組件,讓其它端更像微信小程序,業(yè)務(wù)開發(fā)時(shí)不一致的地方需要環(huán)境變量判斷差異分別調(diào)用,會(huì)造成端差異邏輯和產(chǎn)品邏輯混合在一起。
此外,它要跟隨小程序更新,業(yè)務(wù)方會(huì)有雙重依賴;其它端的和小程序不能保持一致,用戶要各種差異化兼容,不利于維護(hù)。
那 Chameleon 呢?Chameleon 把這些問題都考慮到了,所以在早期偽跨端 MiniProgram View 成型之后不斷演進(jìn)的過程中,把它發(fā)展成為一個(gè)真正的跨多端方案。
前邊的表格顯示了,Chameleon 既考慮統(tǒng)一性,又考慮差異性,且差異性不會(huì)影響可維護(hù)性;當(dāng)各端差異確實(shí)太大,那就不要用一套代碼實(shí)現(xiàn)多個(gè)端同一頁(yè)面,而是統(tǒng)一公用組件。
這還只是拿 Chameleon 與 Taro 的重合點(diǎn)進(jìn)行了對(duì)比,但是別忘了 Chameleon 不僅僅是前端框架,它:
還有統(tǒng)一的 Chameleon Native ?SDK,Chameleon 不僅僅希望統(tǒng)一各類小程序,還要覆蓋自家 APP,會(huì)持續(xù)通過 Native SDK?擴(kuò)展 API 和組件,期望有與小程序一樣的本地能力。理想情況下,一套代碼就能在各類小程序、自家 APP 里面無(wú)縫平滑運(yùn)行。
還有待開源的后臺(tái)管理系統(tǒng)。
還有待開源的 XEdtior 非研發(fā)用編輯器,可以直接編輯跨端頁(yè)面、直接發(fā)布。
另外,未來還將帶來以下能力:
后端統(tǒng)一接口(消息推送、分享與支付等)
基于統(tǒng)一的 MVVM 標(biāo)準(zhǔn),更有基于 Flutter 的原生 APP
當(dāng)前的各類小程序和 Native 跨端框架,類似當(dāng)年多個(gè)瀏覽器時(shí),Safari、Chrome、Firefox、IE 6/7/8/9、Android 瀏覽器等盛行的時(shí)代。以這個(gè)來類比,那么 Chameleon 的接口組件設(shè)計(jì)上更像一個(gè) jQuery。
網(wǎng)絡(luò)請(qǐng)求有的是 XHRHttprequest 有的是 ActiveXObject,jQuery 考慮的是用戶需要什么,需要一個(gè)網(wǎng)路請(qǐng)求接口,支持 get、post 等,所以 jQuery 寫一個(gè)既非 ActiveXObject 又非 XHRHttprequest 的名為 $.ajax 接口,提供一個(gè)封裝網(wǎng)絡(luò)接口,你不用關(guān)心內(nèi)部在不同端怎么調(diào)用的,jQuery 內(nèi)部會(huì)幫你兼容。
Chameleon 也是一樣的思路,所有的接口設(shè)計(jì)都是真正能兼容跨所有的端,沒有差異性,而且只保留當(dāng)前所在端的接口調(diào)用代碼:IE 里面只保留 ActiveXObject,Chrome 只保留 XHRHttprequest。
Chameleon 的接口設(shè)計(jì)上比 jQuery 更強(qiáng)的地方在于,使用標(biāo)準(zhǔn)的多態(tài)協(xié)議,保障可維護(hù)性,性能上只保留當(dāng)前端代碼,且將多態(tài)協(xié)議暴露出來,讓用戶也能擴(kuò)展自己想要的 API(類比 $.xxx)。
當(dāng)然時(shí)代已經(jīng)變了,監(jiān)聽視圖不在是 $("#xxx").click(fn),而是 MVVM 數(shù)據(jù)驅(qū)動(dòng)視圖方式了,所以提供了 Chameleon 雙向綁定這樣的 VM 層。
前邊講到了 Chameleon 的前身 MPV,那具體分享一下 Chameleon 的整個(gè)演進(jìn)過程吧。 出生期:選擇轉(zhuǎn)譯還是模擬小程序環(huán)境?前面講到,2017 年的時(shí)候,我們完成一個(gè)名為 MPV 的項(xiàng)目,一期目標(biāo)是不影響用戶發(fā)揮,不依賴框架方的原則性實(shí)現(xiàn)一套代碼運(yùn)行 Web 和微信小程序。
當(dāng)時(shí)缺乏小程序資料是遇到的最大問題(就更別提今天講到的業(yè)內(nèi)這么多解決方案了),當(dāng)時(shí)唯一一個(gè)可以參考的開源項(xiàng)目是 WEPT,WEPT 是一個(gè)微信小程序?qū)崟r(shí)開發(fā)環(huán)境,它的目標(biāo)是為小程序開發(fā)提供高效、穩(wěn)定、友好、無(wú)限制的運(yùn)行環(huán)境。它的設(shè)計(jì)思路是在 Web 端模仿小程序環(huán)境執(zhí)行。
于是我們?cè)陂_發(fā) MPV 時(shí)考慮了兩種實(shí)現(xiàn)策略:
1、在 Web 端像 WEPT 一樣 mock 小程序環(huán)境;就像微信開發(fā)者工具里面也模擬了小程序執(zhí)行環(huán)境,WAServie、WAWebview 提供的兩套環(huán)境源碼做底層,在頁(yè)面中開啟三個(gè)獨(dú)立運(yùn)行環(huán)境運(yùn)行并用 iframe 通訊模擬微信小程序的 3 個(gè) Webview 之間的聯(lián)通關(guān)系。
2、逐個(gè)轉(zhuǎn)譯代碼支持小程序,缺點(diǎn)是可能會(huì)有 edge case 需要處理以及潛在的 bug 會(huì)比較多。
最終在看完 WEPT 源碼和微信開發(fā)者工具的情況下,我們明確放棄了第 1 條實(shí)現(xiàn)策略,選擇了逐個(gè)轉(zhuǎn)譯代碼支持小程序的路線,主要原因是于 Web 端兼容微信所有的功能,尺寸過于龐大。
經(jīng)過三個(gè)月緊鑼密鼓的開發(fā)終于實(shí)現(xiàn)了第一版本 MPV: ?
經(jīng)過實(shí)現(xiàn)幾個(gè) demo 之后,開始執(zhí)行遷移計(jì)劃:
?
MPV 在 Webapp 上實(shí)踐最終實(shí)現(xiàn)效果如下:
最終實(shí)現(xiàn)效果挺美好,也確實(shí)完成了超過 90% 的代碼重用,總體上開發(fā)效率和測(cè)試效率都有了明顯提升。
但是在后續(xù)實(shí)踐過程中,發(fā)現(xiàn)存在大量的問題,并且項(xiàng)目越大問題越凸顯出來,總結(jié)如下:
可維護(hù)性問題,沒有隔離公用代碼和各端差異代碼。項(xiàng)目中不止有業(yè)務(wù)邏輯,還混雜著 Web 端和小程序端產(chǎn)品功能差異化邏輯。比如前邊舉過的例子,分享功能 Web 端無(wú)法實(shí)現(xiàn)(引導(dǎo)分享),小程序可以實(shí)現(xiàn),意味著各種環(huán)境判斷各種差異化邏輯,牽一發(fā)動(dòng)全身,還要來回測(cè)試。
方向選擇錯(cuò)誤,MPV 使用了小程序語(yǔ)法標(biāo)準(zhǔn)(小程序的生命周期、API 接口等),導(dǎo)致用戶使用上無(wú)法清晰理解。
不能直接使用各端已有生態(tài)組件,即缺乏標(biāo)準(zhǔn)規(guī)范接入某個(gè)端已有開源組件。比如 Web 端 pick.js 組件缺乏快速接入規(guī)范,用戶要么重新開發(fā),或者在模板和 js 代碼中使用環(huán)境判斷的方式針對(duì)引入。最終導(dǎo)致同一功能不同端的調(diào)用方式、輸入與輸出不一致。
業(yè)務(wù)項(xiàng)目依賴 MPV 框架。框架依賴微信小程序接口(模板、生命周期與接口),擴(kuò)展了統(tǒng)一接口。例如微信小程序更新了 wx.request 時(shí),業(yè)務(wù)項(xiàng)目方無(wú)法立刻使用,需要等框架更新。
文件夾結(jié)構(gòu)混亂,混雜著多個(gè)端代碼文件,且識(shí)別成本高。
不支持 vuex、redux 等高效數(shù)據(jù)管理方式
尺寸單位不統(tǒng)一,px 和 rpx 不一致
周邊小型差異點(diǎn)太多:
協(xié)議不一致,例如 Web 端可以用?//:www.didiglobal.com/passenger/create?,小程序只能用?https://:www.didiglobal.com/passenger/create
打開一個(gè)新頁(yè)面時(shí)鏈接不統(tǒng)一,例如打開發(fā)單頁(yè)時(shí),Web 端是?//:www.didiglobal.com/passenger/create,小程序是 /page/create
頁(yè)面之間跳轉(zhuǎn)時(shí),傳參不統(tǒng)一
debug 成本高,修改完代碼之后兩端需要測(cè)試
兩端界面效果不一致,基礎(chǔ)內(nèi)置組件統(tǒng)一性建設(shè)不足
工程化建設(shè)落后,例如不支持 liveroload、數(shù)據(jù) mock、資源定位、proxy、多端統(tǒng)一預(yù)覽
接口設(shè)計(jì)不完整,生命周期、組件分層、本地 API 設(shè)計(jì)等
模板 DSL 語(yǔ)法不規(guī)范
成長(zhǎng)期:從偽統(tǒng)一到大一統(tǒng)在 MPV 的實(shí)踐積累下,有了一定的底氣和把握,后續(xù)的規(guī)劃更加明確。2018 年 4 月我們把跨端項(xiàng)目規(guī)模進(jìn)一步擴(kuò)大,想要做一個(gè)真正跨 N 端的解決方案,目標(biāo)是提供標(biāo)準(zhǔn)的 MVVM 架構(gòu)開發(fā)模式統(tǒng)一各類終端。這就是 Chameleon 的出現(xiàn)契機(jī)。
Chameleon 真正想要一套代碼運(yùn)行多端,總結(jié)下來要解決幾大問題:
要全面完成端開發(fā)的所有細(xì)節(jié)的統(tǒng)一性,特別是界面統(tǒng)一性有大量細(xì)節(jié)要做
要在完成上一條的前提下考慮差異化定制空間
持續(xù)可維護(hù)
目標(biāo)理想業(yè)務(wù)形態(tài)是這樣的:
圖中上半部分是傳統(tǒng)開發(fā)方式,下半部分 Chameleon 的模式抽象出了 UI 渲染層和本地接口能力層,業(yè)務(wù)代碼一部分簡(jiǎn)單頁(yè)面由 XEditor(h5Editor 的前身)編輯工具產(chǎn)出,另一部分工程師使用 Chameleon 開發(fā),不止解決跨端問題,還彌補(bǔ)改進(jìn)了工程開發(fā)過程中的效率、質(zhì)量、性能與穩(wěn)定性問題,讓工程師專注有意義的業(yè)務(wù),成長(zhǎng)更快。
首個(gè) Native 渲染引擎選擇——小程序架構(gòu)、RN/Weex 架構(gòu)
從 MPV 到 Chameleon,外界看來最明顯的變化是從跨 2 端(Web、小程序)升級(jí)到跨多端(Web、小程序、Android、iOS),最開始糾結(jié)于首個(gè)端上版本的渲染引擎使用小程序架構(gòu)還是 RN/Weex 架構(gòu)。
RN/Weex 網(wǎng)上有大量資料可查,但是小程序方面則不然。千辛萬(wàn)苦搜索之后,根據(jù)一位知道內(nèi)情的朋友的描述分享,才有了一定的了解。
?
這里分享幾個(gè)印象深刻的要點(diǎn):
小程序展現(xiàn)層使用 Webview,里面內(nèi)置了一套 JS 框架用來和 Native 通信,真正業(yè)務(wù)代碼執(zhí)行在多帶帶 JS 虛擬機(jī)容器實(shí)例中
JS 虛擬機(jī)容器使用情況,iOS 系統(tǒng)是 JavaScriptCore,Android 系統(tǒng)使用 QQ 瀏覽器的 X5 內(nèi)核
小程序的各個(gè) TAG 組件使用的數(shù)據(jù)驅(qū)動(dòng)用的是?Web Components
顯而易見,部分性能要求較高的使用原生控件(視頻、鍵盤等等)插入到 Webview 里面。
原生控件的具體位置 Native 怎么獲取?答案是由嵌入到 Webview 的一套小程序框架通知給原生層
原生控件怎么保證在內(nèi)部可滾動(dòng)的元素(Scroll-view)里面正常滾動(dòng)?答案是 CSS 設(shè)置 -webkit-over-scroll:touch 時(shí),iOS 的實(shí)現(xiàn)是原生的 UIScrollView,Native 可以通過一些黑科技找到視圖層級(jí)中的 UIScrollView,然后對(duì)原生控件進(jìn)行插入和處理;而 Android 直接繪制沒辦法做到這點(diǎn)。現(xiàn)在(截至?4 月)僅僅是直接覆蓋到 Webview 最外層的 scrollview 上,由內(nèi)置到 Webview 的一套 JS 框架控制原生控件位置
最終多方面分析如下:
雖然小程序方案看起來很簡(jiǎn)單,但其實(shí)很多細(xì)節(jié)點(diǎn)需要大量打磨,從確認(rèn)方案到真正可以跑起來可以線上發(fā)布,僅僅花費(fèi)在終端上的研發(fā)人力為 20P*6 個(gè)月,微信小程序團(tuán)隊(duì)的目標(biāo)和我們跨端目標(biāo)不一樣,他們投入這么多成本是值得的,我們?yōu)榱丝缍藳]必要投入這么高成本。
所以我們選擇放棄小程序渲染方案,而使用已開源的 RN/Weex 方案。
第一個(gè)版本最終使用 Weex,包括團(tuán)隊(duì)同學(xué)去看了 Weex 源碼實(shí)現(xiàn)。
在整體設(shè)計(jì)上僅僅使用 Weex 渲染功能,外層包裝接口,保障后續(xù)能有更高擴(kuò)展性。
Chameleon Native SDK
針對(duì) Native SDK 我們主要從原生能力擴(kuò)展、性能與穩(wěn)定等三個(gè)方面做了工作。?
原生能力擴(kuò)展:無(wú)論是 Webview 還是 React Native、Weex 甚至 Flutter 都只提供渲染能力(以及一些最基礎(chǔ)本地接口),更多完成業(yè)務(wù)功能所需本地環(huán)境的能力(例如分享到微信)需要 Android 和 iOS 的 Native 往容器去擴(kuò)展。本地能力包含 2 種,涉及 UI 界面的統(tǒng)一叫組件(UI 組件如登錄、支付),涉及到純能力調(diào)用的統(tǒng)一叫 API(網(wǎng)絡(luò)、存儲(chǔ)等)
性能:界面展現(xiàn)和交互耗時(shí)關(guān)鍵取決于 2 塊,資源加載耗時(shí)(非打包到安裝包部分代碼)、執(zhí)行耗時(shí)
穩(wěn)定:主要關(guān)注灰度發(fā)布(風(fēng)險(xiǎn)可控)和線上止損,主要工作是按用戶灰度發(fā)布、可以快速降級(jí)到 H5
以下是性能方向中的首屏加載時(shí)間的優(yōu)化數(shù)據(jù),原有 H5 使用 SSR(Server Side Render)已經(jīng)算是最快的 Web 首屏技術(shù)方案了(不考慮優(yōu)化后端多模塊耗時(shí)的 BIGPIPE),它保持在 1.5 秒以下,在優(yōu)化后降到 0.5 秒左右。 ?
?
性能優(yōu)化中我們有一個(gè)關(guān)于執(zhí)行速度的 TODO 計(jì)劃。同樣是跨端,F(xiàn)lutter 之所以比 Weex 和 RN 執(zhí)行速度快,主要原因是前者是編譯型,客戶端機(jī)器運(yùn)行前已經(jīng)是 CPU 可識(shí)別的機(jī)器碼;后者是解釋型,到客戶端運(yùn)行前是字符串,邊編譯邊執(zhí)行,雖然做了 JIT 盡量?jī)?yōu)化,差距還是較大。其實(shí)在這中間還有一個(gè)抹平了不同 CPU 架構(gòu)下機(jī)器碼差異的中間碼;當(dāng)然前提是開發(fā)語(yǔ)言改成靜態(tài)類型,這里不作展開。
原本分 5 次開發(fā)的 Web 端、支付寶小程序、快應(yīng)用、微信小程序、Native 端變成了 1.2 次左右開發(fā)了。最重要的是隨著業(yè)務(wù)級(jí)別各端差異化的多態(tài)組件和跨端組件積累,后續(xù) 1.2 工作量也會(huì)變成 0.8,0.4 的優(yōu)化主要來自兩個(gè)方面:
0.2 是普通跨端組件的積累,復(fù)用度變高
0.2 是各類業(yè)務(wù)級(jí)別的差異化多態(tài)組件,例如登錄功能,在 Web端、Native 端和小程序端實(shí)現(xiàn)和交互是不一致的,這時(shí)候業(yè)務(wù)形態(tài)不一樣,設(shè)計(jì)的
我們的最終目標(biāo)是提供標(biāo)準(zhǔn)的 MVVM 架構(gòu)開發(fā)模式統(tǒng)一各類終端。
接下來的具體 roadmap 如下表所示:
歡迎有共同愿景的同學(xué)加入我們一起共建,往倉(cāng)庫(kù)貢獻(xiàn)自己的代碼。
項(xiàng)目地址:https://github.com/didi/chame...
QQ 群:
公眾號(hào):
采訪嘉賓介紹張楠,Chameleon 創(chuàng)始人,技術(shù)團(tuán)隊(duì)負(fù)責(zé)人,前百度資深工程師,終身學(xué)習(xí)者。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/102122.html
摘要:開局一張圖,故事全靠編是啥變色龍又是啥自從有小程序以來,小程序的第三方框架便孕育而生,從原始時(shí)代的只基于微信小程序多如今多端統(tǒng)一開發(fā)框架,可以說前端技術(shù)從年到年又發(fā)生了天翻地覆的變化。 Created 2019-4-6 21:57:17 by huqi Updated 2019-4-7 22:54:55 by huqi showImg(https://segmentfault.c...
摘要:跨端框架壹個(gè)理想主義團(tuán)隊(duì)的開源作品歷經(jīng)近個(gè)月打磨,滴滴跨端方案終于開源了真正專注于一套代碼運(yùn)行多端。這時(shí)候我們專門成立了一個(gè)人的小項(xiàng)目組,完成一個(gè)名為的項(xiàng)目,一期目標(biāo)是不影響用戶發(fā)揮,不依賴框架方的原則性實(shí)現(xiàn)一套代碼運(yùn)行和微信小程序。 Chameleon跨端框架——壹個(gè)理想主義團(tuán)隊(duì)的開源作品 歷經(jīng)近20個(gè)月打磨,滴滴跨端方案chameleon終于開源了https://github.co...
摘要:今天,為了讓大家的項(xiàng)目?jī)?yōu)雅升級(jí),快速接入,給你帶來一份豐盛的遷移指南目錄結(jié)構(gòu)和微信小程序一樣,包含一個(gè)描述整體程序的和多個(gè)描述各自頁(yè)面的。 cml 作為真正讓一套代碼運(yùn)行多端的框架,提供標(biāo)準(zhǔn)的MVVM模式,統(tǒng)一開發(fā)各類終端。 同時(shí),擁有各端獨(dú)立的 運(yùn)行時(shí)框架(runtime)、數(shù)據(jù)管理(store)、組件庫(kù)(ui)、接口(api)。 此外,cml在跨端能力加強(qiáng)、能力統(tǒng)一、表現(xiàn)一致等方面...
摘要:基于對(duì)跨端工作的積累,規(guī)范了一套跨端標(biāo)準(zhǔn),稱之為協(xié)議開發(fā)者只需要按照標(biāo)準(zhǔn)擴(kuò)展流程,即可快速擴(kuò)展任意架構(gòu)模式的終端。實(shí)現(xiàn)了微信端的基本擴(kuò)展,用戶可以以此為模板進(jìn)行開發(fā)。新框架太多?學(xué)不動(dòng)啦?有這一套跨端標(biāo)準(zhǔn),今后再也不用學(xué)習(xí)新框架了。各個(gè)小程序按自己喜好各自為政?有了這套標(biāo)準(zhǔn),再也不用重復(fù)開發(fā)各種新平臺(tái)啦。如今前端比較流行的 React Native、Weex、Flutter 等跨平臺(tái)開發(fā)框架...
閱讀 2848·2023-04-25 18:58
閱讀 981·2021-11-25 09:43
閱讀 1215·2021-10-25 09:46
閱讀 3499·2021-09-09 11:40
閱讀 1691·2021-08-05 09:59
閱讀 874·2019-08-29 15:07
閱讀 963·2019-08-29 12:48
閱讀 701·2019-08-29 11:19