<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          美團(tuán)民宿跨端復(fù)用框架設(shè)計(jì)與實(shí)踐

          共 13698字,需瀏覽 28分鐘

           ·

          2021-09-05 00:39


          從 PC 時(shí)代、移動(dòng)時(shí)代到萬(wàn)物互聯(lián)的 IoT 時(shí)代,伴隨終端設(shè)備的日趨多樣化,跨端復(fù)用的種子自此落地,開始生根發(fā)芽。從依靠容器能力、各類離線化預(yù)裝包的 Hybrid 方案,到通過(guò) JSC 連接 JavaScript 生態(tài)與原生控件,結(jié)合視圖框架(React、Vue等)尋找效率、動(dòng)態(tài)性和性能更均衡的 Native 容器方案(React Native、Weex 等),接著由微信牽頭的以多進(jìn)程 WebView、容器標(biāo)準(zhǔn)化的小程序方案出世,各平臺(tái)小程序隨之春筍萌發(fā),隨后帶來(lái)了國(guó)內(nèi)Taro、uni-app、Rax、Remax等多端框架的百家爭(zhēng)鳴。


          從業(yè)務(wù)角度出發(fā),跨端技術(shù)演進(jìn)更多是在不同階段、不同時(shí)間段內(nèi)業(yè)務(wù)效率上的選擇,美團(tuán)民宿業(yè)務(wù)就是在大前端融合的浪潮中逐浪前行,不斷探索和迭代抉擇,為解決業(yè)務(wù)痛點(diǎn)而孵化出跨端框架技術(shù)。本文主要分享美團(tuán)民宿在跨端復(fù)用技術(shù)探索層面以及業(yè)務(wù)實(shí)踐過(guò)程中積累的經(jīng)驗(yàn),希望能給大家?guī)?lái)一些幫助或者啟發(fā)。

          • 1. 背景

            • 1.1 美團(tuán)民宿業(yè)務(wù)介紹

            • 1.2 美團(tuán)民宿移動(dòng)端現(xiàn)狀

          • 2. 美團(tuán)民宿跨端復(fù)用框架設(shè)計(jì)

            • 2.1 行業(yè)現(xiàn)狀

            • 2.2 整體方案設(shè)計(jì)

          • 3. 美團(tuán)民宿跨端復(fù)用實(shí)踐

            • 3.1 跨端復(fù)用場(chǎng)景下的問(wèn)題

            • 3.2 跨端復(fù)用應(yīng)用架構(gòu)

            • 3.3 跨端復(fù)用方式設(shè)計(jì)

            • 3.4 跨端復(fù)用流程規(guī)范

            • 3.5 跨端復(fù)用質(zhì)量保障

            • 3.6 成果

          • 4. 總結(jié)

          1. 背景

          1.1 美團(tuán)民宿業(yè)務(wù)介紹

          美團(tuán)民宿專注為消費(fèi)者提供“住得不一樣”的旅居體驗(yàn),提供的服務(wù)包括民宿、酒店、公寓、客棧、短租、賓館、旅行住宿等,同時(shí)包括樹屋、房車、INS 風(fēng)等新奇的網(wǎng)紅民宿。美團(tuán)民宿自上線之后,業(yè)務(wù)發(fā)展迅猛,在供給側(cè),房源類型不斷豐富,各類分銷、直銷、直連、境外陸續(xù)推出,房源信息維度不斷擴(kuò)展,篩選、推薦、信息呈現(xiàn)也不斷變得復(fù)雜。同時(shí)伴隨著營(yíng)銷方式的豐富、房東管理、經(jīng)營(yíng)、服務(wù)的不斷擴(kuò)充,民宿的業(yè)務(wù)也越來(lái)越復(fù)雜。美團(tuán)民宿大前端伴隨業(yè)務(wù)的發(fā)展不斷自我迭代,移動(dòng)端整體架構(gòu)也隨之不斷調(diào)整、升級(jí),以尋求匹配業(yè)務(wù)多樣化、復(fù)雜化的發(fā)展訴求。

          1.2 美團(tuán)民宿移動(dòng)端現(xiàn)狀

          業(yè)務(wù)的發(fā)展和跨端復(fù)用技術(shù)的不斷演化,讓美團(tuán)民宿客戶端從業(yè)務(wù)剛起步的單端 Native App,到跨  App(民宿 App、美團(tuán) App、點(diǎn)評(píng) App )的 Native 復(fù)用和以 SSR 彌補(bǔ)性能差距的 Hybrid 的結(jié)合方案,在這場(chǎng)性能和效率的博弈中,客戶端最終落腳以 React Native(以下簡(jiǎn)稱 RN)為核心的復(fù)用框架。在此同時(shí),民宿小程序端也隨著微信小程序的誕生、生態(tài)壯大、多平臺(tái)化的趨勢(shì)不斷成長(zhǎng),逐漸形成多平臺(tái)復(fù)用的小程序架構(gòu)。

          圖1 美團(tuán)民宿移動(dòng)端原始架構(gòu)圖

          上圖是美團(tuán)民宿移動(dòng)端原始架構(gòu)圖,左側(cè)是客戶端的技術(shù)架構(gòu),iOS 和 Android 系統(tǒng)層之上是獨(dú)立的 Native 基建層,再往上通過(guò)了 RN 打開雙端的復(fù)用之門,接著以 RN 容器標(biāo)準(zhǔn)化屏蔽了宿主應(yīng)用間差異,保障了容器化的一致性,進(jìn)而實(shí)現(xiàn)了業(yè)務(wù)層的復(fù)用和跨 App 的復(fù)用。右側(cè)是民宿小程序當(dāng)前簡(jiǎn)化的架構(gòu)圖,我們?cè)诨▽幼隽硕喽诉m配,通過(guò)多平臺(tái)復(fù)用構(gòu)建工具實(shí)現(xiàn)了各平臺(tái)小程序的復(fù)用。當(dāng)前客戶端和小程端相關(guān)獨(dú)立,開發(fā)維護(hù)也相互獨(dú)立,團(tuán)隊(duì)各司其職。

          盡管美團(tuán)民宿 App 已經(jīng)通過(guò) RN 實(shí)現(xiàn) iOS 和 Android 的跨端復(fù)用,但是由于 App 和小程序仍然需要投入雙倍的人力成本進(jìn)行業(yè)務(wù)迭代,所以我們思考一個(gè)問(wèn)題:是否可以更進(jìn)一步,使用一套代碼解決多端,把 iOS App、Android App、小程序進(jìn)行大一統(tǒng)。

          2. 美團(tuán)民宿跨端復(fù)用框架設(shè)計(jì)

          2.1 行業(yè)現(xiàn)狀

          近幾年,在微信小程序產(chǎn)品牽頭下,業(yè)界也隨之誕生出各種小程序應(yīng)用,各端技術(shù)差異使得開發(fā)和維護(hù)成本都成倍增加。為了抹平原生開發(fā)、小程序開發(fā)、Web 開發(fā)等技術(shù)差異,一些優(yōu)秀多端框架也就此誕生了。比如 Taro、uni-app、Rax、Remax 等,這些框架都是以自身定義 DSL (一般是 React DSL、Vue DSL)轉(zhuǎn)換成各端應(yīng)用(微信小程序、RN、H5等),從而實(shí)現(xiàn)一套代碼,多端運(yùn)行。

          在美團(tuán)民宿業(yè)務(wù)中,App 的交易占比較大,從業(yè)務(wù)角度出發(fā)需優(yōu)先保障 App 的性能體驗(yàn)和需求開發(fā)效率,而當(dāng)前的民宿 App 已遷移至 RN 技術(shù)棧。基于這兩點(diǎn),我們希望跨端復(fù)用方案的是:RN 轉(zhuǎn)到小程序平臺(tái)方案,所以上述的多端框架并不能滿足我們的 RN-小程序跨端復(fù)用的訴求,為此美團(tuán)民宿參考了業(yè)界多端設(shè)計(jì)方案,實(shí)現(xiàn)了基于 RN 轉(zhuǎn)小程序復(fù)用的方案。

          RN 采用的是 React 語(yǔ)法,因此如何將 RN 轉(zhuǎn)換為小程序,首先要思考如何將 React 代碼轉(zhuǎn)換成小程序可運(yùn)行的代碼(簡(jiǎn)稱小程序代碼),其次是 RN 基礎(chǔ)組件庫(kù)的適配。隨著這幾年的發(fā)展, React 代碼轉(zhuǎn)換成小程序代碼在業(yè)界實(shí)踐也是層出不窮,業(yè)界方案分為編譯時(shí)與運(yùn)行時(shí)兩類,以下是這兩類方案的簡(jiǎn)單對(duì)比:

          對(duì)比來(lái)看,重編譯方案有一個(gè)嚴(yán)重的問(wèn)題:語(yǔ)法限制。因?yàn)榇蟛糠智岸碎_發(fā)者們已經(jīng)對(duì)靈活的語(yǔ)法有一定的依賴性,比如會(huì)使用高階組件、在條件判斷的時(shí)候?qū)懞芏?return 等等,這種寫法很難在編譯過(guò)程被準(zhǔn)確命中。因此,編譯時(shí)方案就會(huì)制定一些語(yǔ)法規(guī)則來(lái)限制開發(fā)者的寫法。重運(yùn)行方案則沒(méi)有語(yǔ)法限制問(wèn)題,可以隨意使用各種 React 特性。它的實(shí)現(xiàn)原理是通過(guò) react-reconciler 實(shí)現(xiàn)小程序平臺(tái)對(duì)應(yīng)的 React 渲染器(以下簡(jiǎn)稱 MP-Renderer),從而來(lái)渲染虛擬 DOM 樹。不過(guò)小程序沒(méi)有 DOM API 可以更新界面,所以生成的虛擬 DOM 樹數(shù)據(jù)是通過(guò)小程序的 setData 觸發(fā)渲染層的更新,在渲染層里有一個(gè)通用模板可以用來(lái)渲染這些數(shù)據(jù)。

          因重編譯語(yǔ)法限制的問(wèn)題,我們決定采用重運(yùn)行時(shí)方案來(lái)實(shí)現(xiàn) RN 轉(zhuǎn)小程序。但重運(yùn)行方案存在性能問(wèn)題,難以滿足業(yè)務(wù)的要求,我們經(jīng)不斷探索后設(shè)計(jì)了對(duì)應(yīng)的方案極大提升了性能,下文會(huì)詳細(xì)描述如何解決這個(gè)問(wèn)題的。

          2.2 整體方案設(shè)計(jì)

          2.2.1 RN 與小程序復(fù)用的技術(shù)方案

          圖2 RN與小程序復(fù)用技術(shù)方案圖

          整體架構(gòu)分為兩個(gè)部分:編譯過(guò)程、運(yùn)行過(guò)程。它的渲染方式與上文描述重運(yùn)行時(shí)方案類似,都是通過(guò) MP-Renderer 來(lái)處理 React 代碼。下面我們來(lái)簡(jiǎn)要分析這兩個(gè)過(guò)程:

          (1) 編譯過(guò)程:該階段對(duì) RN 源碼進(jìn)行一定的轉(zhuǎn)換處理,用于運(yùn)行過(guò)程,編譯后主要產(chǎn)生有以下產(chǎn)物:

          • 編譯后的 RN :經(jīng)過(guò)編譯后產(chǎn)生 RN 代碼,本質(zhì)上還是 React 代碼。
          • 適配組件庫(kù):RN 基礎(chǔ)組件的適配庫(kù),是使用小程序自定義組件實(shí)現(xiàn)的。
          • 通用模板:由于小程序沒(méi)有像 Web 有 DOM API 操作節(jié)點(diǎn)操作方法,所以這里通過(guò)一個(gè)通用模板來(lái)渲染 React 渲染出來(lái)的 TreeData (頁(yè)面虛擬 DOM 樹序列化后的 UI 數(shù)據(jù))。
          • 合并模板:主要用于性能優(yōu)化的,下文會(huì)詳細(xì)分析這個(gè)模板的作用。
          • WXSS:將 RN 代碼的 Style 轉(zhuǎn)換為 WXSS,這樣可以減少頁(yè)面的 TreeData 數(shù)據(jù)量,從而優(yōu)化性能。

          (2) 運(yùn)行過(guò)程:運(yùn)行過(guò)程分為邏輯層和視圖層兩部分。

          • 邏輯層:編譯后的 RN 源碼包含 RN 業(yè)務(wù)組件和適配組件庫(kù),適配組件庫(kù)是通過(guò)小程序自定義組件來(lái)進(jìn)行適配。這樣的方式既可以靈活使用小程序原生代碼對(duì)齊 RN 組件功能,也可以提升轉(zhuǎn)換后小程序的性能,因?yàn)樾〕绦蛟a不會(huì)產(chǎn)生 TreeData 數(shù)據(jù),從而使性能上得到提升。邏輯層有一個(gè) MP-Renderer ,實(shí)現(xiàn)方式和上文講述的是一樣的,RN 代碼經(jīng)過(guò)渲染后,便產(chǎn)生對(duì)應(yīng)的虛擬 DOM 樹,虛擬 DOM 樹數(shù)據(jù)再經(jīng)過(guò)序列化便產(chǎn)生對(duì)應(yīng)的 TreeData(描述頁(yè)面的 UI 數(shù)據(jù))。
          • 渲染層:當(dāng)頁(yè)面需要更新的時(shí)候,邏輯層通過(guò) setData 將 TreeData 傳輸?shù)戒秩緦永铮琓reeData 與通用模板、合并模板和對(duì)應(yīng)樣式結(jié)合在一起,便可以渲染出對(duì)應(yīng)的 UI。

          綜上所述,上述整體設(shè)計(jì)與業(yè)界多端框架有點(diǎn)類似,但是也有不同點(diǎn),主要體現(xiàn)在適配組件庫(kù)和合并模板。適配組件庫(kù)上文有解釋比較好理解,而合并模板這里可能大家還是比較有疑惑的。其實(shí)這個(gè)合并模板內(nèi)容是由編譯過(guò)程的 “靜態(tài)編譯” 轉(zhuǎn)換生成的,這樣的處理方式是為提升轉(zhuǎn)換后的小程序性能,接下來(lái),我們會(huì)著重來(lái)講述這個(gè)性能解決方案。

          2.2.2 性能解決方案

          重運(yùn)行時(shí)方案性能損耗原因是什么?正如上文所說(shuō),重運(yùn)行時(shí)方案會(huì)將所有 React 代碼對(duì)應(yīng)的 TreeData,再通過(guò)小程序 setData 傳輸?shù)戒秩緦?,?dāng)頁(yè)面初始化或者大數(shù)據(jù)更新的話,setData 就需要傳遞比較大的一個(gè)數(shù)據(jù),因此也就會(huì)造成對(duì)應(yīng)的性能問(wèn)題。所以要解決這種方案的性能問(wèn)題,核心就是要減少 TreeData 數(shù)據(jù)量。

          在上述 RN 轉(zhuǎn)小程序方案,有提到適配組件庫(kù)、樣式轉(zhuǎn)換等是可以起到對(duì)應(yīng)性能優(yōu)化作用的,它的優(yōu)化原理正是通過(guò)減少 TreeData 數(shù)據(jù)的方式。盡管這些方式可以優(yōu)化性能,但是在頁(yè)面比較復(fù)雜的時(shí)候,TreeData 數(shù)據(jù)量仍然會(huì)保留比較大,因此優(yōu)化效果并不明顯。為此,我們思考一種新的方式來(lái)進(jìn)一步壓縮 TreeData 的數(shù)據(jù)量,也就是前文所提到的結(jié)合靜態(tài)合并樹節(jié)點(diǎn)方案,在講述該方案前我們先來(lái)看下一個(gè) RN 代碼轉(zhuǎn)換為 TreeData 的例子:

          圖3 RN代碼轉(zhuǎn)換TreeData示例圖

          如上圖所示,RN 代碼轉(zhuǎn)換后的 TreeData 是一個(gè)描述 UI 樹的 JSON 數(shù)據(jù),等同于右側(cè)的 UI 樹,將這顆樹的節(jié)點(diǎn)進(jìn)行分類,可以分為靜態(tài)數(shù)據(jù)和動(dòng)態(tài)數(shù)據(jù),比如 View、Text 節(jié)點(diǎn)就是靜態(tài)數(shù)據(jù),而 “Hello”、“World” 則是動(dòng)態(tài)數(shù)據(jù)。所謂靜態(tài)數(shù)據(jù),就是編譯過(guò)程可預(yù)知的,因此這些數(shù)據(jù)是不是可以轉(zhuǎn)換另一種形式來(lái)描述 UI 呢,從而減少 TreeData 的數(shù)據(jù)量。答案是肯定的,靜態(tài)編譯合并樹節(jié)點(diǎn)正是通過(guò)這樣的原理來(lái)實(shí)現(xiàn)的,如下流程所示:

          圖4 靜態(tài)編譯合并樹節(jié)點(diǎn)原理圖-1

          這個(gè)方案有兩個(gè)動(dòng)作,分別是靜態(tài)編譯和合并樹節(jié)點(diǎn),靜態(tài)編譯就將 RN 代碼的轉(zhuǎn)換成合并模板,如上圖序號(hào) 2 代碼所示,合并模板的名稱為 “b1”,內(nèi)容就是一段與 RN JSX 代碼對(duì)應(yīng)的 WXML 結(jié)構(gòu)片段。而合并節(jié)點(diǎn)是將已經(jīng)靜態(tài)編譯的節(jié)點(diǎn)進(jìn)行合并,如上圖序號(hào) 2 至序號(hào) 3 流程所示,原本五個(gè)節(jié)點(diǎn)被合并到頂層的 View 節(jié)點(diǎn),這個(gè) View 節(jié)點(diǎn)稱為合并節(jié)點(diǎn),合并節(jié)點(diǎn)需要記錄合并模板的名稱和相關(guān)的動(dòng)態(tài)數(shù)據(jù),目的是為了渲染時(shí)讓合并節(jié)點(diǎn)可以找到對(duì)應(yīng)的合并模板進(jìn)行渲染,經(jīng)過(guò)這樣合并節(jié)點(diǎn)后,最終生成的 TreeData,如上圖序號(hào) 4 所示??梢钥吹?TreeData 相比之前的數(shù)據(jù)量就減少了 60% 左右!

          看到這里,是不是有同學(xué)就有疑問(wèn)了,上文不是提到靜態(tài)編譯會(huì)有語(yǔ)法限制,那這里是否會(huì)有語(yǔ)法限制?確實(shí),如果是完全靜態(tài)編譯,是會(huì)有語(yǔ)法限制,而這里所說(shuō)的結(jié)合靜態(tài)編譯是有選擇性的編譯,即在編譯過(guò)程,首先會(huì)通過(guò) AST 分析節(jié)點(diǎn)是否靜態(tài)數(shù)據(jù),如果是的話,再轉(zhuǎn)換成對(duì)應(yīng)的合并模板。如果遇到不可預(yù)測(cè)的動(dòng)態(tài)節(jié)點(diǎn),則按照運(yùn)行時(shí)方案去處理。因此,最終生成的 UI 樹節(jié)點(diǎn)即會(huì)包含合并節(jié)點(diǎn)、也會(huì)包含原本的組件節(jié)點(diǎn),如下圖所示:

          圖5 靜態(tài)編譯合并樹節(jié)點(diǎn)原理圖-2

          通過(guò)這樣的方式,既可以保證語(yǔ)法無(wú)限制,又能通過(guò)編譯結(jié)合的手段最大化優(yōu)化性能。當(dāng)然了這種方案也是有缺點(diǎn),因?yàn)檫@種方案其實(shí)是用空間換性能的方式,生成的合并模板會(huì)影響會(huì)影響包大小,不過(guò)對(duì)于一些需要追求性能的頁(yè)面,這點(diǎn)包大小的增加是值得付出的。

          為了更好地衡量解決方案對(duì)性能的提升程度,我們參考 Taro 官網(wǎng)的實(shí)驗(yàn)(實(shí)驗(yàn)內(nèi)容),對(duì)優(yōu)化前后以及原生和 Taro 3.0 運(yùn)行后的性能指標(biāo)進(jìn)行采集與比較。經(jīng)過(guò)實(shí)驗(yàn),統(tǒng)計(jì)出各框架在初始化、加載數(shù)據(jù)、加載大量數(shù)據(jù)的操作耗時(shí),如下表所示:

          從上表中可以看出:性能優(yōu)化后,得益于更少的渲染數(shù)據(jù)與更精簡(jiǎn)的節(jié)點(diǎn)樹,加載數(shù)據(jù)的操作耗時(shí)比優(yōu)化前減少 80% ,初始化耗時(shí)減少了 52%。與同類型的框架 Taro 3.0 相比,也有更好的性能表現(xiàn)。

          與原生相比,優(yōu)化后性能差距明顯減少,但是由于運(yùn)行時(shí)方案相對(duì)于原生需要更多的 setData 數(shù)據(jù)開銷和更復(fù)雜渲染流程,所以從原理上運(yùn)行時(shí)方案和原生性能差距客觀存在。盡管如此,業(yè)務(wù)實(shí)踐上兩者差距并不會(huì)那么明顯,因?yàn)樵跍y(cè)評(píng)實(shí)驗(yàn)中測(cè)試數(shù)據(jù)比較純粹,setData 數(shù)據(jù)使用率較高,但在業(yè)務(wù)實(shí)踐中原生開發(fā) setData 數(shù)據(jù)難免冗余且難以優(yōu)化,而運(yùn)行時(shí)方案會(huì)默認(rèn)優(yōu)化冗余數(shù)據(jù)使得兩者性能差距更接近,從我們歷史業(yè)務(wù)實(shí)踐數(shù)據(jù)上看,性能與原生差距在 10% 左右。

          3. 美團(tuán)民宿跨端復(fù)用實(shí)踐

          在跨端復(fù)用探索中,我們用創(chuàng)新的方案解決了性能和特性限制的難題,設(shè)計(jì)了 RN-小程序跨端復(fù)用框架。雖然跨端復(fù)用屬于“利器在手”,但是這是一把“雙刃劍”,用得其所則事半功倍,處理不當(dāng)則隱患叢生。那么,如何在業(yè)務(wù)實(shí)踐中駕馭好這把利刃呢?我們先介紹在業(yè)務(wù)實(shí)踐中遇到的問(wèn)題,然后介紹解決這些問(wèn)題的方案。

          3.1 跨端復(fù)用場(chǎng)景下的問(wèn)題

          1. 復(fù)用場(chǎng)景下的問(wèn)題:小程序產(chǎn)品形態(tài)以輕、快、便為旨,用戶可快速使用,用完即走,客戶端產(chǎn)品相對(duì)全、精、穩(wěn),可以滿足更多的用戶需求,以用戶留存、用戶認(rèn)知、用戶體驗(yàn)為主,兩者在產(chǎn)品功能上存在較大的差異,如何恰當(dāng)?shù)靥幚懋a(chǎn)品差異化問(wèn)題是跨端復(fù)用的場(chǎng)景下的一個(gè)重要挑戰(zhàn)。
          2. 跨端復(fù)用質(zhì)量隱患:實(shí)現(xiàn)了復(fù)用便要考慮兩端的各種兼容性問(wèn)題,這就會(huì)產(chǎn)生各種質(zhì)量上的隱患。如何在復(fù)用組件不斷迭代中,保障組件接口、輸入、輸出的兼容性問(wèn)題?如何保障各個(gè)復(fù)用組件底層依賴的統(tǒng)一、適配層接口的統(tǒng)一?雙端復(fù)用場(chǎng)景下,如何更好的做測(cè)試和監(jiān)控?雙端同學(xué)存在各自技術(shù)認(rèn)知的邊界,如何在出現(xiàn)問(wèn)題時(shí)快速排查、及時(shí)止損?
          3. 跨端復(fù)用流程規(guī)范問(wèn)題:新的技術(shù)革命,必然打破舊的秩序,在當(dāng)前跨端復(fù)用場(chǎng)景下,各種包括工程管理、代碼規(guī)范、分支管理、需求同步的問(wèn)題也會(huì)孕育而生,同需解決。

          3.2 跨端復(fù)用應(yīng)用架構(gòu)

          為了解決跨端復(fù)用在業(yè)務(wù)實(shí)踐中遇到的各種問(wèn)題,我們重新設(shè)計(jì)了跨端復(fù)用應(yīng)用架構(gòu),從架構(gòu)分層管理、復(fù)用方式設(shè)計(jì)、流程規(guī)范、質(zhì)量保障方面入手,重點(diǎn)解決跨端差異化、質(zhì)量隱患、流程規(guī)范各種問(wèn)題,并尋求復(fù)用的最大化和性能上的均衡。

          3.2.1 跨端復(fù)用應(yīng)用架構(gòu)演進(jìn)

          在這里,先貼出動(dòng)態(tài)的架構(gòu)演進(jìn)過(guò)程,讓大家有一個(gè)宏觀的認(rèn)識(shí)。我們先簡(jiǎn)單地描述下演進(jìn)過(guò)程,后續(xù)會(huì)基于最終的架構(gòu)圖再做詳細(xì)的介紹。大致演進(jìn)過(guò)程如下:

          圖6 跨端復(fù)用架構(gòu)演進(jìn)動(dòng)畫圖

          • 起初,客戶端分 Android App 和 iOS App 單獨(dú)開發(fā),引入 RN 技術(shù)實(shí)現(xiàn)了 Android 和 iOS 跨端復(fù)用,但是小程序端依然需要單獨(dú)維護(hù)迭代。
          • 為了跟進(jìn)一步實(shí)現(xiàn) RN-小程序跨端復(fù)用,我們接入了自研的 RN-小程序跨端復(fù)用框架,并基于框架的適配規(guī)范,以 RN 的基建為基準(zhǔn),打造出一個(gè)和 RN 基建統(tǒng)一接口的小程序適配層。
          • 完成小程序渲染器接入(MP-Render)和小程序適配層后,React-Reconciler 這一層就可以打通到小程序側(cè),實(shí)現(xiàn)了 React 代碼復(fù)用到小程序的能力。
          • 實(shí)現(xiàn) RN 與小程序間的復(fù)用后,就可以對(duì)存量的 RN 代碼進(jìn)行抽象、適配、整理,進(jìn)而抽取出一個(gè)組件復(fù)用層,這個(gè)復(fù)用層可直接供上層業(yè)務(wù)層直接使用。
          • 最后,為了解決跨端復(fù)用場(chǎng)景下各種流程、協(xié)作和質(zhì)量隱患,我們配套了相應(yīng)的流程規(guī)范和質(zhì)量保障措施。

          3.2.2 跨端復(fù)用應(yīng)用架構(gòu)整體介紹

          圖7 跨端復(fù)用應(yīng)用架構(gòu)圖

          整個(gè)民宿的 RN-小程序跨端復(fù)用架構(gòu)圖如上,我們按照從下到上,從左到右的視角進(jìn)行解讀:

          • 系統(tǒng)層:最底層是系統(tǒng)服務(wù),除了 iOS 系統(tǒng)和 Android 系統(tǒng)外,我們把小程序視為一個(gè)單獨(dú)的系統(tǒng)模塊。
          • 基礎(chǔ)服務(wù)層:系統(tǒng)服務(wù)之上是基礎(chǔ)服務(wù)層,這一層主要是集團(tuán)基于 Native 和小程序建設(shè)的基建,全公司通用,覆蓋了研發(fā)工程中方方面面的基礎(chǔ)服務(wù)。在此基礎(chǔ)上,我們?cè)谛〕绦蚧ㄖ幸肓嘶?react-reconciler 實(shí)現(xiàn)的小程序運(yùn)行時(shí)渲染器(MP-Render),這個(gè)渲染器能在運(yùn)行時(shí)動(dòng)態(tài)更新 vnode 以匹配編譯轉(zhuǎn)化的小程序 UI 模板,調(diào)用小程序原生 API,最終渲染出小程序組件,有了這個(gè)基于 React 的小程序渲染器便使得跨端復(fù)用成為可能。
          • 基建層:基礎(chǔ)服務(wù)層之上是基建層,這塊主要包括 MRN 基建和小程序適配層,我們以 MRN 的基建為標(biāo)準(zhǔn),適配出一個(gè)統(tǒng)一標(biāo)準(zhǔn)和統(tǒng)一接口的小程序適配庫(kù),通過(guò)這一層適配,上層可以無(wú)感知、無(wú)差異地以同一標(biāo)準(zhǔn)實(shí)現(xiàn)復(fù)用組件。其中適配層分為 2 塊,下半部分主要適配 RN 基礎(chǔ)服務(wù),上層是民宿業(yè)務(wù)獨(dú)立封裝的基礎(chǔ)庫(kù)和第三方庫(kù),這塊我們單獨(dú)引入一個(gè)名為 Mapping 的適配庫(kù)。一個(gè)獨(dú)立的適配庫(kù)可以讓 RN 和小程序在業(yè)務(wù)迭代和技術(shù)變革過(guò)程中相互獨(dú)立,互不干擾,如此就能保障技術(shù)的推進(jìn)完全不會(huì)影響業(yè)務(wù)的迭代。基建層的最上方是 react-reconciler,React 框架本身就是把協(xié)調(diào)過(guò)程和渲染過(guò)程分開的,react-reconciler 是實(shí)現(xiàn)跨端復(fù)用的核心,所以我們把它單獨(dú)展示出來(lái),它真正打通了客戶端和小程序的隔閡,只要有了一個(gè)獨(dú)立的小程序渲染器,就可以全面、無(wú)限制的把 React 代碼復(fù)用到小程序。
          • 復(fù)用層:基建層再往上是復(fù)用層,復(fù)用層主要以組件維度做復(fù)用,復(fù)用組件是基于存量 RN 組件做抽象和適配,然后抽取獨(dú)立出來(lái),復(fù)用層的組件以統(tǒng)一的標(biāo)準(zhǔn)和接口供上層業(yè)務(wù)使用。復(fù)用層是很重要的一塊,好的復(fù)用機(jī)制能幫助我們解決前面提到的產(chǎn)品差異化問(wèn)題和復(fù)用最大化問(wèn)題。這塊我們單獨(dú)放到 3.3 跨端復(fù)用方式設(shè)計(jì) 來(lái)詳細(xì)講解。
          • 業(yè)務(wù)層:復(fù)用層之上就是業(yè)務(wù)層,業(yè)務(wù)層的各模塊主要以頁(yè)面容器來(lái)承接復(fù)用組件,基于不同的端和產(chǎn)品差異,可以靈活、動(dòng)態(tài)配置頁(yè)面的組件來(lái)滿意業(yè)務(wù)的差異化需求。

          3.3 跨端復(fù)用方式設(shè)計(jì)

          差異化問(wèn)題,一直是跨端復(fù)用場(chǎng)景中的一個(gè)痛點(diǎn),雙端的產(chǎn)品上、平臺(tái)上、代碼上的差異如何妥善的處理、適配,也是我們一直思考的問(wèn)題。而好的差異化處理方案可以提升代碼的可維護(hù)性、降低質(zhì)量隱患、提升開發(fā)效率。我們從復(fù)用設(shè)計(jì)層面出發(fā),探索出頁(yè)面復(fù)用模式、組件復(fù)用模式、“組件+邏輯復(fù)用”模式等三種復(fù)用設(shè)計(jì)方式,并且根據(jù)不同的場(chǎng)景下采用不同的復(fù)用模式,可以較好地處理跨端差異化問(wèn)題,同時(shí)能兼顧效率提升、性能體驗(yàn)和可維護(hù)性。

          3.3.1 差異化下的復(fù)用方式

          我們自研的復(fù)用框架提供兩種復(fù)用模式,如下圖所示:

          圖8 小程序復(fù)用方式原理圖

          頁(yè)面復(fù)用模式:頁(yè)面模式基于頁(yè)面維度的,可以直接把頁(yè)面的網(wǎng)絡(luò)層、邏輯層、數(shù)據(jù)層以及頁(yè)面內(nèi)的組件集全部轉(zhuǎn)換復(fù)用,這樣可以達(dá)到復(fù)用的最大化,代碼復(fù)用率能達(dá)到 90% 以上,人效提升明顯。

          組件復(fù)用模式:組件模式是基于組件維度的,復(fù)用以頁(yè)面中的業(yè)務(wù)組件為目標(biāo),把頁(yè)面的所有組件抽象、解耦、規(guī)范化之后抽取為復(fù)用組件。組件模式只能復(fù)用組件內(nèi)代碼,對(duì)于頁(yè)面容器的邏輯交互、網(wǎng)絡(luò)層都需要小程序自己實(shí)現(xiàn),代碼復(fù)用率相對(duì)較低,但是組件復(fù)用更靈活、可控,可隨意插拔、拼接、定制。

          以下是兩種復(fù)用模式的優(yōu)劣分析。

          頁(yè)面復(fù)用模式

          優(yōu)勢(shì)

          1. 提效明顯:整個(gè)頁(yè)面包括所有組件、頁(yè)面邏輯層網(wǎng)絡(luò)層一并打包轉(zhuǎn)換復(fù)用,代碼復(fù)用率極高,開發(fā)效率提升幅度更大。
          2. 接入成本低:整個(gè)頁(yè)面直接轉(zhuǎn)化同步復(fù)用,無(wú)需小程序同學(xué)協(xié)助接入,減少雙端協(xié)助、接口溝通帶來(lái)的出錯(cuò)風(fēng)險(xiǎn)。

          劣勢(shì)

          1. 靈活性低:業(yè)務(wù)差異和小程序特性不易處理,雙端差異適配只能在 RN 上做,代碼易出錯(cuò),維護(hù)成本高。
          2. 性能劣勢(shì):整體頁(yè)面由 RN 轉(zhuǎn)換復(fù)用而來(lái),頁(yè)面一次性渲染,性能上會(huì)略差一些,而且做頁(yè)面級(jí)的性能優(yōu)化困難。
          3. 包大小風(fēng)險(xiǎn)大:整頁(yè)復(fù)用情況下包大小較大,且不能動(dòng)態(tài)調(diào)配(比如頁(yè)面內(nèi)某一模塊需求迭代較少,不想復(fù)用,但是頁(yè)面模式做不到動(dòng)態(tài)移除)。

          組件復(fù)用模式

          優(yōu)勢(shì)

          1. 輕便靈活:組件如插件般可隨意插拔、拼接、定制,可較好解決 App 和小程序雙端的差異性問(wèn)題,針對(duì)差異點(diǎn)雙端可以獨(dú)立實(shí)現(xiàn),提高項(xiàng)目的可維護(hù)性。
          2. 性能較好:頁(yè)面容器依然是小程序原生組件,如滾動(dòng)、滑動(dòng)組件采用原生可減少性能損耗,另外組件分布式 setData 渲染有更好的性能,不會(huì)像整頁(yè)一次性渲染導(dǎo)致 setData 數(shù)據(jù)量較大影響首屏加載性能。
          3. 性能優(yōu)化空間大:不會(huì)影響做頁(yè)面維度的性能優(yōu)化(如首屏優(yōu)先、請(qǐng)求前置)。
          4. 包大小可控:組件是否復(fù)用可以動(dòng)態(tài)調(diào)配,比如把頁(yè)面中迭代較少的組件不復(fù)用以減少包大小。

          劣勢(shì)

          1. 提效有限:組件模式只能復(fù)用組件內(nèi)的代碼,代碼復(fù)用率較低,頁(yè)面容器、邏輯層、網(wǎng)絡(luò)層小程序依然要自己維護(hù)一份代碼。
          2. 復(fù)用組件維護(hù)成本高:組件的接口要考慮組件升級(jí)迭代的兼容性、可維護(hù)性問(wèn)題,管理不當(dāng),容易產(chǎn)生質(zhì)量隱患。
          3. 接入成本較高:小程序需要實(shí)現(xiàn) RN 的頁(yè)面邏輯,然后按照組件接口進(jìn)行接入,有更高的接入成本。

          兩組復(fù)用模式各有利弊,頁(yè)面模式復(fù)用率高,但是靈活性低、性能欠佳;組件模式輕便靈活,性能可控,能較好的處理平臺(tái)差異化問(wèn),但是復(fù)用率低、維護(hù)成本高。我們?cè)谙胗袥](méi)有一種方案能保留組件模式的靈活性,又能降低組件維護(hù)成本、提高復(fù)用程度。在業(yè)務(wù)實(shí)踐中,我們探索出一套“組件+邏輯復(fù)用”的模式,可以較好地解決上面提到的問(wèn)題。

          3.3.2 差異化下的邏輯復(fù)用

          “組件+邏輯復(fù)用”模式依然保留組件復(fù)用的方式,但是在組件復(fù)用基礎(chǔ)上增加了邏輯層(包括頁(yè)面邏輯、網(wǎng)絡(luò)、數(shù)據(jù)層)的復(fù)用,這樣保留了組件靈活性,也增加了復(fù)用性。具體設(shè)計(jì)如下圖:

          圖9 組件+邏輯復(fù)用模式原理圖

          整個(gè)組件+邏輯復(fù)用模式設(shè)計(jì)圖如上,我們按照?qǐng)D片標(biāo)注的序號(hào)進(jìn)行一一解讀:

          1. 邏輯復(fù)用接口實(shí)例:在小程序的頁(yè)面容器中,通過(guò)注入的方式獲取邏輯層復(fù)用的接口實(shí)例,通過(guò)這個(gè)實(shí)例便可以調(diào)用接口實(shí)現(xiàn)獲取、更改、監(jiān)聽(tīng) Redux 的狀態(tài),實(shí)質(zhì)上就達(dá)到了邏輯復(fù)用的效果。
          2. 頁(yè)面復(fù)用組件集:頁(yè)面可以自由使用復(fù)用組件,復(fù)用組件可大可小,可以雖然拼裝布局,保留了組件模式良好的靈活性。
          3. 小程序原生組件:頁(yè)面既可以使用復(fù)用組件,也可以用小程序原生組件來(lái)實(shí)現(xiàn)小程序差異化的功能和特性,這樣能較好的處理雙端差異性。小程序原生組件可以通過(guò) 邏輯復(fù)用接口實(shí)例 來(lái)調(diào)用邏輯層功能,進(jìn)而達(dá)到邏輯復(fù)用的效果。
          4. 彈窗復(fù)用組件:彈窗復(fù)用組件和頁(yè)面復(fù)用組件同理,這邊主要說(shuō)明可以按照各類維度把復(fù)用組件分類,進(jìn)而更好的做復(fù)用組件管理。
          5. 復(fù)用組件庫(kù):復(fù)用組件庫(kù)的復(fù)用組件可多可少,可大可小,如果頁(yè)面雙端差異性小,一個(gè)大組件即可滿足。每個(gè)復(fù)用組件集外層包一層 Reudx-Provider 并設(shè)置相同的 Store,便可以和邏輯層自動(dòng)綁定上。因?yàn)?RN 組件本身就是基于 Redux 的,所以復(fù)用過(guò)程相對(duì)容易。
          6. 業(yè)務(wù)邏輯層:最右側(cè)的業(yè)務(wù)邏輯層可以簡(jiǎn)單理解成3塊,一塊是基于 Redux Store 的數(shù)據(jù)層,這里存放整個(gè)頁(yè)面模塊所有的數(shù)據(jù)和操作、監(jiān)聽(tīng)數(shù)據(jù)的接口,一塊是包含頁(yè)面內(nèi)所有網(wǎng)絡(luò)請(qǐng)求的網(wǎng)絡(luò)層,另外就是用來(lái)流轉(zhuǎn)狀態(tài)和處理復(fù)用的 Reducer、Redux-Saga,以及配套的各種工具類。業(yè)務(wù)邏輯層可以根據(jù)雙端的差異把 Reducer 與 Saga 分拆更小的單元實(shí)現(xiàn)差異化的邏輯復(fù)用,提升邏輯復(fù)用層的代碼可維護(hù)性。
          7. 封裝復(fù)用接口:業(yè)務(wù)邏輯層包含整個(gè)頁(yè)面的業(yè)務(wù)邏輯,只要針對(duì)性開放接口給小程序,讓小程序可能獲取、更改、監(jiān)聽(tīng) Redux 的狀態(tài),那實(shí)質(zhì)上就達(dá)到了邏輯復(fù)用的效果。開放接口給小程序有 2 種方式:邏輯 API 接口 和 Store。
          8. 邏輯API接口:基于 Store 給小程序提供小程序真正需要的邏輯 API 接口,通過(guò)這些 API 小程序可以來(lái)獲取數(shù)據(jù)來(lái)渲染 UI(如:渲染沒(méi)有復(fù)用的組件),也可以更新數(shù)據(jù),也能監(jiān)聽(tīng)復(fù)用組件內(nèi)部的數(shù)據(jù)變化。
          9. Store:把 Redux Store 暴露出去,小程序便利用 Store 實(shí)例可以通過(guò) getState、dispatch、subscribe來(lái)操作、監(jiān)聽(tīng)狀態(tài)機(jī)了,也就達(dá)到邏輯層復(fù)用的目的了。

          這種方案的優(yōu)勢(shì)很明顯,它保留組件模式的靈活特性,可以比較方便做差異化處理和性能優(yōu)化。而邏輯復(fù)用層把 Redux 包含進(jìn)來(lái)了,這樣不僅轉(zhuǎn)化容易、不易出錯(cuò),而且邏輯復(fù)用接口基于 Redux 的 Store,接口較好設(shè)計(jì),容易維護(hù)、不易出錯(cuò)。而對(duì)于邏輯層,可以根據(jù)業(yè)務(wù)上一些差異做 Reducer 與 Saga 分拆,把不需要復(fù)用的代碼邏輯排查在外,邏輯層復(fù)用也可以做到像組件一樣熱插拔,按需引入,這樣也比較好做差異化代碼管理,挺高項(xiàng)目的可維護(hù)性,同時(shí)也能優(yōu)先減少包大小風(fēng)險(xiǎn)。

          3.4 跨端復(fù)用流程規(guī)范

          為在代碼跨端復(fù)用過(guò)程中盡可能提升開發(fā)效率并避免引入質(zhì)量問(wèn)題,我們制定了差異化編碼規(guī)范、需求同步規(guī)范、復(fù)用組件規(guī)范等開發(fā)流程規(guī)范,以下將通過(guò) RN 到小程序產(chǎn)品需求同步過(guò)程進(jìn)行簡(jiǎn)單的介紹。

          圖10 跨端復(fù)用流程規(guī)范圖

          1. 評(píng)估業(yè)務(wù)需求是否需要同步

          針對(duì) PM 提出需要同步的需求,客戶端盡量將 RN 業(yè)務(wù)代碼復(fù)用至小程序,以提升開發(fā)效率。無(wú)需同步的需求將通過(guò)差異編碼規(guī)范進(jìn)行控制,避免同步至小程序后增加潛在風(fēng)險(xiǎn)與測(cè)試成本。通常可使用平臺(tái)判斷(如 iOS、Android、WX_Platform)的方式控制業(yè)務(wù)代碼是否打入復(fù)用組件包,也可通過(guò) module.rn.js、module.wx.js 不同后綴文件方式完成相同接口不同邏輯的實(shí)現(xiàn)。

          2. 評(píng)估是否有關(guān)聯(lián)依賴需求

          如明確業(yè)務(wù)需求需要同步,先判斷該需求是否有前置需求依賴,再評(píng)估技術(shù)方案。如無(wú)依賴可直接開始復(fù)用適配工作;如有依賴,需判斷前置需求能否一起同步或做適當(dāng)降級(jí),以此遞推,避免因前置依賴需求未同步出現(xiàn)不符合預(yù)期的問(wèn)題。

          3. 制定 RN 組件適配與小程序接入方案

          明確需求同步范圍評(píng)估工作后,需完成以下技術(shù)評(píng)估工作:(1)明確需求是否需要新建復(fù)用組件還是在原有的復(fù)用組件上進(jìn)行迭代。如需新建復(fù)用組件 NPM 包,需根據(jù)組件復(fù)用規(guī)范進(jìn)行技術(shù)選型,確定使用“組件+邏輯復(fù)用模式”、“頁(yè)面模式”還是“組件模式”,并制定相應(yīng)的復(fù)用組件接口協(xié)議;(2)明確該需求是否需要開發(fā) RN-小程序映射方法、組件,并評(píng)估相應(yīng)的開發(fā)量。完成技術(shù)評(píng)估后需提前與小程序側(cè)溝通接入排期。

          4. RN 組件適配開發(fā)

          客戶端完成 RN 側(cè)需求開發(fā)后,便可進(jìn)行復(fù)用組件適配小程序開發(fā)。完成適配開發(fā)工作后需在 RN 頁(yè)面與小程序 Demo 頁(yè)面中對(duì)復(fù)用組件同時(shí)進(jìn)行測(cè)試,避免在適配小程序過(guò)程中引入 RN 頁(yè)面 Bug。復(fù)用組件測(cè)試完畢后將 NPM 包以及相應(yīng)的接口文檔提供給小程序接入,但在打包前需嚴(yán)格審查當(dāng)前版本與上個(gè)版本間的 diff,避免不符合預(yù)期的代碼也被同步至小程序。

          5. 小程序接入 RN 適配組件

          適配完成后將組件打包提供給小程序側(cè)接入,接入后需在美團(tuán)民宿小程序環(huán)境下再次進(jìn)行自測(cè)。原則上客戶端同學(xué)提供適配好的 RN 組件后,由小程序側(cè)同學(xué)接入并測(cè)試,但我們也鼓勵(lì)客戶端在完成 RN 組件開發(fā)與復(fù)用適配后,一并完成小程序側(cè)的組件接入工作,這樣需求開發(fā)完整度更高,并能有效減少跨端開發(fā)下的溝通成本。后續(xù)隨著大前端融合推進(jìn),RN-小程序代碼復(fù)用率將逐步提升,客戶端(iOS、Android)與 小程序代碼將傾向由一名同學(xué)完成多端開發(fā)。

          6. RN 適配代碼合入迭代分支

          需求在小程序測(cè)試完畢后,將 RN 組件適配 Feature 分支代碼合入 Release 迭代分支,并在客戶端(iOS、Android)打包上線。

          3.5 跨端復(fù)用質(zhì)量保障

          跨端復(fù)用場(chǎng)景下存在包括復(fù)用組件接口兼容性問(wèn)題、組件間的依賴隱患問(wèn)題、測(cè)試和監(jiān)控的缺失問(wèn)題,以及故障排查困難等各種質(zhì)量隱患,我們?cè)跇I(yè)務(wù)實(shí)踐中,也探索出一系列解決這些隱患的質(zhì)量保障措施,包括組件接口維護(hù)、組件依賴管理、雙重自測(cè)卡控、異常監(jiān)控融合、雙端故障 SOP、跨端復(fù)用流程規(guī)范 。這些措施能有效保障復(fù)用場(chǎng)景下雙端的線上質(zhì)量,民宿業(yè)務(wù)在跨端復(fù)用推進(jìn)中,因?yàn)檫@些措施的保障護(hù)航,沒(méi)有出現(xiàn)任何的線上故障。

          1. 組件接口維護(hù)

          復(fù)用組件隨著業(yè)務(wù)迭代會(huì)不斷更新升級(jí),組件升級(jí)過(guò)程中便會(huì)帶來(lái)的組件接口、輸入、輸出的變動(dòng),進(jìn)而產(chǎn)生兼容性隱患,比如組件輸入?yún)?shù)類型變動(dòng),而小程序端或RN端沒(méi)有及時(shí)兼容或者未知曉,非常容易引發(fā)線上質(zhì)量問(wèn)題。為此,我們制定了組件接口維護(hù)計(jì)劃,包括復(fù)用組件接口規(guī)范、組件版本管理規(guī)范、組件接口文檔建設(shè)等。復(fù)用組件接口規(guī)范要求復(fù)用組件接口、參數(shù)必須嚴(yán)格按照規(guī)范來(lái),如參數(shù)類型使用基礎(chǔ)類型、只增少減原則、接口命名清晰、參數(shù)個(gè)數(shù)限制等等,減少雙端的接入組件難度,避免參數(shù)頻繁變動(dòng)產(chǎn)生質(zhì)量隱患。組件版本管理規(guī)范要求組件版本升級(jí)必須遵循語(yǔ)意化 2.0,并且有相應(yīng)的版本升級(jí)文檔。組件接口文檔建設(shè)也是很重要的一環(huán),每個(gè)復(fù)用組件都有相應(yīng)的文檔維護(hù),記錄參數(shù)的增刪改查,接入方對(duì)組件接口變動(dòng)一目了然,自然減少了接入風(fēng)險(xiǎn)。

          2. 組件依賴管理

          組件依賴主要存在兩個(gè)問(wèn)題,第一,復(fù)用框架本身也在不斷升級(jí)優(yōu)化、新的復(fù)用組件可能用新的編譯版本轉(zhuǎn)化而來(lái)并且依賴新的運(yùn)行時(shí)渲染器,但是舊的復(fù)用組件可能會(huì)出現(xiàn)不兼容問(wèn)題,因此我們開發(fā)相關(guān)的工具,如果組件依賴的運(yùn)行時(shí)渲染器版本和小程序內(nèi)置的不一致就會(huì)發(fā)出警告,提示組件兼容性問(wèn)題。第二,因?yàn)椴煌膹?fù)用組件來(lái)自不同的RN模塊,它們可能依賴不同版本的第三方庫(kù),容易產(chǎn)生版本不一致的質(zhì)量問(wèn)題。目前的解決方案是把這些依賴庫(kù)分別打入各自的包里,這樣復(fù)用組件間依賴相互獨(dú)立,互不影響。再結(jié)合 Tree-Sharking 的優(yōu)化,打入的依賴的真實(shí)包大小并不大,用小量的包大小換取更穩(wěn)健的質(zhì)量保證。

          3. 雙重自測(cè)卡控

          在跨端復(fù)用場(chǎng)景下,一個(gè)復(fù)用模塊的改動(dòng)要考慮雙端兼容和新舊版兼容問(wèn)題,相比與之前有更高的出錯(cuò)風(fēng)險(xiǎn),更全面的自測(cè)能幫我們盡早暴露問(wèn)題,減少故障風(fēng)險(xiǎn)。所以我們?cè)?App 側(cè)和小程序側(cè)做了代碼自測(cè)覆蓋率卡控,要求改動(dòng)代碼執(zhí)行覆蓋率超過(guò) 90% 才能提測(cè)和上線。復(fù)用組件既在 RN 側(cè)自測(cè)過(guò)一遍,在小程序接入后又強(qiáng)制要求再自測(cè)一遍,雙重自測(cè)卡控更能保障組件質(zhì)量和線上質(zhì)量。

          4. 異常監(jiān)控融合

          RN 和小程序側(cè)都有單獨(dú)的異常監(jiān)控機(jī)制,包括 JS 異常監(jiān)控、API 異常監(jiān)控、自定義異常監(jiān)控等。但是雙端的異常監(jiān)控機(jī)制差別較大,在復(fù)用場(chǎng)景下兩者交叉混用導(dǎo)致異常監(jiān)控體系混亂,上報(bào)數(shù)據(jù)格式、策略、日志不統(tǒng)一而造成監(jiān)控體系誤告、漏告、排查困難、運(yùn)維混亂等問(wèn)題。所以我們把雙端的異常監(jiān)控模塊打通,適配了底層異常上報(bào)邏輯,統(tǒng)一了雙端的上報(bào)規(guī)范,告警策略、日志、處理流程。異常監(jiān)控體系雙端融合后,異常上報(bào)、監(jiān)控、運(yùn)維都順暢許多,也幫我們發(fā)現(xiàn)不少的線上異常,是 RN-小程序跨端復(fù)用場(chǎng)景線上質(zhì)量的堅(jiān)固屏障。

          5. 雙端故障SOP

          鑒于雙端同學(xué)存在技術(shù)上的隔閡和信息不對(duì)稱,當(dāng)出現(xiàn)復(fù)用組件的故障或異常時(shí),如何快速排查問(wèn)題成為一個(gè)痛點(diǎn),小程序的錯(cuò)誤日志 RN 同學(xué)不熟悉,小程序同學(xué)不熟悉 RN 的業(yè)務(wù)代碼實(shí)現(xiàn),框架層面的錯(cuò)誤更難排查。為此,我們整體了梳理雙端故障 SOP,這里面包括常見(jiàn)日志分析幫助鑒別是復(fù)用組件、小程序端、底層復(fù)用框架的問(wèn)題和相應(yīng)的解決方案,同時(shí)開發(fā)了 Source Map 錯(cuò)誤反解工具協(xié)助RN同學(xué)反解小程序日志幫助快速排錯(cuò)等等。這些 SOP 和工具能夠在第一時(shí)間幫助雙端同學(xué)自主或協(xié)助排查相關(guān)故障,快速止損。

          6. 跨端復(fù)用流程規(guī)范

          流程規(guī)范包括前面提到的復(fù)用組件規(guī)范、編碼規(guī)范、需求同步規(guī)范、分支管理規(guī)范等等也是質(zhì)量保障的重要的一環(huán),它讓研發(fā)流水線每一環(huán)都有嚴(yán)格的法律約束,保障整條研發(fā)流水線最終能把完整的產(chǎn)品交付到用戶手里。

          3.6 成果

          RN-小程序跨端復(fù)用的設(shè)計(jì)方案在業(yè)務(wù)實(shí)踐中不斷完善,探索出效率相對(duì)最大化的復(fù)用模式。從開發(fā)效率角度來(lái)看,提升顯著。我們總結(jié)了代碼復(fù)用率與人效提升率來(lái)評(píng)估效率的提升,兩個(gè)指標(biāo)具體計(jì)算公式如下:

          • 代碼復(fù)用率:∑(RN 復(fù)用模塊代碼行數(shù)-模塊中 RN 與小程序平臺(tái)分支判斷代碼行數(shù))/ ∑(RN 代碼總行數(shù)+小程序原生代碼行數(shù));其中,RN 復(fù)用模塊代碼行數(shù)是根據(jù)框架轉(zhuǎn)換生成的組件來(lái)確定。
          • 人效提升率:∑(RN 開發(fā)耗時(shí) + 小程序開發(fā)耗時(shí) - (RN 開發(fā)耗時(shí) + 轉(zhuǎn)換適配耗時(shí))) / ∑(RN 開發(fā)耗時(shí) + 小程序開發(fā)耗時(shí));復(fù)用前需要RN與小程序側(cè)兩端的開發(fā)耗時(shí),復(fù)用后只需要 RN 開發(fā)與復(fù)用組件轉(zhuǎn)換適配的耗時(shí),根據(jù)復(fù)用前后的耗時(shí)可以得出人效提升率公式。

          根據(jù)轉(zhuǎn)換采用的模式不同,可以得出代碼復(fù)用率與人效提升率,如下表所示:

          從表中可以看出,頁(yè)面轉(zhuǎn)換模式復(fù)用了頁(yè)面與組件的代碼,代碼復(fù)用率可以達(dá)到 90% 以上;組件復(fù)用模式復(fù)用了組件與部分業(yè)務(wù)邏輯代碼,復(fù)用率也可以達(dá)到 76%。在人效提升方面,所有模式都能達(dá)到較高的人效提升率,代碼復(fù)用率越高人效提升率也越高,頁(yè)面轉(zhuǎn)換模式可以復(fù)用頁(yè)面與數(shù)據(jù)狀態(tài)處理邏輯人效提升比組件轉(zhuǎn)換模式更高。

          4. 總結(jié)

          民宿大前端團(tuán)隊(duì)為解雙端研發(fā)效率之痛,傾力而尋跨端之技,淺嘗百草、深諳其理而后自建之,舉偏補(bǔ)弊、終解跨端框架性能之桎梏,青出藍(lán)而勝于藍(lán)。而后踐于實(shí)業(yè),瑕弊昭然若揭。為此,重設(shè)框架以謀其變(復(fù)用架構(gòu)設(shè)計(jì)),尋之新式以盡其效(復(fù)用模式設(shè)計(jì)),立之新法以固其序(跨端復(fù)用流程規(guī)范),磨之利器以護(hù)其城(跨端復(fù)用質(zhì)量保障),至此成果初成。然朝夕變化不休,路漫遠(yuǎn)兮,吾當(dāng)持之求索以適其變、順其道??缍藦?fù)用前行之鑒,故記以文,望有啟示,文畢。

          作者簡(jiǎn)介

          凱林、森偉、熙辰、戈弋、少元等,均為美團(tuán)民宿前端團(tuán)隊(duì)研發(fā)工程師。



          瀏覽 45
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  自慰大秀 | 豆花视频操MM | 成人在线观看视频亚洲 | 成人国产免费 | 最新爱爱视频网站 |