初識weex與rax
背景
weex目前在集團乃至全球發展的如火如荼,最近也正在了解相關的資料,目前隻是一些初步的了解,在這裏分享一下。weex是跨端渲染框架,就是說一套代碼,可以在web、ios和android跑,而且在後兩者中,是以native方式跑的,因此在渲染效率和交互流暢度上,均有上乘的表現。weex於2016年開始在淘係雙11、雙12大促大規模使用,穩定可靠,可以看鬼道的介紹:《Weex 在雙十一會場的大規模應用:業務支撐、穩定性保障和秒開實戰》
那麼為什麼要做weex,相信做過web移動端頁麵的開發非常清楚,主要原因就是web在渲染和操作體驗上的表現,相對於native來說又慢又卡,但是native雖然好,但開發卻遠比h5麻煩,不但開發環境麻煩、部署麻煩,還需適配android和ios兩大平台,甚至需要招不同的程序員,h5盡管也有平台瀏覽器內核的兼容性問題,但開發容易上手,相對於native的開發成本,這些處理兼容性問題的代價基本上算是可以忽略了。
react-native、react-web與weapp
如何即讓學習成本低、代碼寫的少,部署簡單,又盡可能地在三端都能跑流暢,是全球各大互聯網公司都在較勁腦汁思考的問題,比如facebook的react-native,實現了“learn once,run anywhere”,但因為其還是不能實現h5的渲染降級,因此說的是learn once,即web端還是需要再寫一遍,react-web做了一個能讓react-native代碼跑在web的事情,為什麼react-native能實現一份代碼跑兩端,react-web又能擴展其web渲染呢?其實是因為無論是web、ios還是android,盡管其底層實現的api或控件不同,但都能實現相同功能的布局和界麵,因此要實現一份代碼跑三端,最關鍵的是把三端的布局細節封裝並對上層屏蔽,上層UI描述使用一樣的DSL,在native渲染的時候,再根據不同平台走不同的renderer。
再說集團,在3年前,集團的weapp也做了這個事情,它使用json或xml描述界麵,包含界麵的布局、樣式、事件甚至聯動,然後能實現三端渲染:
{
"type":"label",
"dataBinding":{"value":"$phone_number"},
"styleBinding":{"align":4,"fontSize":28,"fontStyle":1,"gravity":4,"height":80,"lines":1,"marginLeft":86,"textColor":"#3d3f45","width":-1}
"events":[
{
"type":"click",
"actions":[
{
"type":"userTrack",
"param":{"utName":"TelPhone","utParams":{"wp_app":"weapp","wp_m":"phone_7","wp_pk":"$wp_pk"},"utType":"Button"}}
{
"type":"phoneCall",
"param":{"phoneNumber":"$phone_number"}
}
]
}]
}
weapp的想法是很好的,也有很多應用場景,1688早期的roc,就是使用weapp搭建native頁麵,在後期,很多無線團隊也在研究weapp與react-native的融合,但weapp由於是基於json的,因此編寫邏輯不靈活,也不方便編寫和引用模塊,還有很多私有的語法增加了學習成本,落地情況不是很理想,因此在後來react-native出來以後,看到這麼耀眼的東西一個存在,基本上就在思考新的方式了。
weex與rax
這個新的思路就是weex,weex吸取了集團在跨端方麵的很多沉澱,拋棄了一些缺陷,主要有這麼一些優勢:
- 使用web的方式寫代碼,通過與vue的結合,深得社區人心,尤其是h5移動頁麵開發者,學習成本實在太低了,首先解決了一個使用難的問題
- 實現了跨三端的高性能渲染,比native要慢,但比react-native要快
- 成熟配套的工具支持,weex sdk、weex toolkit、weex playground等,比起react-native,更容易上手
- 開放了native dom api,因此上層可以開發自己的js框架,後來的rax就是基於此實現的
我們來看下weex的架構:
在DSL層,使用vue的方式編寫界麵和交互,打包編譯成js bundler自執行文件,js bundle通過url協議被客戶端識別,這個過程可通過離線緩存,或者直接請求的方式實現,客戶端要執行這個js,那麼必須有一個js引擎,目前用的是google v8,js本身是不可能渲染native控件的,因此需要一個jsbridge,jsbridge去callnative實現native控件的生成,不同端的native渲染是不一樣的,值得一提的是,如果是web端,那麼就不需要jsbridge去callNative了,直接走dom渲染。
weex架構的有一個好處就是,開放了vdom這一層,即操作nativeDom的這一層,這意味著你可以自己手寫代碼渲染native界麵,或者自行封裝框架,比如這段代碼,即沒用vue,也沒用jsx,直接手寫,也一樣能在native運行:
var m = __weex_require__('@weex-module/modal');
m.alert({
message: "你好嗎?"
});
document.open();
var body = document.createBody();
document.documentElement.appendChild(body);
var x = document.createElement("text");
x.attr.value = "hello faxin";
x.style = {
color: "green",
fontSize: 100
};
document.body.appendChild(x);
document.close();
//隱藏菊花
sendTasks(document.id, [{module: 'dom', method: 'createFinish', args: []}]);
把這個js放到本地http服務器,然後手機連上公司wifi,用weex的playground掃描即可渲染出結果:
如果沒裝,可以使用mds模擬,值得一提的是,mds還提供了weex js的斷點調試能力,非常推薦:
可以看到,這些api和dom的太像了,事實上,無論是weex jsframework,還是rax,都是對vdom的上層封裝而已,有點類似無論是angular、jquery,其實最終都是操作瀏覽器的dom api來驅動渲染html,在這點上看,我們可以把weex底層看成一個dom level提供者。
接下來再說一下rax,rax是跨容器渲染框架,寫法與react基本兼容,rax的前身應該就是react-web,隻是現在直接驅動weex容器作為native渲染了,rax的架構有許多值得學習的地方,他的界麵寫法使用jsx,接下來編譯成js,有virtual dom的機製在裏麵,在最終的渲染端,是通過驅動的機製來實現,也就是說,它能在哪裏渲染,取決於你寫的驅動,目前在native的渲染,直接對接了weex的native dom api,在web的渲染,使用自己的封裝,還有服務器的渲染,你如果後麵要寫在其他設備的渲染,理論上可以自己編寫驅動來實現。
表麵上看,rax是提供了另外一種陣營的選擇,即vue體係意外的react體係,但它還做了很多事情:
- rax ui庫,封裝了很多集團內的庫和組件,如slider、tab、spm打點等等,大部分業務都可以稍微封裝即可使用
- 兼容的處理,比weex在h5渲染還原度更高
- 支持返回一批元素,了解react的同學知道,react必須返回一個帶根root的元素
結語
跨三端是多少移動開發人員的夢想,如今在weex體係下已經得到幾乎完美的解決,盡管在h5降級上仍有細微的缺陷,目前weex已經捐到了apache基金會,預計未來會得到持續的發展,也歡迎更多的同學加入其研發或者接入。
最後更新:2017-10-24 19:33:54