引言
在上篇中,我已經介紹了美團點評的業務情況、大前端的技術體系,其中大前端的技術全景圖如下:

上篇重點介紹了工程化和程式碼質量的部分,工程化涵蓋了客戶端持續整合平臺-MCI、全端監控平臺-CAT、移動端整合日誌庫-Logan和全棧前端框架-Era。程式碼質量部分重點介紹了ESLint在大規模專案中落地實踐和移動端靜態分析工具-Hades。
在這篇文章中,我們將繼續介紹大前端技術體系中的跨平臺、UI元件庫和前端框架。
跨平臺
跨平臺動態化方案
跨平臺、動態化始終是移動網際網路時代永恆的話題,在效能體驗和研發效率之間不斷尋找平衡,誕生了一批批跨平臺動態化方案。

將業界主流的跨平臺方案整理一下,大致分為四個類別:
- 佈局動態化:主要依賴是客戶端的渲染能力,通過約定佈局配置的資料結構(例如JSON),可以後端動態下釋出局內容,客戶端解析然後進行渲染,從而實現一定能力上的佈局動態化。
- 虛擬執行環境:類RN、Flutter的解決方案,RN/Weex是通過JS來編寫前端程式碼,然後通過Virtual Dom轉換成Native介面元素進行渲染,達到了研發效率和效能渲染的平衡。Flutter在RN的理念上又邁出一步,將底層渲染引擎用C/C++自己實現,從而減少JS/Native之間通訊成本,而且統一了iOS、Android雙平臺的元件渲染樣式。
- 業務外掛化:在Android系統中,通過特有的外掛化能力,實現動態更新的能力,但是不能支援iOS,因此多用於Android系統中Hot fix。
- Web容器增強:本質都還是通過WebView來渲染、執行頁面功能,通過JSBridge來補強實現原生能力。可以通過本地離線包減少資原始檔的遠端載入,從而提高使用者體驗。
在跨平臺、動態化方案中並不存在銀彈,每個方案都存在一定的取捨,下圖就總結了各個方案在使用者體驗、穩定性、上線實時性、開發效率和遷移效率五個方面的對比總結:

每種方案都有優點和缺點,所以每種方案的適用場景是不一樣的。
- 佈局動態化:穩定性要求高,效能要求高,適合高流量的運營頁面
- 虛擬執行環境:可用於新業務探索,或者對於效能要求不高,業務迭代迅速的業務型功能
- 業務外掛化:Android熱更新,或者老業務的遷移
- Web容器增強:短期的活動、營銷類頁面,對於效能互動要求不高,使用週期不長的業務
美團的動態化方案
美團點評針對多種業務形態和各個業務的階段,沉澱了多種跨平臺解決方案,總結如下圖:

每種技術方案都需要周邊的配套設施來支援,從底層依次是執行環境、輔助工具和業務介面,所以在每種技術選型上都需要慎重,尤其對於中小型公司,結合自身業務尋找合適的技術框架來滿足業務開發最為重要,而不要僅僅為了追求最新、最炫而盲目採納新技術。
MRN
MRN-Meituan Reative Native,顧名思義可以知道這是美團基於RN框架進行封裝優化的一個跨端動態化框架,下圖可以看到MRN的整個周邊設施建設:

需要涵蓋完整的研發週期,例如釋出系統中需要能夠有打包MRN的能力、對MRN程式碼進行釋出和程式碼檢查;需要配套的開發工具,提供將原生程式碼轉換成MRN的工具;在業務開發中,首先要對MRN框架進行大量優化,對其效能進行優化,核心包進行拆包優化大小,抹平雙平臺的差異,同時也需要沉澱大量業務的MRN元件和原生能力的橋接;線上運維部分需要包括對異常錯誤、效能、穩定性等方面的監控。
Picasso
Picasso是大眾點評移動研發團隊自研的高效能跨平臺動態化框架,經過三年多的孕育和發展,目前在美團多個事業群已經實現了大規模的應用。

Picasso應用程式開發者使用基於通用程式語言的佈局DSL程式碼編寫佈局邏輯。佈局邏輯根據給定的螢幕寬高和業務資料,計算出精準適配螢幕和業務資料的佈局資訊、檢視結構資訊和文字、圖片URL等必要的業務渲染資訊,我們稱這些檢視渲染資訊為PModel。PModel作為Picasso佈局渲染的中間結果,和最終渲染出的檢視結構一一對應;Picasso渲染引擎根據PModel的資訊,遞迴構建出Native檢視樹,並完成業務渲染資訊的填充,從而完成Picasso渲染過程。需要指出的是,渲染引擎不做適配計算,使用佈局DSL表達佈局需求的同時完成佈局計算,即所謂“表達即計算”。

業界對於動態化方案的期待一直是“接近原生效能”,但是Picasso卻做到了等同於原生的渲染效率,在複雜業務場景可以達成超越原生技術基本實踐的效果。就目前Picasso在美團移動團隊實踐來看,同一個頁面使用Picasso技術實現會獲得更好的效能表現。
Picasso實現高效能的基礎是宿主端高效的原生渲染,但實現“青出於藍而勝於藍”的效果卻有些反直覺,在這背後是有理論上的必然性的:
- Picasso的錨點佈局讓佈局表達和佈局計算同時發生。避免了冗餘反覆的佈局計算過程。
- Picasso的佈局理念使檢視層級扁平。所有的檢視都各自獨立,沒有為了佈局邏輯表達所產生的冗餘層級。
- Picasso設計支援了預計算的過程。原本需要在主執行緒進行計算的部分過程可以在後臺執行緒進行。
詳細可以檢視參考資料[1]。
UI元件庫
beeshell - RN元件庫
為了進一步降低開發成本、提升產品迭代的效率,美團開始推廣使用 RN 技術。隨之而來,相關業務方開始提出對 RN 元件庫的訴求。2018 年 11 月,公司內部發起了 RN 元件庫建設,旨在提供全公司共用的元件庫。鑑於我們團隊在開源 beeshell 1.0時,積累了豐富的經驗,於是就加入到了公司級 RN 元件庫的專案共建中。完成元件庫開發後,我們決定將共建的成果貢獻出來,並以 beeshell 升級 2.0 的形式進行開源,共計開源 38(33 個元件與 5 個工具)個功能。在服務社群的同時,也希望藉助社群的力量,進一步完善元件庫。
beeshell 2.0 效果圖如下:

整體架構如下:

元件庫由 1.0 的一個專案演變成 2.0 的三個專案(版本),形成元件庫體系。具體包含:公司通用版本MTD、外賣定製版本Roo和開源版本beeshell。
beeshell元件庫使用了分層的架構風格,分成了介面層、元件層、工具層以及三端適配:
-
介面層。彙總所有元件,統一輸出,使用全部引入的方式,方便元件使用。另外,為了避免引入過多無用元件,引起資源包過大,也支援元件的按需引入。
-
元件層。細分為原子、分子、擴充套件元件。 與 beeshell 1.0 相比,我們對元件在更細的粒度上進行拆分。同時,層次劃分也更加精細、明確。如上圖 F 所示:基礎元件細分為分子、原子元件。這樣,元件的繼承、組合方式更加靈活,能夠最大化程式碼複用。而且,原子、分子、擴充套件元件,各層次元件各司其職,“關注度分離”,兼顧通用性和易用性。
-
工具層。與 beeshell 1.0 相比,工具更加完備。不但新增了樹形結構處理器、校驗器等;而且工具的獨立性更強,與元件完全解耦,與元件配合實現功能。 這樣,一方面,使得元件實現更加簡潔,提升了元件的可維護性;另一方面,可以將工具提供給使用者,方便使用者開發,提升元件庫的功能性、易用性。而且,工具與元件的解耦遵循“關注度分離”的原則。 三端適配。RN 在整體上實現了跨平臺,iOS、Android、Web 三端使用一套程式碼,但是在一些細節方面,例如:特殊 API 的支援、相對位置計算等,各個平臺有較大差異。為了更好的支援三端,保證跨平臺穩定性,還需要在這一層做很多適配工作。
除此之外,整個元件庫體系,還具備以下特點:更加完善的測試方案;豐富的程式碼示例;使用 TypeScript(以下簡稱 TS)語言進行開發,充分利用 TS 的型別定義與檢查;針對每個元件都有詳細的文件說明。
詳細可以檢視參考資料[2]。
Vix - Web UI元件庫
Vix是金融BU沉澱了Web前端元件庫,適用於美團金融的業務場景,基於Vue框架,服務了超過60個業務產品。

為了打造高效元件庫需要具備以下三個特點:
- UI 風格一致:只有 UI 風格與視覺側保持一致,高還原視覺稿,才能快速完成介面開發。
- 可複用性強:只有可複用性強,才能覆蓋更多場景,獲得更多收益。
- 簡潔易上手:只有簡潔易上手,才能讓更多人使用,創造更大的價值。
在元件庫建設過程中經歷了三個階段:產生期,發展期,優化期。
產生期主要是萌生了元件庫的想法,主要是為了解決元件複用和標準化的問題,同時當時開源專案定製化成本高,無法滿足需求。

在這個階段,不同的業務、設計團隊共同合作,制定視覺規範,從而沉澱通用的元件庫,這樣不同業務的開發同學就能夠採用元件庫實現標準統一的業務樣式。
發展期:Vix 如何打造可復⽤用性強的元件體系?

通過對功能點的梳理抽象出一個個原子單元元件,保證每個單個元件職責單一,元件對外介面一致。然後可以通過對元件進行組合,並且賦予業務邏輯形成業務元件。
優化期:Vix 如何讓開發者使⽤用簡潔易易上⼿手?

優化期主要讓開發同學能夠更加方便的使用Vix,於是從文件完善、提供示例、命名規範方面降低理解成本,通過引入簡單、配置簡單降低使用成本。
前端框架
mpvue - Vue小程式框架
mpvue 是一款使用 Vue.js 開發微信小程式的前端框架。使用此框架,開發者將得到完整的 Vue.js 開發體驗,同時為 H5 和小程式提供了程式碼複用的能力。如果想將 H5 專案改造為小程式,或開發小程式後希望將其轉換為 H5,mpvue 將是十分契合的一種解決方案。

Vue.js 檢視層渲染由 render 方法完成,同時在記憶體中維護著一份虛擬 DOM,mpvue 無需使用 Vue.js 完成檢視層渲染,因此我們改造了 render 方法,禁止檢視層渲染。熟悉原始碼的讀者,都知道 Vue runtime 有多個平臺的實現,除了我們常見的 Web 平臺,還有 Weex。從現在開始,我們增加了新的平臺 mpvue。
生命週期關聯:生命週期和資料同步是 mpvue 框架的靈魂,Vue.js 和小程式的資料彼此隔離,各自有不同的更新機制。mpvue 從生命週期和事件回撥函式切入,在 Vue.js 觸發資料更新時實現資料同步。小程式通過檢視層呈現給使用者、通過事件響應使用者互動,Vue.js 在後臺維護著資料變更和邏輯。
可以看到,資料更新發端於小程式,處理自 Vue.js,Vue.js 資料變更後再同步到小程式。為實現資料同步,mpvue 修改了 Vue.js runtime 實現,在 Vue.js 的生命週期中增加了更新小程式資料的邏輯。
詳細可以檢視參考資料[3]
Thunder - 資源離線化

Thunder 是一個漸進式資源快取與離線化方案。它通過瀏覽器本地儲存(localStorage/IndexedDB)快取資源,並且基於 service-worker 提供了離線化能力。Thunder 的接入方式簡單,不會侵入你的業務程式碼,僅需簡單的配置,即可讓你的 Webpack 專案享受高速資源載入。
- 漸進式 web 資源離線化: localStorage/IndexedDB 提供 JS 、CSS 離線化,ServiceWorker 全站離線化
- 增量更新:進一步利用快取,降低資源版本更新成本
- 資源異常自動 CDN 降級: 提供頁面資源載入穩定性
- CDN 劫持自動降級: JS 內容檢查校驗和,不符合自動切換降級 CDN
- 極速頁面載入效能: SDK gzip 後 8 KB, 結合離線化和增加更新,提升現代 web 應用載入體驗
- 接入簡單快捷:使用 webpack 外掛即可接入,不侵入業務
EH - 增強型Hybrid框架
EH - Enhanced Hybrid框架是美團金融研發的針對Hybrid業務場景的增強型框架。Hybrid實現雖然在研發效率上有很大優勢,但同時也存在大量的使用者體驗問題。

頁面白屏問題,無法做到原生頁面在切換時候的流暢度。白屏問題的本質原因在於原生頁面切換到Web頁面時候,Web頁面這時候還未載入渲染完成,因此會導致白屏問題。解決方案就是在當前原生頁面中通過一個不可見的webview將頁面進行載入,當webview頁面完全載入完成後通知原生頁面然後進行跳轉。

離線化技術,通過資源離線化,線上增量更新,實現頁面的載入效能提升,接近於原生的渲染體驗。
互動一致性,由於SPA的前端系統在頁面互動上難以做到原生一致的體驗,例如左滑回退操作等等,EH TransPage通過使用Native導航結合SPA頁面實現,在互動體驗上和原生保持一致。
一體化配置,前端頁面在Webview中缺乏對外部宿主的有效控制,例如導航欄樣式、狀態列文字顏色等等,EH Config提供一套介面可以讓前端頁面靈活進行配置,實現視覺一致性。
下圖是EH的整體架構圖:

技術團隊的前端體系
美團點評是一個多業務形態的平臺,各個業務發展階段和技術訴求都不盡相同,因此前端技術在美團點評各個團隊中百花齊放,誕生了眾多的解決方案。下面我分享一下幾個代表性團隊的前端技術體系。
金融團隊

上文中已經介紹過Vix元件庫和EH的Hybrid增強框架,這張圖更加完整的展現了金融團隊前端技術體系的全景,從開發、編譯、部署到線上執行等環節。
詳細可以檢視參考資料[4]
酒旅團隊

以上是酒旅前端團隊的技術體系結構圖,我們有兩種共存的專案型別(靜態化專案和服務端專案),靜態化專案是通過CDN進行承載,使用Vue進行功能開發,同時藉助移動端樣式元件庫提升開發效率,通過離線包機制和KNB (Native Bridge)增強頁面在容器內的表達能力,最後通過AWP(自建的靜態化釋出系統)可以高效的進行上線部署。
服務端專案不同的是使用NodeServer進行承載,前端通過AngularJS/VueJS進行功能開發,同時配合NGUI(AngularJS樣式元件庫)快速進行頁面搭建,Node端框架選用的是Express,服務的部署通過OPS(內部的運維釋出系統)完成。
人機識別服務是我們在前端角度設計和開發的一套安全機制,它包含前端SDK和基於Node實現的驗證服務,可以用於介面的防抓取、防止介面被第三方非法呼叫等場景。目前線上接入的業務平均攔截率在30%左右,介面TOP90的響應時間在9ms以內。
構建工具棧中我們通過Yeoman開發了團隊的腳手架,開發者可以通過腳手架快速的進行專案搭建和元件開發,通過Gulp和Webpack進行專案的構建和打包,NPM作為團隊統一的包管理工具,Sass作為CSS的預編譯工具提升CSS程式碼的可維護性,Babel作為ES6的編譯工具,ESLint作為團隊的程式碼檢查工具保證程式碼的規範一致,並且接入了Sonar。同時藉助一些開源的自動化測試工具提升開發階段的程式碼質量。
監控體系中Sentry用於線上錯誤資訊的收集和監控,Perf平臺用於Web端效能資料的收集,靈犀用於業務的統計和埋點,Falcon一方面用於Server的監控報警,一方面用於業務監控和報警(比如火車票的搶票失敗率和介面呼叫情況),PM25是我們自建的一套針對NodeServer程式粒度的開源的監控報警系統,用於確保線上Node服務的穩定性。
詳細可以檢視參考資料[5]
寫在最後
美團點評這幾年業務不斷擴張發展,基礎架構團隊不斷沉澱基礎能力夯實平臺能力,各個業務團隊也是各顯神通,不斷積累框架並在公司內外部進行推廣使用。
本文重點介紹了工程化、程式碼質量、跨平臺動態化、元件庫和前端框架等方面,同時也列舉了金融和酒旅團隊的前端技術體系建設情況。希望能夠讓你對於美團點評的前端技術體系有個大概的瞭解,當然這些僅僅基於公開資料整理而成,僅僅是整個技術體系的冰山一角。
最後,美團點評在大量招前端資深/專家工程師,如果有興趣近距離接觸美團點評大前端技術框架,歡迎私信給我進行內推。
參考資料
[1]Picasso開啟大前端的未來:mp.weixin.qq.com/s/lqyo7YzQ_…
[2]開源React Native元件庫beeshell 2.0釋出:mp.weixin.qq.com/s/5XgNTQdBm…
[3]用Vue.js開發微信小程式-開源框架mpvue解析:mp.weixin.qq.com/s/fY3HMV__w…
[4]美團點評金融平臺Web前端技術體系:tech.meituan.com/2018/03/16/…
[5]美團點評酒旅前端的技術體系:tech.meituan.com/2017/05/12/…
推薦閱讀
解密國內BAT等大廠前端技術體系-美團點評之上篇(長文建議收藏)

『奶爸碼農』從事網際網路研發工作10+年,經歷IBM、SAP、陸金所、攜程等國內外IT公司,目前在美團負責餐飲相關大前端技術團隊,定期分享關於大前端技術、投資理財、個人成長的思考與總結。