經(jīng)過持續(xù)的迭代,Rax 小程序迎來了一個(gè)大的升級(jí),支持全新的運(yùn)行時(shí)方案。站在 2020 年初這個(gè)時(shí)間點(diǎn),我們想從 Rax 小程序的特點(diǎn)出發(fā),進(jìn)行一次全面的梳理與總結(jié),并且在文末附上了 Rax 與當(dāng)前主流的小程序開發(fā)框架的對(duì)比。本文將從 API 設(shè)計(jì)與性能、雙引擎架構(gòu)、優(yōu)秀的多端組件協(xié)議設(shè)計(jì)和基于 webpack 的工程架構(gòu)四個(gè)方向展開。 一、API 設(shè)計(jì)與性能當(dāng)決定一個(gè)產(chǎn)品的技術(shù)選型的時(shí)候,我們往往會(huì)從幾個(gè)方面考慮,(1)可用生態(tài),即周邊相關(guān)的工具是否滿足產(chǎn)品開發(fā)的條件;(2)風(fēng)險(xiǎn)率,即出現(xiàn)問題是否能夠快速定位解決,所使用的技術(shù)是否會(huì)持續(xù)維護(hù);(3)上手成本,即需不需要很大代價(jià)才能達(dá)到能夠使用的階段;(4)性能,即能夠滿足產(chǎn)品既定的性能標(biāo)準(zhǔn)以及用戶體驗(yàn)。 本節(jié)主要會(huì)介紹 Rax 小程序在后面兩點(diǎn)上的優(yōu)勢。 API 設(shè)計(jì)框架整體的上手成本是比較小的,Rax 小程序鏈路從框架上是繼承自 Rax(構(gòu)建多端應(yīng)用的漸進(jìn)式類 React 框架)。所以只要你會(huì) Rax Web/Weex 開發(fā)或者 React,那么你就會(huì)用 Rax 開發(fā)小程序,并且可以同時(shí)投放到 Rax 所支持的其它端。 但是由于小程序端的特殊性,總會(huì)存在無法抹平以及需要單獨(dú)處理的地方。得益于 Rax 已經(jīng)做了比較久的多端方案,我們認(rèn)為,每個(gè)端獨(dú)立的屬性不應(yīng)該入侵基礎(chǔ)框架本身,保證基礎(chǔ)框架的純凈有利于做更多的擴(kuò)展。 以下面的代碼為例: Taro: import Taro, { Component } from '@tarojs/taro' Rax:
在和 Taro 的對(duì)比中,可以看出主要是兩點(diǎn)差異:(1)Rax 沒有 這就是前文所說的不入侵基礎(chǔ)框架本身,React 本身其實(shí)是沒有 當(dāng)然這種設(shè)計(jì)本身會(huì)導(dǎo)致代碼量一定的膨脹,但是通過工程上的手段,是可以保證最后產(chǎn)物代碼的體積幾乎毫無差異。 性能小程序的性能問題是在業(yè)務(wù)開發(fā)中經(jīng)常會(huì)遇到的,為此 Rax 小程序現(xiàn)有的編譯時(shí)方案也做了很多的努力。通過阿里小程序真機(jī)云測的功能,我們對(duì)一個(gè)無限下拉的列表做了測試。 頁面結(jié)構(gòu)如下: 根據(jù)真機(jī)測試報(bào)告,原生小程序三次平均是 2008 ms,Taro 是 2003ms,Rax 是 1924ms,當(dāng)然其實(shí)相差并不多,但是實(shí)際的業(yè)務(wù)場景其實(shí)遠(yuǎn)比上面的頁面結(jié)構(gòu)更加復(fù)雜。 與 Taro 類似的,Rax 小程序側(cè)的基礎(chǔ)框架沒有在邏輯層弄一個(gè) VDOM,而是通過數(shù)據(jù)合并、傳統(tǒng)的數(shù)據(jù) diff,來避免用戶更新冗余的數(shù)據(jù)。更多的是,阿里小程序原生提供了私有方法 另外需要提到的是,前面說的原生事件監(jiān)聽,小程序本身需要預(yù)先注冊(cè)才能監(jiān)聽事件(這也是為了保障性能),即需要: Page({ 而不能動(dòng)態(tài)注冊(cè):
所以加入 于是 Rax 小程序引入了 當(dāng)然,Rax 小程序能做的性能優(yōu)化到此為止了么?在可計(jì)劃的未來,Rax 小程序編譯時(shí)方案已經(jīng)有一些明確的 action,比如進(jìn)一步減輕框架對(duì) 二、雙引擎架構(gòu)Rax (可能)是業(yè)界首個(gè)同時(shí)支持編譯時(shí)和運(yùn)行時(shí)方案的小程序解決方案。兩種方案之間的切換無比簡單,我們將高性能 or 完整語法的選擇權(quán)真正地交給了用戶。雙引擎驅(qū)動(dòng)的 Rax 小程序架構(gòu)如下: 編譯時(shí)方案Rax 小程序編譯時(shí)方案是基于 AST 轉(zhuǎn)譯的前提下,將 Rax 代碼通過詞法、語法分析轉(zhuǎn)譯成小程序原生代碼的過程。由于 JavaScript 的動(dòng)態(tài)能力以及 JSX 本身不是一個(gè)傳統(tǒng)模板類型語法,所以在這個(gè)方案中引入一個(gè)較為輕量的運(yùn)行時(shí)墊片。 Rax 小程序編譯時(shí)架構(gòu)的核心主要分為兩個(gè)部分,AST 轉(zhuǎn)譯和運(yùn)行時(shí)墊片。下文會(huì)針對(duì)這兩個(gè)部分做簡要的介紹。 AST 轉(zhuǎn)譯AST 轉(zhuǎn)譯部分的架構(gòu)相比同類產(chǎn)品 Taro 來說,更加清晰以及可維護(hù)性更強(qiáng)。這里不得不提到,它的分語法場景轉(zhuǎn)譯以及洋蔥模型。我們可以粗略的看一下,分語法場景轉(zhuǎn)譯部分的代碼結(jié)構(gòu): 可以比較清晰的看到,針對(duì)需要轉(zhuǎn)譯的每一個(gè)語法場景都有一個(gè)模塊專門負(fù)責(zé)轉(zhuǎn)譯,這就讓整個(gè)轉(zhuǎn)譯的過程輕松了起來,只要每一部分的轉(zhuǎn)譯結(jié)果符合預(yù)期,那么轉(zhuǎn)譯結(jié)果就是符合預(yù)期的。這樣的設(shè)計(jì)可以讓我們能夠充分利用單元測試來對(duì)轉(zhuǎn)譯前后的代碼進(jìn)行比較。 而洋蔥模型的設(shè)計(jì)則是AST 轉(zhuǎn)譯的另一個(gè)主要設(shè)計(jì),整個(gè)轉(zhuǎn)譯過程實(shí)際上分為 4 個(gè)步驟: 洋蔥模型主要進(jìn)行的是后面三步,在 parser 層將原有的 AST 樹修改為符合預(yù)期的新 AST 樹,然后在 generate 層將新的 AST 樹轉(zhuǎn)譯成小程序代碼。 運(yùn)行時(shí)墊片由于 JSX 的動(dòng)態(tài)能力以及 Rax 原本提供的一些例如 hooks 之類的特性。所以,Rax 小程序編譯時(shí)方案提供了一個(gè)運(yùn)行時(shí)墊片,用來對(duì)齊模擬 Rax core API 。 既然引入了運(yùn)行時(shí),自然可以基于這套機(jī)制對(duì)數(shù)據(jù)流做更多的管理,以及提供 Rax 工程在其他端上的 API,比如路由相關(guān)的 運(yùn)行時(shí)方案Rax 小程序的運(yùn)行時(shí)方案沒有自研,而是『站在了巨人的肩膀上』,復(fù)用了 kbone[3] 的架構(gòu)并對(duì)其作了一定程度的改造以接入 Rax 小程序的工程體系。關(guān)于運(yùn)行時(shí)方案的實(shí)現(xiàn)原理可以點(diǎn)擊這里[4]查看,此處不再詳細(xì)介紹。首先需要介紹的是 Rax 小程序同時(shí)也是 kbone 的優(yōu)點(diǎn):
而在 kbone 的基礎(chǔ)上,Rax 小程序運(yùn)行時(shí)方案還新增了不少特性,概括起來有以下幾點(diǎn):
最后,我們也不能回避的是,Rax 小程序運(yùn)行時(shí)方案具有所有運(yùn)行時(shí)方案都存在的問題:性能損耗。事實(shí)上,運(yùn)行時(shí)方案就是以一定的性能損耗來換取更為全面的 Web 端特性支持。所以,如果你對(duì)小程序有一定的性能要求,建議使用編譯時(shí)方案;如果對(duì)性能要求不高,那么運(yùn)行時(shí)方案就是助你快速開發(fā)小程序的利器。雙引擎驅(qū)動(dòng)的 Rax 小程序,總有一處能夠擊中你的內(nèi)心。 三、優(yōu)秀的多端組件協(xié)議設(shè)計(jì)Rax 小程序編譯時(shí)方案支持項(xiàng)目級(jí)開發(fā)和組件級(jí)開發(fā)。與 Taro 將組件統(tǒng)一在項(xiàng)目中進(jìn)行編譯產(chǎn)出為小程序代碼不同,Rax 在組件工程中即可構(gòu)建出小程序組件。結(jié)合一套優(yōu)秀的多端組件協(xié)議設(shè)計(jì),我們做到了在 Rax 小程序項(xiàng)目和原生小程序項(xiàng)目中都能正常使用 Rax 小程序組件,同時(shí)保持統(tǒng)一的多端開發(fā)體驗(yàn)。該協(xié)議定義在 package.json 中的 支持漸進(jìn)式接入 Rax對(duì)于那些已經(jīng)使用原生語法開發(fā)了完整的小程序的開發(fā)者來說,一個(gè)很合理的需求就是漸進(jìn)地切換到 Rax 開發(fā)鏈路上來,畢竟整個(gè)項(xiàng)目遷移可能成本高昂。而 Rax 依托多端組件協(xié)議,能夠幫助開發(fā)者平滑過渡。 按照設(shè)計(jì),Rax 小程序組件工程的構(gòu)建產(chǎn)物為符合小程序語法的組件,因此其理所當(dāng)然可以直接在原生小程序項(xiàng)目中使用。這意味著,如果你想漸進(jìn)式地使用 Rax 來開發(fā)小程序,可以以組件或者頁面為單位將之前使用原生語法開發(fā)的小程序逐漸地遷移到 Rax 上來。而這,也是 Taro 等其他框架不具備的能力。在 Rax 的使用方中,浙江省網(wǎng)上政務(wù)平臺(tái)『浙里辦』支付寶小程序即采用了漸進(jìn)式接入 Rax 的方式。 多端統(tǒng)一的組件使用體驗(yàn)當(dāng)使用 Rax 組件工程發(fā)布的小程序組件在 Rax 項(xiàng)目中使用時(shí),構(gòu)建器會(huì)自動(dòng)通過 // Wrong 除此之外,多端組件協(xié)議還可以擴(kuò)展成多端組件庫協(xié)議,支持更靈活的類似 四、基于 webpack 的工程架構(gòu)Rax 工程以阿里巴巴集團(tuán)前端統(tǒng)一的 CLI 工具 @alib/build-script[7] 為基礎(chǔ),其依賴 webpack,通過插件體系支持各個(gè)場景,同時(shí)基于 webpack-chain 提供了靈活的 webpack 配置能力,用戶可以通過組合各種插件實(shí)現(xiàn)工程需求。Rax 小程序的編譯時(shí)方案通過 webpack loader 來處理自身邏輯。以 app/page/component 等文件角色分類的 webpack loader 會(huì)調(diào)用 jsx-compiler 進(jìn)行代碼的 AST 分析及處理,再將處理完的代碼交由 loader 生成對(duì)應(yīng)的小程序文件;運(yùn)行時(shí)方案直接復(fù)用 Web 端的編譯配置,再通過額外的 webpack 插件生成具體的小程序代碼。 相比其他自研的工程體系,整套架構(gòu)具有如下優(yōu)點(diǎn):
總結(jié)最后,附上 Rax 和現(xiàn)有主流小程序框架的對(duì)比。 更多關(guān)于 Rax 小程序的內(nèi)容,歡迎訪問 https://rax./miniapp 了解! 參考資料https://github.com/alibaba/rax: https://link.zhihu.com/?target=https%3A//github.com/alibaba/rax [2]https://rax./miniapp: https://link.zhihu.com/?target=https%3A//rax./miniapp [3]kbone: https://github.com/wechat-miniprogram/kbone [4]這里: https://wechat-miniprogram./kbone/docs/guide/principle.html [5]Rax 小程序——多端組件開發(fā): https://rax./docs/guide/multiple-ends-component-development [6]Rax 基礎(chǔ)組件: https://rax./docs/components/introduce [7]@alib/build-script: https://www./package/@alib/build-scripts 關(guān)注我們 |
|