滴滴小程序框架Mpx發布2.0,支持小程序跨平臺開發,可直接轉換已有微信小程序

作者:董宏平 (hiyuki)

Mpx是一款致力于提高小程序開發體驗和效率的增強型小程序框架,目前在滴滴公司內部支撐了包括滴滴出行小程序,滴滴出行廣場小程序,青桔單車,黑馬電單車,小桔養車,小桔加油在內的小程序生態;自去年11月開源以來,Mpx也吸納了眾多外部開發者的加入,基于Mpx開發了開走吧,好免街,花憶等小程序。

長期以來,Mpx優秀的開發體驗和強大的穩定性得到了內外開發者的一致認可和好評,這非常符合Mpx的設計初衷。但是在各大廠商陸續推出自己的小程序平臺,且各家的技術標準都不統一的今天,單純地提高某一個平臺的開發體驗已經不能滿足廣大小程序開發者們的訴求,一套代碼在多小程序平臺運行已經成為一個現實上的剛需。為了解決這個小程序開發的痛點,Mpx發布了2.0版本,適配了目前業內已經發布的所有小程序平臺(微信、支付寶、百度、頭條、qq),并且提供了直接將現有微信小程序編譯輸出到其他平臺運行的能力。

Mpx2.0版本新增的主要特性主要包含:

  • 完整支持了目前業內已發布的所有小程序平臺(微信,支付寶,百度,qq,頭條);
  • Mpx小程序跨平臺開發,支持將已有的Mpx微信項目編譯輸出到其他已支持的小程序平臺中運行,點擊查看詳情
  • 小程序原生組件跨平臺編譯,支持將已有的微信原生組件編譯輸出到其他已支持的小程序平臺中運行;
  • 深度分包優化,編譯過程中進行精準分包資源判斷,所有分包only的資源(組件、js、外部樣式、外部模板、wxs,圖像媒體等)都會精確輸出到分包目錄中;
  • render函數中完整支持wxs模塊,關于render函數點擊查看詳情
  • 支持了模板引入,內聯wxs,自定義tabbar,獨立分包,workers,云開發等原生能力,進一步完善原生兼容性。

同業內主流的小程序跨端框架相比,Mpx更專注于小程序開發本身,在小程序開發中具備以下優勢:

  • 基于小程序自身的技術標準進行增強,沒有進行過重的DSL轉換,開發時遇到的坑會更少;
  • 完全兼容原生小程序技術規范,0成本遷移原生小程序項目;
  • 跨平臺開發以跨小程序平臺為目標,大部分差異抹平工作在編譯階段進行,大大減少運行時適配層增加的包體積;
  • 支持業內微信小程序組件庫(如vant、iView等)直接轉換到其他小程序平臺運行;
  • 非常重視小程序性能,提供了深度的setData和包體積優化。

關于Mpx更詳細的介紹可以查看官方文檔這篇文章

Github:https://github.com/didi/mpx

跨平臺開發

作為2.0版本的核心能力,Mpx的跨平臺開發能力允許用戶直接將已有小程序項目編譯輸出到其他已支持的小程序平臺中運行。微信小程序作為小程序概念的提出者,有著最廣泛的生態覆蓋,因此我們優先支持了將微信小程序編譯為其他平臺小程序的能力。基于這個能力,用戶不僅能跨平臺編譯微信Mpx項目,甚至能夠將微信的原生自定義組件也編譯到其他小程序平臺進行運行,這意味著我們的跨平臺項目能夠直接使用一些社區內已有的UI組件庫生態(如vant、iView等),極大地提高了跨平臺開發的適用范圍。

設計理念

Mpx框架的核心設計理念在于增強,增強是指在小程序已有的原生能力基礎上做加法,拓展小程序的開發能力,提高小程序的開發體驗和效率。這個設計理念使Mpx給開發者帶來了更強的確定性和可預期性,更低的學習上手和調試成本。基于這個理念,Mpx在不同的小程序平臺中進行了差異性的增強適配,并參考各個平臺的模板指令風格提供了不同的增強模板指令集,讓用戶在各小程序平臺中都可以以增強的方式去最大限度地使用平臺自有的原生能力。

我們在對Mpx提供跨平臺能力的支持時也遵循了增強的核心設計理念。簡單來講,Mpx的跨平臺能力是在多平臺能力的基礎上,在編譯和運行時增加了一層轉換層,將源平臺的代碼轉換為目標平臺的代碼之后,再按照既有的目標平臺的處理邏輯進行增強,同時我們也提供了一套完善的條件編譯機制,讓用戶自行實現少數框架無法轉換的部分。

Mpx跨平臺開發流程示意圖

Mpx跨平臺開發流程示意圖

Mpx跨平臺能力設計思路明顯區別于業內已有的其他小程序跨平臺框架,主要差異在于:

  • Mpx以小程序本身的DSL作為基準,而沒有使用web框架(React,Vue)的DSL;
  • Mpx主要通過編譯和運行時轉換的方式處理平臺差異,沒有提供額外的差異抹平層(基礎組件庫等)。

之所以采用這種設計,主要基于以下原因:

  • Mpx主要以跨小程序平臺為目標,目前各大小程序平臺的技術規范具有一定相似性,絕大部分平臺差異能夠通過編譯和運行時手段抹平,同時省去的差異抹平層也能夠進一步減少框架運行時體積;
  • 使用小程序本身的DSL作為基準允許用戶直接在已有項目中使用跨平臺能力,對于原生小程序項目或組件也能夠使用該能力進行跨平臺輸出;
  • 結合完善的條件編譯支持,該方案能夠在滿足用戶跨平臺需求的同時仍然允許用戶最大限度地使用各個小程序平臺提供的能力,完全延續了Mpx增強的核心設計理念。

使用方法

Mpx跨平臺開發的使用方式非常簡單,用戶只需在MpxWebpackPlugin創建時傳入mode和srcMode參數指定源平臺和目標平臺,當srcMode和mode不一致時,框架會讀取相應的配置對項目進行編譯和運行時轉換。

// 微信轉支付寶
new MpxWebpackPlugin({
  // mode指定目標平臺,可選值有(wx|ali|swan|qq|tt)
  mode: 'ali',
  // srcMode指定源碼平臺,默認值同目標平臺一致 
  srcMode: 'wx' 
})

差異抹平

目前各大廠商的小程序技術規范在宏觀層面上大致保持一致,但是技術細節方面存在很多差異,大致劃分為以下幾個部分:

  • 模板語法/基礎組件差異
  • json配置差異
  • wxs語法差異
  • 頁面/組件對象差異
  • api調用差異
  • webview bridge差異

其中,對于模板語法/基礎組件、json配置和wxs中的靜態差異,我們主要通過編譯手段進行轉換處理,對于這部分差異中無法轉換的部分會在編譯階段報錯指出;而對于頁面/組件對象、api調用和webview bridge中js運行時的差異,我們主要通過運行時手段進行處理,對應的無法轉換部分也會在運行時中報錯指出。

值得注意的是,我們在跨平臺轉換中做的工作不僅是對可轉換的技術標準進行轉換映射,對于一些目標平臺中不存在的能力,我們也盡可能地通過編譯和運行時手段提供了模擬和支持,最大限度地減少用戶在跨平臺開發中需要付出的額外工作量。以差異性最大但現實場景也最多的微信轉支付寶為例,Mpx模擬提供了許多微信中支持但支付寶中未支持的能力:

  • 組件自定義事件
  • 組件間關系
  • 獲取子組件實例
  • observers/property observer
  • 內聯wxs
  • 外部樣式類

對于原生自定義組件的跨平臺轉換,我們會對其進行簡單的運行時注入,使其能夠使用Mpx框架提供的運行時轉換能力。

條件編譯

對于框架無法抹平的差異部分,會在編譯和運行時報錯指出,對于這部分錯誤,我們提供了完善的條件編譯機制讓用戶能夠自行編寫目標平臺的patch進行修復,該能力也能用于實現具有平臺差異性的業務邏輯。

上文中提到Mpx通過讀取用戶傳入的mode和srcMode來決定是否以及如何對項目進行轉換,mode和srcMode分別代表整個項目構建的目標平臺和源平臺,條件編譯能夠讓用戶在項目中創建聲明了自身平臺屬性(localSrcMode)的文件和代碼塊。在項目構建中,框架會優先加載帶有localSrcMode聲明且localSrcMode與項目目標平臺匹配(localSrcMode===mode)的文件和代碼塊,這部分文件和代碼塊需要完全依照自身聲明的平臺標準進行編寫,Mpx不會對其進行任何編譯和運行時的跨平臺轉換。

Mpx提供了三種維度的條件編譯,分別是文件維度,區塊維度和代碼維度,用戶可以根據平臺差異的覆蓋范圍靈活選擇使用。

性能優化

Mpx框架專注于小程序開發,在性能優化方面我們做過很多嘗試和努力,主要集中在兩個方面:

  • 運行時的setData優化
  • 編譯構建時的包體積優化

setData優化

數據響應是Mpx運行時增強的核心能力,該能力讓用戶在小程序開發中能夠像Vue中一樣使用watch和computed特性,并且用直接賦值的方式操作數據驅動視圖更新,而不需要手動調用setData方法,換言之框架接管了小程序中的setData調用。

通過各大小程序平臺的設計原理和性能優化建議可以得知,setData對于小程序的性能表現非常重要,而setData優化的兩大方向在于:

  • 盡可能減少setData調用的頻次
  • 盡可能減少單次setData傳輸的數據

為了實現setData的優化,我們在模板編譯過程中對于每個組件的模板都生成了一個渲染函數(render function),該函數模擬模板的渲染邏輯,在每次執行時訪問當次渲染所需的數據,并將當次訪問過的數據路徑記錄下來作為函數返回值返回。

在運行時,框架會在每個組件創建時創建一個render watcher,該watcher追蹤渲染函數,當渲染依賴數據發生變更時異步執行渲染函數,在render watcher回調中得到渲染函數返回的數據路徑,基于這些路徑與上一次的緩存數據進行diff比對,過濾掉未發生變化的數據后得到最小必要數據,最后調用setData將最小必要數據發送到真實的小程序渲染層更新視圖。

基于這個機制,當數據發生變更時,只有當前渲染依賴的那部分數據發生變更才會異步地觸發render watcher的執行,而每次執行后也只有實際發生變更的那部分數據會被setData發送到渲染層。這樣用戶就能自由地根據業務需求來操作數據,無需關注setData的調用優化,框架能夠自動進行程序上最優的setData調用,在提升用戶開發體驗的同時也提升了程序性能。

在1.x版本中,渲染函數內無法執行wxs的邏輯,對于含有wxs的組件有可能降級到全量設置數據的模式,在2.0版本中,我們將wxs模塊轉譯處理為js可執行的代碼后注入到js bundle中,含有wxs的渲染函數也能夠正常訪問并執行wxs邏輯。

setData優化示意圖

setData優化示意圖

包體積優化

類似于運行時對于setData的接管,Mpx在編譯階段接管了項目的資源管理。得益于webpack強大的插件機制,Mpx開發了一個深度定制的webpack插件,基于webpack完成小程序的打包構建工作。用戶在使用Mpx開發小程序時可以不受限制地使用npm依賴、最新的es特性和css預處理器等現代web開發能力。與此同時,Mpx在包體積優化上也做了很多工作,讓用戶專注于業務開發而無需花費過多精力進行包體積管理,我們所做的優化工作如下:

  • 打包構建工作完全基于依賴分析,任何沒有被引用的資源都不會出現在dist當中;
  • 對于npm組件和頁面的構建也完全基于依賴分析按需打包,不會copy整個miniprogram_dist目錄,也不需要執行構建npm,使用體驗和包體積均優于微信小程序自身的npm支持方案;
  • 基于webpack提供的能力進行公共模塊抽取和代碼壓縮等優化工作;
  • 完善的分包支持,對所有資源進行從屬分析,將所有分包only的資源都輸出到分包目錄中。

分包作為微信小程序中優化包體積的核心手段(類似于異步按需加載),Mpx對其進行了完善的支持。為了精確地標記出分包only的資源,我們在構建時將主包和分包的依賴收集步驟拆分開來串行處理,先處理主包,再處理分包。在主包的處理過程中,將主包頁面中引用的所有非js資源(組件、外部樣式、外部模板、wxs,圖像媒體等)都記錄下來,在處理分包時,對分包內引用的非js資源都進行檢查,如果被主包引用過則輸出到主包中,否則標記為分包only的資源輸出到分包目錄下。

對于js模塊資源,我們在腳手架中生成的構建配置中提供了輔助函數,便于用戶進行分包bundle的配置,經過該配置后,分包only的公用模塊會被打入分包bundle輸出到分包目錄下,其余的公共模塊會正常打入主bundle中。

在跨平臺開發中,我們建議用戶使用Mpx提供的packages來定義分包,這樣在轉換到不支持分包的小程序平臺時會自動降級為同步包進行處理。

分包構建示意圖

分包構建示意圖

漸進遷移

Mpx提供了良好的漸進遷移支持,對于使用原生或其他小程序框架的開發者來說,采用漸進遷移的方式逐步引入Mpx進行開發成本并不大。

在2.0版本中我們進一步完善了Mpx的原生兼容性,跟進支持了各個小程序平臺最新的技術能力,如自定義tabbar,獨立分包,分包預加載,workers,云開發等能力,同時補齊了一些1.x版本遺漏的支持。得益于此,對于使用原生小程序開發的開發者來說,遷移Mpx的成本幾乎為0,用戶只需將對應頁面組件的構造函數替換為Mpx提供的createPage/createCompnent,即可使用Mpx提供的各種增強能力。

對于使用其他框架的開發者,Mpx也提供了局部構建的機制,允許用戶將特定的頁面和組件單獨構建輸出為原生組件,用戶只需手動或者編寫腳本輸出的原生組件整合進原有項目中即可。

未來規劃

作為滴滴公司內部小程序生態的基礎設施,我們會對Mpx框架進行長期的維護更新,確保能在第一時間支持各個小程序平臺最新的技術特性。與此同時,我們也會進一步完善框架的基礎能力,目前已排上日程待支持能力包括:

  • i18n
  • ts支持
  • 單元測試支持

在跨平臺能力方面,我們也會根據社區的反饋和建議,以及小程序的標準化進程,對其進行持續的完善與更新。

最后,如果你專注小程序開發,關注開發體驗和產品性能,那Mpx會是你最好的選擇。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 因新工作主要負責微信小程序這一塊,最近的重心就移到這一塊,該博客是對微信小程序整體的整理歸納以及標明一些細節點,初...
    majun00閱讀 7,392評論 0 9
  • 1.小程序起步 (1)點擊https://mp.weixin.qq.com/wxopen/waregister?a...
    GXW_Lyon閱讀 3,414評論 0 0
  • 一.微信小程序是啥 本質其實就是(混合)的app 介于web app與native 原生app之間,具備豐富的調用...
    極樂叔閱讀 3,113評論 1 4
  • 第一次書寫即感到熟悉又感到陌生,將有十年沒有提筆,心中的竊喜真是無法描述。
    Zxy_8ae3閱讀 180評論 0 1
  • “我想清楚了 你還是別靠近了 我怕我是曇花一現 更怕你是走馬觀花 我怕用最好的一面 來留住你一眼 而你一眼 卻耽誤...
    聽聞蔣亦涵閱讀 107評論 0 1