快應用宣佈支援第三方DSL

快應用研發中心發表於2019-04-10

1. 背景介紹

大家好,這裡是快應用聯盟的前端研發團隊;
自去年3月,快應用聯盟成立之後,已經有很多開發者使用快應用的標準DSL(以ux檔案字尾的專案形式)上線了對應產品。
以“旅遊出行”的品類為例,就有:攜程、去哪兒、高鐵管家等;
快應用宣佈支援第三方DSL

關於更多的快應用產品與體驗,讀者可以在Android手機的應用商店 -> 分類 -> 快應用 欄目中檢視;
今天呢,研發團隊帶來一個好訊息,就是:快應用開放平臺介面,可以支援第三方的DSL啦!
接下來分享主題:以流行的vue框架為例,讓快應用支援第三方DSL的開發能力;
那麼為什麼做這個事呢?主要還是為了滿足前端同學的開發習慣,提升開發者的體驗與效率。所以藉助這種契機與介面開放的能力,快應用可以支援其他更多的DSL。

1.1過往回溯

自從微信小程式從16年10月內測以來,前端開發在端適配上迎來了巨大的變化;開發者寫的程式碼,不僅要滿足WEB平臺、原生渲染平臺(RN開發),而且還要增加對小程式的支援;
18年3月成立了國內手機廠商成立了快應用聯盟,隨後又湧現了百度/阿里/頭條等多個小程式生態,給開發者提出了更高要求,從"面向模組的開發"到"面向多端適配";
可喜的是:在這種背景下,前端圈子裡逐漸衍生出新的框架,就是希望能夠提供統一的DSL,讓開發者編寫一套程式碼,完成多端自適應的執行效果;
面對市場上眾多的框架,新手開發者如何粗略瞭解與選擇呢?

1.2當前現狀

從歷史發展與職責目標的角度看,當前市場上的DSL框架可以分為以下4類:
快應用宣佈支援第三方DSL
1) WEB型:
比如:React、Vue、Angular等輕量級的資料驅動框架;
簡述:主要用於瀏覽器的頁面開發,因為語法簡單、容易上手、除錯方便而備受開發者的喜歡;
發展:因為擁有廣泛的使用者基礎,逐漸發展多個子方向,如:UI元件庫方向(如:Ant Design、ElementUI),簡化版方向(移動端效能好,擴充套件更多能力);
職責:提供開發者鍾愛的語法,解決前端專案中元件化、分層架構、工程組織、資料流等問題,讓開發者以最優雅的方式管理專案;


2) 平臺型
比如:Weex初期的we檔案語法,微信小程式的wxml語法,快應用提供的ux檔案、百度智慧小程式的swan檔案、Flutter的dart;
簡述:主流的大網際網路公司都會推出自有的渲染平臺,從而為滿足初期自身平臺的渲染而提供一套自己實現的前端框架;
發展:每個平臺擁有獨特的語法,讓開發者水土不服,針對該平臺重新開發一套產品程式碼,學習成本較大;
職責:這類前端框架的存在主要是為了滿足初版與迭代,更多服務於平臺的系統能力提供,研發方向著重於技術深度的底層渲染(繪製、合成);對於前端框架而言,僅滿足開發需求,期望培養開發者習慣,並引領開發潮流較難,除非這類DSL可以同時生成到移動端等的適配;


3) 適配型
比如:Weex上支援Vue語法,微信小程式中使用Wepy和mpvue,以及本次介紹的快應用平臺上引入Vue開發方式;
簡述:介於諸多開發者對於上述平臺型DSL不適應,從而引入前端受歡迎的WEB型DSL;
發展:這裡的發展思路差異比較大,有的是平臺自身開發支援的,有的是通過DSL愛好者移植適配完成的,經歷二次編譯(WEB型DSL先轉成平臺型DSL,然後平臺型DSL再轉換成可以直接執行的平臺編譯程式碼);
二次編譯的優勢在於:它不需要了解平臺內部是如何實現的,僅需要根據官方提供的DSL能力進行能力適配即可;缺點在於:比較依賴平臺型DSL能力,如果不支援某個特性則適配困難,或者容易造成效能瓶頸;
如果是平臺自身支援的,那麼開發者程式碼,直接就可以完成對UI的操作,跳過官方標準DSL的模型,減少中間呼叫,完成加速渲染;這種方式的難點在於:平臺自身需要提供穩定的UI操作介面,做到向後相容;
毫無疑問,平臺自身的支援,能夠比二次轉換,帶來更好的效果;
職責:儘管各自思路不同,但是目標一致,完成開發者從WEB到具體平臺的順利過渡;


4) 全能型
比如:滴滴的chameleon、去哪兒的nanachi、京東的taro等;
簡述:該型別從上面的適配型開始萌芽,圍繞如何解決多端適配問題,但這僅僅只是表象問題;對於後續壯大發展,需要思考面更廣,對抽象概念理解更深刻,如: APP容器管理,渲染設計,系統功能呼叫,動態載入等概念;
發展:儘量抹平WEB、原生、快應用、小程式等渲染的差異,抽象應用模型,完成頁面渲染設計,最後適配到各平臺;當然適配時如果能夠直接完成對平臺API的操作,要比二次轉換效果要好的多;
職責:完成較全面的多端適配,達到一套程式碼多端適配的目標;

那麼本文講述的快應用引入Vue DSL,屬於上述的適配型,讓平臺自身支援,同時開發平臺介面,為往後出現的全能高效型框架服務;

1.3 近期趨勢

在作者看來,新的19年,全能型框架會逐漸取代適配型,並且從規範、架構、設計等角度上,提出新的理念與原則;基於此,各平臺通過自身或者開源愛好者完成適配轉換;
當然,各平臺負責方(快應用、小程式)也會加深對統一的認識,藉助於W3C研討會、興趣組、前端會議,促教交流,考慮抽象出自己的渲染API與能力通道,讓更友好的全能型框架完成高效適配,這塊敬請期待吧;
中間也必定會產生一些相容性類庫,完成polyfill的輔助角色;
所以基於這種趨勢,快應用採用了這樣的路線:開放頁面渲染介面,輕鬆支援第三方的DSL;

2. 實現方案

那麼快應用本次支援Vue的DSL能力,都做了哪些事情呢?
接下來我們從渲染流程、架構設計、開發體驗、專案程式碼、載入過程、平臺解耦、測試保證的多個角度闡述。

2.1渲染流程

要想完成適配,首先需要對比兩方平臺的頁面渲染過程是否相似;經過抽象彙總,得出主體過程都是這樣的:
快應用宣佈支援第三方DSL
步驟1. 工程化工具編譯開發者使用某種DSL而編寫的業務程式碼;
步驟2. JS引擎執行時載入完DSL框架後,執行開發者的業務程式碼;
步驟3. 基於DSL的核心邏輯,生成MVVM的模型;
步驟4. 業務中對資料的操作,觸發對DOM節點的更新;
步驟5. DOM更新後渲染引擎,發出VSync申請,標記髒值節點;
步驟6. 遍歷待更新節點,依次樣式佈局計算、繪製合成,完成渲染;
當前兩者實現的區別主要在於:執行緒的工作分配與協調機制、渲染實現的具體邏輯;然而這些對於DSL框架而言,是不需要關注深度實現的;
同時快應用自身會構建一套頁面UI的DOM樹,因此抽象出了一套DOM的API提供給DSL;DSL只需要呼叫快應用提供的節點操作介面,即可輕易完成適配;
為了方便理解,我們在Github上增加了Vue版本的TodoMVC的示例專案quickappcn/todomvc-vue
實際效果可以訪問下面地址:github.com/quickappcn/…
快應用宣佈支援第三方DSL
既然流程一致,那接下來就看如何架構設計,分層組織了。

2.2架構設計

以當前支援Vue的適配為例,主要工作在於:編譯時、執行時兩方面;
  • 編譯時
提供針對DSL的專案模板化、DSL的解析編譯能力,期間可以使用快應用元件與樣式的校驗解析介面;
當前快應用專案的開發,使用的是官方hap-toolkit工具,這是一個基於NodeJS的npm庫;
關於專案的構建打包、除錯等非DSL專有能力的,均已模組獨立;專案結構採用模組化的開發方式,藉助於lerna完成耦合分離;
DSL開發者只需要開發對應的DSL模組,增加模板化、語法解析,即可完成適配。
  • 執行時
負責執行開發者的業務程式碼,管理DSL中的驅動模型,完成資料更新到DOM操作的轉換;
快應用平臺執行時會提供DOM的API,針對每個頁面提供一個document節點;
DSL層除了包含官方Vue的原始碼邏輯之外,還有兩部分:
  • DOM API呼叫:完成對節點的操作;
  • 容器適配模組:提供針對應用/頁面概念的適配;
針對這塊,快應用在Github提供了以下幾個專案:
從官方Vue站點克隆而來,儲存Vue核心原始碼、以及針對快應用DOM API的適配;
負責DSL在快應用平臺上的應用容器適配,如:生命週期、事件通知等;
有了編譯時/執行時的核心支援,其它工作(如:IDE支援)就是相對較小的任務拆解了。

2.3開發體驗

對於使用DSL Vue的快應用開發者來說,會不會與標準DSL(標準DSL:ux作為字尾名)開發方式,差別很大呢?
其實開發過程,與快應用標準的DSL專案開發方式基本完全一致,標準DSL的專案中展示的ux檔案,DSL Vue中展示的是vue檔案;
使用方式如下:
步驟1:全域性安裝npm庫:npm install -g hap-toolkit
步驟2:初始化專案:hap init --vue
步驟3:構建專案:npm run build
步驟4:執行在快應用的APK平臺,開發者可以選擇“本地安裝“或者” 線上更新“的方式,與標準開發方式一致。

2.4專案程式碼

總結一下,本次快應用為引入Vue DSL而提供的專案:
展示在快應用平臺上執行該DSL專案的實際開發示例;
專案使用了元件化的開發方式,完成展示與表單的頁面互動,檔案組織結構如下圖所示:

快應用宣佈支援第三方DSL

熟悉快應用開發的讀者,會發現與標準DSL一樣,這樣方便快速上手。
從官方Vue站點克隆而來,提供針對快應用DOM API的適配;
專案中新建了一個quickapp-initial的分支,放置適配程式碼;
提供了DSL在平臺上的應用容器適配,如:生命週期、事件通知等;同時包含針對上一個核心DSL原始碼專案的構建後程式碼;
為了輔助開發,開發者可以補充測試用例,完成單元測試、專案測試的功能保證;
其中的單元測試:測試Vue的自身功能表現正常;
其中的專案測試:測試Vue在基於NodeJS的快應用模擬平臺上,是否表現正常;
提供對開發者寫的DSL的模板化、語法校驗、專案打包等功能;
採用lerna模組化改造後,目前劃分的模組的依賴關係如下圖所示:

快應用宣佈支援第三方DSL

對於DSL開發者來說,只需要關注:hap-dsl-vue的模組即可,這塊的程式碼以原始碼的形式儲存;其中的templates資料夾存放專案模板,src資料夾存放相關的編譯解析能力;
對於其他的部分模組,比如:hap-compiler,hap-server屬於所有的DSL共用模組,開發者一般無需更新;同時部分模組並未僅提供了編譯後程式碼,如需開放原始碼,開發者可以下來聯絡;
為了保證穩定性,也可以增加測試用例(當前使用的是Jest),完成單元測試與專案測試的編譯功能確認。
hap-toolkit@0.3.0版本上增加了對Vue DSL的支援,不過並未採用lerna管理,後續釋出的0.4版本以後會用這種方式;
注意:由於新業務功能的開發,當前模組化組織結構可能還會繼續調整。

2.5載入過程

在快應用完成編譯時/執行時的開發後,DSL是如何載入並呼叫渲染的呢?大家看下下面的圖例就明白了;

快應用宣佈支援第三方DSL

快應用的執行可以分為三個階段:
第一階段:環境準備
底層平臺啟動,暴露DOM等相關API,載入DSL程式碼,並完成與平臺的橋接通訊;
第二階段:業務程式碼執行
載入並執行開發者專案中的vue業務程式碼(編譯後轉換為JS),建立驅動模型,完成VDOM的對比;
第三階段:平臺渲染
上一層VDOM對比的結果,轉換成對平臺的DOM API的實際呼叫,平臺執行緒然後做佈局計算、繪製等完成介面的展示;
上圖所示,可以得出:DSL與平臺的解耦與互動發生在第一階段的最後一步,即:平臺介面暴露之後,業務程式碼執行之前;因此整個執行,DSL框架僅會載入一次。

2.6平臺解耦

那麼DSL與平臺需要考慮哪些方面的解耦事項呢?主要分為三個部分:
1) 容器管理
快應用是一個應用形態,包含多個頁面,這點不同於瀏覽器,所以就會存在應用/頁面的生命週期;
開發者需要監聽這些生命週期,用於完成:資料請求、統計、效能監控;
為了保持解耦合,平臺使用了Publish/Subscribe模型,DSL只需要訂閱相關的事件,即可暴露給開發者;
開發者可以從專案quickappcn/quickapp-dsl-vue的src/shared資料夾 中得到提示;
2) 頁面渲染
對於每個頁面來說,頁面的渲染依賴於元件樹的構建,為了方便對元件進行操作,平臺提供了一套類似瀏覽器的元件操作介面,稱為:平臺DOM API;
為了提升DSL適配的簡易性,快應用的DOM與瀏覽器中的DOM非常相似;
比如:建立節點的API(document.createElement())、節點增刪的API(element.appendChild()、element.insertBefore())
在Vue DSL中,開發者都會使用哪些介面進行節點操作呢?
可以從專案quicappcn/vue的src/platforms/quickapp/node-ops.js檔案中得到提示;
3) 介面功能
業務開發中,開發者肯定需要呼叫系統功能,如:fetch請求:require('@sysem.fetch')、地理位置:require('@system.geolocation')
這方面的語法與平臺的標準DSL語法保持一致,會在編譯時進行轉換,如:fetch請求轉換為:$app_require$("@app-module/system.fetch")$;
平臺執行開發者的JS程式碼時,會自動注入一個全域性函式$app_require$;那麼JS執行時就會通過該函式完成系統功能的獲取;
所以關於這塊,DSL適配不會有實際工作量;可以專案quickappcn/quickapp-dsl-vue的src/dsls/vue/page/interface.js檔案中得到提示;

2.7 測試保證

對於DSL開發者來說,通過測試用例保證功能穩定是必不可缺的;
針對編譯時,測試相對簡單,檢視專案quickapp/hap-toolkit即可讀懂;
針對執行時,如果每次對原始碼修改後,都需要在手機裝置上測試執行,確認功能的話,將會很浪費時間;
為了解決這一難題,快應用平臺的前端層面,提供了在NodeJS環境上的平臺模擬能力;因此開發者可以通過兩方面的測試用例來保證穩定:
  • 單元測試
完成對DSL的基本功能進行測試,如:指令、filter、資料驅動等各種DSL自身特性;
相關程式碼請參考:專案quickappcn/quickapp-dsl-vue的 test/suite/dsls/vue/unit資料夾;
測試命令請參考:專案quickappcn/quickapp-dsl-vue的package.json中的"test:suite:framework:main:vue:unit"命令;
  • 專案測試
開發者像開發正式的快應用專案一樣,編寫DSL頁面;模擬平臺會將測試專案編譯打包,然後逐個執行開發者的頁面程式碼;
開發者可以在這裡,測試DOM樹的結構一致性、生命週期、介面功能等;
相關程式碼請參考:專案quickappcn/quickapp-dsl-vue的test/suite/dsls/vue/project資料夾;
測試命令請參考:專案quickappcn/quickapp-dsl-vue的package.json中的"test:suite:framework:main"命令;

3. 合作交流

如果您是快應用的開發者,或者其他角色,對於前端開發生態感興趣,歡迎提出各類建議,或合作意向。
快應用平臺對DSL能力的支援,前端與底層研發團隊做了很多耦合分離工作,開源工作得以推進;同時感謝聯盟內各家廠商研發的鼎力支援,大家合作共同管理專案原始碼與規範制定。

3.1使用DSL開發

如果您也是Vue框架深度愛好者的話,可以考慮使用Vue來做快應用產品的開發;
圍繞Vue DSL的最新能力與執行體驗,我們將會在專案quickappcn/quickapp-dsl-vue中保持更新,您可以向這裡提交issue反饋需求;
快應用的Vue DSL會在1050版本邀請內測,待功能穩定後,平臺將內建正式版本的Vue DSL;
注意:由於當前內測期間,Vue DSL暫不支援華為裝置,聯盟內所有剩餘廠商均可以無縫支援;

3.2其它DSL接入

如果您是某個DSL(如:React)的愛好者,或者某個全能型框架的設計者,有意向接入到快應用平臺中,讓更多的開發者受益,歡迎洽談垂詢;
您可以通過聯盟的任何成員/各種渠道聯絡前端團隊,或者向我們傳送郵件:dongyongqing#xiaomi.com
謝謝!

3.3簡歷推薦

如果您對快應用的研發工作感興趣,有意提升對平臺的架構/設計能力,或者能夠跨越瀏覽器的限制提出更多的規範思路,歡迎聯絡我們;

相關文章