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

做者:董宏平 (hiyuki)css

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

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

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

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

同業內主流的小程序跨端框架相比,Mpx更專一於小程序開發自己,在小程序開發中具有如下優點:github

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

關於Mpx更詳細的介紹能夠查看官方文檔這篇文章web

Github:github.com/didi/mpxnpm

跨平臺開發

做爲2.0版本的核心能力,Mpx的跨平臺開發能力容許用戶直接將已有小程序項目編譯輸出到其餘已支持的小程序平臺中運行。微信小程序做爲小程序概念的提出者,有着最普遍的生態覆蓋,所以咱們優先支持了將微信小程序編譯爲其餘平臺小程序的能力。基於這個能力,用戶不只能跨平臺編譯微信Mpx項目,甚至可以將微信的原生自定義組件也編譯到其餘小程序平臺進行運行,這意味着咱們的跨平臺項目可以直接使用一些社區內已有的UI組件庫生態(如vant、iView等),極大地提升了跨平臺開發的適用範圍。json

設計理念

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會是你最好的選擇。

相關文章
相關標籤/搜索