作者:馬倩
轉(zhuǎn)發(fā)鏈接:
https://mp.weixin.qq.com/s/LlZB6ZC5NkxnBj-C5iZNnA
Kbone原理解析
官方介紹
“Kbone 是一個致力于微信小程序和 Web 端同構(gòu)的解決方案。”
Web端框架基本原理
首先我們來看下普通Web端框架,以Vue框架為例,一份Vue模板對應(yīng)一個組件,在代碼構(gòu)建階段編譯成調(diào)用Dom接口的JS函數(shù),執(zhí)行此JS函數(shù)就會創(chuàng)建出組件對應(yīng)的Dom樹,從而渲染到瀏覽器頁面上。
然而,小程序是雙線程的,并沒有Dom樹的概念,邏輯層和視圖層完全分離,邏輯層是一個純粹的JSCore,開發(fā)者可以編寫JS腳本,但是無法直接調(diào)用Dom/Bom的api, 沒有任何瀏覽器相關(guān)的實現(xiàn)。
在小程序中,視圖層和邏輯層的交互是通過數(shù)據(jù)和時間驅(qū)動的。
因此,要實現(xiàn)跨端同構(gòu),問題是:怎么將web端代碼轉(zhuǎn)為小程序代碼?
業(yè)界常規(guī)做法
目前業(yè)界流行的第三方跨端框架們,常規(guī)做法都是:靜態(tài)編譯兼容。
原理是把代碼語法分析一遍,然后將其中的模板部分翻譯成對應(yīng)的跨端需求的模板(微信小程序、支付寶小程序、H5、App等)。
靜態(tài)編譯最大的局限性是無法保證轉(zhuǎn)換的完整性,因為Vue模板和WXML模板的語法并不是直接對等的,Vue的特性設(shè)計也和小程序的設(shè)計無法劃等號,這自然就導(dǎo)致了部分Vue特性的丟失。
比如像Vue中的v-html指令、ref獲取Dom節(jié)點、過濾器等就通通用不了。
除了Vue自身的特性外,一些原本依賴Dom/Bom接口的Vue插件也無法使用,例如Vue-Router。
Kbone的做法
Kbone是通過提供 適配器 的方式來實現(xiàn)同構(gòu),即運行時兼容,而非靜態(tài)編譯。
Kbone的適配器核心包含兩個部分:
miniprogram-render:仿造Dom/Bom接口,構(gòu)造仿造Dom樹;
miniprogram-element: 監(jiān)聽仿造Dom樹變化,渲染到頁面,同時監(jiān)聽用戶行為,觸發(fā)事件。
仿造Dom樹和瀏覽器的運行時對比:
仿造Dom樹:
利用內(nèi)置組件和自定義組件的自引用來進行遞歸,創(chuàng)建組件樹。
如圖,自定義custom-dom為遞歸自引用組件:
遞歸的終止條件是遇到特定節(jié)點、文本節(jié)點或者children空節(jié)點。
在創(chuàng)建出組件樹后,將Dom節(jié)點和自定義組件實例進行綁定,以便后續(xù)的Dom更新和操作。
kbone這里還對節(jié)點數(shù)進行了優(yōu)化:
如果一個dom節(jié)點對應(yīng)一個自定義組件的話,就會創(chuàng)建很多自定義組件,這樣會很浪費開銷,這里做了子樹的合并,也就是說3層才創(chuàng)建一個自定義組件,節(jié)省開銷。
優(yōu)化前:17個dom=17個自定義組件;優(yōu)化后:17個dom=4個自定義組件,藍色那個是單節(jié)點,會合并到上面的樹;
dom 子數(shù)作為自定義組件渲染的層級數(shù)是可以通過配置傳入,理論上層級越多,使用自定義組件數(shù)量越少,性能也就越好。
一顆很大的 Dom 樹,一次性 setData 到視圖層,可能會超過 setData 的大小限制(1024kB),拆分成多顆子 Dom 樹,然后分批的 setData 到視圖層,可以節(jié)省開銷。
事件監(jiān)聽
小程序的事件是視圖層到邏輯層的通訊方式,事件綁定在組件上,當(dāng)被觸發(fā)時,就會執(zhí)行邏輯層中對應(yīng)的事件處理函數(shù)。
小程序的捕獲冒泡是在視圖層view端,因此邏輯層在整個捕獲冒泡流程中各個節(jié)點接收到的事件不是同一個對象,小程序事件的捕獲冒泡和阻止冒泡等操作必須在WXML模板中聲明,無法使用接口實現(xiàn)。
為了能夠讓web端和小程序端的事件系統(tǒng)行為一致,kbone除了仿造了一份Dom樹外,也把整個事件系統(tǒng)仿造了一份,即在仿造Dom樹上進行捕獲冒泡。
當(dāng)自定義組件監(jiān)聽到用戶的操作后,就將事件發(fā)往仿造Dom樹,后續(xù)自定義組件監(jiān)聽到的同一個事件的冒泡就直接忽略。
當(dāng)觸發(fā)該節(jié)點,仿造Dom樹接收到事件后,再進行捕獲和冒泡,讓事件在各個節(jié)點觸發(fā)。
Kbone的優(yōu)勢
- 支持多個前端框架:Vue、React、Preact 等
- 支持更為完整的前端框架特性:Vue 中的 v-html 指令、Vue-router 插件等
- 提供了常用的 dom/bom 接口
- 可以使用小程序本身的特性:live-player 內(nèi)置組件、分包功能等
- 提供一些 Dom 擴展接口:getComputedStyle 接口等
Kbone實踐
腳手架kbone-cli
官方已經(jīng)提供了kbone-cli可以用來快速開發(fā):
用npm全局安裝kbone-cli
可以根據(jù)自己的技術(shù)棧選擇不同的開發(fā)模板:React/Vue/Omi/Preact
然后就可以愉快的進行開發(fā)啦~
生成的demo項目結(jié)構(gòu)如下:
demo中包含了多頁跳轉(zhuǎn)、vue-router、vuex等的使用示例,以及mp-webpack-plugin的配置示例。
對于多頁面的應(yīng)用,在 Web 端可以直接通過 a 標(biāo)簽或者 location 對象進行跳轉(zhuǎn),但是在小程序中則行不通。同時 Web 端的頁面 url 實現(xiàn)和小程序頁面路由也是完全不一樣的。
Demo實例對比
其中,有一部分兩端差異的業(yè)務(wù)邏輯功能,也給出了3種不同的解決方案:
利用vue-improve-loader,在構(gòu)建時對dom樹節(jié)點進行刪減,在需要提出的節(jié)點加上check-reduce屬性 利用reduce-loader,將業(yè)務(wù)中不需要被打包的代碼進行去除,使用行內(nèi)loader和環(huán)境變量來判斷 使用樣式隱藏,即設(shè)置不需要顯示的節(jié)點樣式為 display:none
其他問題
在實際開發(fā)中,還會碰到一些細(xì)節(jié),例如:
- 多頁面開發(fā):修改webpack和mp-webpack-plugin配置
- 小程序內(nèi)置組件:部分用html標(biāo)簽代替,其他用wx-component + behavior標(biāo)簽
- 小程序自定義組件:修改mp-webpack-plugin配置,補充wxCustomComponents字段,將自定義組件放入組件根目錄,使用自定義組件
- 自定義app.js和app.wxss:監(jiān)聽app的生命周期,修改webpack配置補充app.js的構(gòu)建入口,修改插件配置的generate.app字段,補充app.js
- 擴展dom/bom對象和API:使用 window.$$extend追加方法
- 代碼優(yōu)化:用reduce-loader做體積精簡,dom樹精簡用vue-improve-loader
- 區(qū)分環(huán)境實現(xiàn)不同功能:process.env.isMiniprogram
更新迭代
kbone由于目前在快速發(fā)展期,更新迭代非常迅速,以下特性是對比了8月份的版本和11月份版本,可以看出已經(jīng)解決了近2/3的問題。
小程序技術(shù)選型
詳細(xì)了解了kbone之后,我們來分析下小程序技術(shù)框架到底應(yīng)該怎么選?
kbone & 小程序原生
- 已有web版,需要小程序版:kbone
- 跨平臺需求(web + 小程序):kbone
- 對性能特別苛刻 or 追求穩(wěn)定 or 要用最新功能:小程序原生
- 頁面節(jié)點數(shù)量特別多( 1000 節(jié)點以上),且對渲染性能要求高:靜態(tài)模板轉(zhuǎn)義方案(第三方框架:mpvue/taro等)
第三方框架
- MpVue :不推薦再用了,坑越來越多,內(nèi)部也表示之后不會投入太多維護
- WePY 1.7.x :不推薦再用了:1.7.x 的版本在最初的設(shè)計上的缺陷導(dǎo)致遺留了很多比較嚴(yán)重的問題
- WePY 2.0:現(xiàn)在還是 alpha 階段,內(nèi)外部有一些小程序在跑,體驗和反饋還可以。但依然 issue 比較多。害怕踩坑的也不推薦使用
- Taro: 也還是有不少問題,但相對來說應(yīng)該是比 mpVue 和 WePY 更穩(wěn)定一點
- Uni-app:mpvue的衍生版,跨端 (官方示例有6段) 支持的很好,在H5端實現(xiàn)了一套微信模擬器,可以嘗試,是目前唯一支持app端的商用方案,有獨立的編輯器HBuildX
- Chameleon: 統(tǒng)一的多態(tài)協(xié)議,漸進式跨端,提供腳手架命令工具,規(guī)劃比較宏大
- Omi :基于Taro完成的框架,kbone有支持omi的模板
- Nanachi: 基于react的編譯期間的轉(zhuǎn)義框架
總結(jié)
沒有跨端需求,只需要微信小程序 ==> 小程序原生
web端轉(zhuǎn)小程序 or 兩端 or 想要嘗鮮 ==> kbone
多端 or Vue 技術(shù)棧 ==> uni-app
多端 or React 技術(shù)棧 ==> taro
不介意學(xué)習(xí)新技術(shù)了 ==> wepy 2.0 or chaemeleon
寫在最后
小程序在非常快速的更新迭代,就算是原生框架也還是有一些坑的,因此沒有哪種框架是百分之百完美,需要根據(jù)業(yè)務(wù)具體需求以及自身技術(shù)棧偏好來進行選擇。
如果是你,你會怎么選擇?歡迎你在留言區(qū)給出答案。