本文整理自美團技術沙龍第76期《大前端研發協同效能提升與實踐》,為大家介紹了美團到店前端研發框架Rome實踐與演進趨勢。
具體來講,本文首先介紹了Rome整體的工程生態、演變路徑、規模化升級以及工程框架外的開發輔助工具;第二部分,重點闡述瞭如何做框架度量和相關的業務實踐;最後做整體的總結以及對工程框架的下一階段的思考。希望能為大家帶來一些幫助或啟發。
2 工程生態、演進路徑與規模化升級
3 框架開發輔助
4 框架度量與業務實踐
5 總結及工程框架趨勢思考
1 背景介紹| 1.1 業務背景
首先介紹一下業務的背景,這裡主要從3個維度展開。第一個維度是組織維度,在立項之初,恰逢美團的多個事業群合併,因前端規模比較大,橫向的流動協同比較多(需要跨部門支持需求,進行跨系統協作等等) 。此外,美團到店事業群新人比例比較高,校招和新進員工比例很高,我們會幫助新同學快速融入團隊,需要完成一些較為基礎的開發工作。
第二維度是業務維度,美團到店業務迭代頻次比較高,基礎工程框架不僅要確保交付速度快,同時還對品質有很高的要求。
第三個維度是系統維度,因業務週期比較長,到店還存在大量的存量系統,需要考慮遷移升級和重構等問題,同時會有頻繁的系統交接。
| 1.2 技術背景
在Rome整體立項時,我們已經準備好了相關的基礎設施,包括發布系統的收斂、基礎架構,統一為基於S3(美團內部存儲服務)加動靜分離的技術架構,但是上層開發框架、組件類庫種類繁多且開發方式不統一。存在問題包括:整個團隊中人數比較多,學習交接、建設維護成本相對較高,而整體開發的效率比較低,跨團隊之間的工程能力也很難進行複用等等。
建設之初,我們基於純靜態S3(美團內部儲存服務)架構進行前端框架的建設,這源自於我們早期大量基於Node.js的前後端一體架構存在一些問題:首先,事業群早期以中後台場景業務為主,對頁面的秒開、SEO的訴求比較低;其次,當時Node.js生態基建還沒有那麼完善,前端同學需要做動態擴縮容、峰值流量處理等操作,整體的業務風險比較高。同時也存在機器成本高、開發人員能力要求高、招募難度等問題。
因此,在整體的建設思路和路徑上,我們不會建設類Egg.js這樣的前後端一體的框架;同時因為我們的框架層要解決研發流程不規範、交付品質不高等問題,也需要連動上下游的設計研發、CI/CD等系統形成一體的開發工程平台,而不只是做CLI工具。
2 工程生態、演化路徑與規模化升級| 2.1 工程生態2.1.1 降學習成本
框架約束
根據前文所述,我們一開始要解決的核心問題是學習成本,因此我們會做框架約束。
Rome在這一側的解法:
跨技術堆疊開發認知一致
在實際迭代的時候,到店內部一開始整體收斂到Vue技術棧,後來因團隊合併,又有了React技術棧。我們採取的第一個策略是把Vue和React整體目錄保持大家認知的一致,如下圖。而在真正開發的時候,例如配置子目錄SRC下,當一個同學一開始是偏Vue,但開發React需求的時候,即使團隊和業務有一些變動,TA也可以準確拿到專案快速啟動,接下來擺在TA面前的可能就是特定技術堆疊下,對於對應的API理解是否深入的問題,這部分同學自己就可以解決。
第二是我們會保證使用Rome開發框架的整體開發調試流程和體驗一致。如下圖,在Vue或React框架中同學專注業務開發就行,基本上可以不用關注工程框架的相關事情。例如Vite在Vue或在React指令和表現是一致的,同學可以透過一行指令直接開始調試對應項目並進行開發。
第三,我們的整體工程能力會進行高度對齊,如上圖所示。我們生態下80%的插件在Vue和React下,用法和表現完全一致,大家基本上不用關心這部分,當真正用到某部分能力,詳細看對應的文檔就行。
基礎基建對接
工程能力:一行程式碼引入公司基建(CDN容災)
當前端同學處理如CDN廠商故障等問題時,需要自行查找、學習和使用公司/開源的基建能力,解決成本較高,但在Rome開發過程中可以透過開閉式的配置一鍵CDN容災生效,如下圖,接入後會自動進行靜態資源的降級重試,當業務出現故障時(即下圖峰值部分),它會有一個明顯的資源加載重試,這就是降級CDN在生效;對業務同學來說只需配置框架需要哪個能力就行,其詳細配置如何注入大家並不需要太關注。
工程能力:一行程式碼引入公司基礎建設(警告監控)
業務開發以外的像警報監控,對同學來說,可能也要理解很多事。但在企業內開發,我們希望同學可以專注業務開發,像線上告警、日誌鏈路等出現問題,可以不用配置對應平台,我們用對應的項目Key就可以查到對應的錯誤總量、錯誤調用鏈路等。
工程能力:一行程式碼引入公司基礎建設(水印)
我們也可以一鍵完成對應的浮水印接入,同時開發配置時有對應的配置項智慧提示。各種開閉能力的屬性命名語意可能沒那麼清晰,可以透過如中的智慧提示一鍵跳到對應能力的文件位址,查看它的實作原理以及使用方法。
2.1.2 降建設成本
之前組織下建設的許多能力是偏小蘑菇的形式,「小蘑菇」的語意是整體工程能力的生命週期比較短,會進行頻繁的重複建構。但我們希望以一個大樹的形式建設,「大樹」的語意是我們可以透過跨團隊、橫向方式進行高品質的設計和建設,透過評審委員會把控整體的方案建設,把方案拆分到幾個階段,橫向團隊共建,共同完成核心能力,如、SSR等。
工程能力生態
如果大家對工程架構的建構能力感興趣,可以參考我們內部的效率、品質、體驗和領域實務進行對應分類的建構。我們透過第一線研究、能力盤點的方式建造了31個,在企業內進行建設時,有很多能力一開始可能本身成本就很高,比如統一基建接入等,大概需要30人力/個,而實際業務需求開發總共只有幾天時間,很難說服產品營運單獨抽出大量人力開發前端基建能力,這部分我們就以共建+橫向評審的方式,保證業務團隊可以攤平整體的建設成本。
典型共建案例
SSR能力,在休娛頻道的密室和優選團長端的訂單管理流量分別是百萬級別和千萬級別,整體秒開可以做到90%左右。
整個過程是Rome + Arche團隊共建並形成到店標準,業務統一落地,過程中有超過3個業務團隊參與了部分能力建設。
這裡簡單介紹下的方案流程:
首先是存取自動降級,使用者透過負載平衡命中對應的網關,命中對應的的Node ,這裡會有對應頁面粒度的SSR渲染函數,當使用者存取伺服器返回5.xx 狀態碼或逾時時會自動降級到CSR資源(SPA頁面);即使出現了極端情況,例如SSR 服務異常,我們也可以保證整體頁面可用,差異主要在SSR場景秒開~90%,CSR場景秒開~30%,兼顧了效能和穩定性的優勢。
其次是支援頁面粒度接入,在大型MPA 專案開發中,可以把某個頁面單獨設定為SSR,不必要求整個專案都是SSR工程,建置時預設會上傳CSR端建置資源,而針對SSR頁面會額外進行另外一份資源的構建,在部署SSR端、CSR端資源時分別部署,使用者存取頁面連結時,對應命中端或CDN資源。
支援自動擴縮容和流失渲染,對接公司Nest基建,支援業務無感知的峰值流量自動擴縮容;同時長列表頁面也可以透過串流渲染來降低TTFB時間。
2.1.3 提研發效率
編譯提速主要分兩個方向進行業務落地,分別是體系和Vite體系。
編譯提速- 體系最佳化
首先是體系,因為我們整體的技術棧分Vue和React兩部分,我們會抽一部分基礎的跨技術棧的配置,上層有不同團隊分別維護Vue技術棧和React技術棧的特有配置,中間我們會進行專項最佳化,包括像的開發最佳化、編譯壓縮器、SWC和等。
另外,我們做工具時,不僅要考慮我們本身建構工具比如,也要考慮如何和我們的CI/CD平台結合,如快取復用結合依賴安裝、建構工具做,在許多需求場景下,可以獲得耗時的10倍提升,CI/CD側我們也支援分粒度的構建,例如大型MPA做頁面粒度的構建等。
編譯提速- 開發時⼀鍵Vite
Vite主要是我們在開發時使用的,是建置時使用,除了一小部分增量專案的開發和建置都走Vite,大多數存量專案都是開發使用Vite保證效果,建置階段使用。
整體流程:首先是啟動,透過Vite,例如拉起頁面,抹平差異;環境變數的抹平,保證客戶端存量項目,將客戶端的環境變數注入到Vite端;對設定文件,大家原本在rome. .js中的配置也可以一鍵轉換為對應的Vite配置;在下層我們會做內建的技術堆疊插件,包括Vue2/Vue3 SFC+JSX,包括React的內建插件等;比較繁瑣的是生態相容,在公司內這部分的工作量比較大,像我們的一些SaaS的靜態資源的一些路徑等,包括之前我們存量這麼多年積累下來的公司基建,我們如何保證它能被注入到Vite端,包括組件庫按需引入,當一些模組例如.js的模組如何指向對應的目錄等,最後我們會屏蔽一些認知成本,把Vue、React和公司依賴包內置到Vite預編譯內容中。
依賴提速
主要分兩部分,分別是開發階段和部署階段。
首先會做工程框架自身Node.js依賴的預先構建,這部分核心解決的是Node.js端公司內外包資源的體積和遞歸依賴數量龐大的問題。依賴安裝的一個核心耗時其實是遞歸依賴龐雜,需要逐個安裝帶來的耗時,例如需要安裝A,其實A依賴了B、C、D、E、F、G,整體安裝耗時就會非常久,同時研發同學對Node.js包體積、依賴數量一般不如面向瀏覽器端投放的NPM包那麼敏感,這個時候預編譯就很關鍵。
其次是把整體的依賴環節套件管理工具切換到Pnpm。這部分經過研究(Pnpm、Yarn Berry、Yarn Berry with PNP等),判斷Pnpm是未來幾年的核心趨勢,同時可以穩定發展。內部建置了對應的套件管理遷移工具,來服務企業內幾百個、上千個專案。
在部署階段客製了Rome依賴安裝鏡像,鎖Pnpm版本和內建常用依賴、快取復用,它的整體邏輯是上一次需求迭代和下一次需求迭代可能依賴套件的變化沒有那麼多。我們在第二次發布的時候,如果能夠嘗試命中上一次的里的一些包,那麼第二次安裝耗時就會有一個比較大的提升。
| 2.2 演進路徑
第一階段的時候是強烈依賴和Vue技術棧的。直到2020年-2021年,像社區UI框架有Solid.js、、Vue3,構建工具有、、Vite等且發展勢頭也比較好,面向這個大趨勢,我們希望研發框架能夠分層過渡,不再和具體的UI框架、建置工具綁定:
首先最底層是差異機制,核心做插件的載入與調度;
中間層是建構工具的,這一層主要是分別結合、、等建構實現,支援大量專案;
上層、做框架拓展,各個業務能夠基於場景客製化自己的工程能力;
頂層是品牌指令(bin),這部分主要是企業內合作時業務方希望維持自己的品牌名。
範例如下圖右側,大多數情況下,我們有一個新的研發框架出來,只需要開發我們對應的語言特色的插件集合就行,底層插件機制+建構工具大家其實可以保持一致的。
| 2.3 規模化升級
框架價值=覆蓋範圍* 功能價值。我們的共識是建立的能力需要落地才能產生價值,核心是幫助大家業務低成本地享受好用的能力。
如下圖所示,是某一業務的升級成本圖,可以看到有100多個專案(成本平均值~5pd/專案),業務面臨幾百天的成本。對團隊Tech Lead很難說服業務產品營運業務階段投入升級。對第一線同學來說,雖然能力很多、很棒,但是升級風險怎麼處理:編譯提升10s,線上問題定位消耗一週。
這部分的我們給兩個解。
首先是提供遷移工具(非Rome到Rome專案):
巨石計畫做存量遷移時,一般同學下意識反應是透過Babel做靜態解析遷移,純靜態解析實測的遷移準確率在40%,也就說一個項目40%的事情透過Babel可以搞定。
第二階段是基於建構工具的依賴引用關係去做遷移,透過建構工具啟動時的模組工廠鉤子去產生依賴引用樹狀結構然後做遷移,得到遷移準確率約60%。
第三階段是動態分析結合AST靜態分析一起去做,在資料擷取階段透過建構工具的模組工廠鉤子、Vue/React實例化物件的路由/資料流配置去產生依賴圖結構,透過等工具進行靜態解析,不用Babel是因為有比較好保持樣式的程式碼回寫,檔案內容增刪改後寫回原檔案樣式不亂,同學在git diff時需要Code 程式碼就可以少一些,便於遷移影響範圍判斷。
最後配備上基礎公司基建做的一些依賴版本、體積、相容性檢測的品質工具,自動遷移了差不多有100多個項目,線上零Case。
另一個是做框架生態的大版本升級,假如一個季度推出來一個大版本,實際業務開發升級難度、成本就會比較大,業務可能也不敢升級,這時大版本升級就要提供關鍵流程自動遷移支援:
從Yarn到Pnpm的時候,會做幽靈依賴偵測,自動往Pnpm/src的幽靈依賴配置等;
也會做工程源碼比較;
建構配置,如前後框架無關的配置對比;
產物變動升級前後entry數量是否不一樣、產物有沒有明顯變大;
相容性檢測,升級前是ES 5+的程式碼,升級後到ES 6了,那也會出問題;
線上驗證等。
公司內部的一些標竿團隊都是由我們Rome團隊升級+寫報告,標竿業務由基建團隊升級的話,ROI可能會比較高,我們升級透過工具將我們的二次調整,整體成本可能會非常低,2 ~4h就可以完成一個中等存量項目,再由核心業務同學驗收、線上灰度跟進等。
3 框架開發輔助
我們Rome的工程開發輔助工具是基於IDE的。一般業界的開發輔助工具兩種形式,下圖是Vue UI和的拓展圖示:
| 3.1 為什麼要基於IDE?
理解:對於Web形式,業界以Umi UI(更先進)和Vue CLI為主,雖然它們都是基於Web實現,但出發點不太一樣,Vue UI核心是做體驗提升,支持工程創建CLI視覺化,工程配置分析等;但是UMI UI要服務公司內部,更多的是做提效,支援一些組的資產插入、執行工程任務如build/lint等。
基於Web做開發輔助工具
IDE側方案確實有UI互動受限、視窗面積、跨IDE開發成本等問題,因為同學在開發時,的面積就這麼大,每彈出一個就會侵占用戶的開發視窗,會比較難受。
選型原因:
| 3.2 提效率
提效率的一個例子是“一分鐘內部署”,這裡主要解決我們高頻的測試環境部署流程冗長問題。 2021年我們Rome⾮線上環境發布⼤概10W次/年,核⼼流程369s/次,如下圖所示:
透過我們的開發輔助工具,可以做到頁面粒度的CSR/SSR發布,同學不需要關注跨平台之間有哪些工作量,我們會在背後同步並且流轉節點,把原本我們要在研發流程中,企業內要做品質分析、規範卡控等部分做非同步,然後非同步進行觸發,整體的連結就可以保證一分鐘內完成部署。
| 3.3 提質
IDE可以做開發時品質偵測,開發時會有歷史線上故障的提醒。
哪些問題我們之前已經出過很多次線上故障了,在開發時就會即時檢測程式碼並提示這部分應該進行修復,否則後續可能會出現線上故障。
它和的區別:
首先是我們可以做規則的動態下發,研發規則配置,做管理中心化;
內容上我們也會支援故障包版本,例如業界之前出過幾次故障包問題,包括core-js、內部元件庫故障版本等;
我們也會把歷史業務線上故障分析出來並提示,點擊連結就可以跳轉詳細查看之前具體是出了哪次線上問題,是由什麼引起的。
| 3.4 平台流轉
我們內部研發時不僅要開發,還有設計稿,包括平台的流轉等,也會上下游聯動,保證設計可以快速到平台,平台可以一鍵打開本地VS Code,記憶歷史的倉庫和分支并快速打開,也可以快速流轉到設計平台,開發完返回剩餘流程。
| 3.5 文件提示
開發時也會給大家文件提示,只要研發人員託管到到店內部的知識庫,就可以在開發時,自動進行相關文件的配對和跳轉提示。
| 3.6 對接
得益於業界IDE標準的高度統一,一般只需一次開發,即可本地、雲端IDE自動安裝開發輔助,能力完全一致。
4 框架度量與業務實踐
上文中從接入公司基礎建設、編譯提速、框架大版本升級等方面提到了許多工程能力,過程中也建構了升級、遷移工具,而作為企業內框架,也有一些問題和指標需要考慮。
| 4.1 框架度量-核心問題
問題和指標
在業務規模不斷擴大、能力落地覆蓋範圍及用戶數量都在不斷增加的背景下,框架現狀衡量、框架如何發展等問題逐漸顯現:
Rome的用戶群從純B端業務到涵蓋B&C端業務,業務節點已涵蓋4個事業群、15個事業部;對比2020年,專案規模已擴大了11倍,公司內共落地1000+專案。
1. 如何判定標竿業務、框架能力支撐效果,如何持續快速統計使用者規模並做營運?
框架價值=覆蓋範圍* 功能價值。能力開發完我們需要盡可能清晰化並提升落地覆蓋,在統計運營上可以透過CI/CD平台發布過程數據、Git倉庫掃描數據、框架運行時數據打點、IDE使用數據來做框架能力和用戶規模數據採集;同時結合標竿團隊、標竿業務以組織維度框架生態能力最大提效數據,並對能力驗證和優化有正回饋,促進能力高品質、更大規模落地。
2. 哪些生態能力使用頻率高,哪些能力使用頻率低,哪些是安裝在專案中但沒有實際使用的?
面對已建立的生態能力,如果純粹從能力發展視角出發、缺乏有效的衡量體系,會導致有限的人力會被分攤到非常龐大的工程體系內:(1)已有的好能力因為沒有度量數據,感知弱,在人員變動等客觀背景下沒有得到持續足夠的推廣導致好能力沒有獲得足夠的落地,導致收益低於預期。 (2)初期能力建置完後產生持續的維護成本,對部分使用率低的能力無法感知,未及時做出關鍵判斷,產生一部分人力浪費。 (3)對存在優化空間的能力,由於未及時拿到使用數據,不了解落地問題,能力未得到持續驗證和優化而導致收益不達預期。
3. 框架如何從產品角度量化價值?
從人力節省、品質、縮短交付週期等方面建立有效的產品價值衡量體系,對齊框架年度輸出指標並持續運作。
4. 下個階段框架發展方向與重點是什麼?
不變的是要深入結合業務架構重點支撐階段核心業務場景,緊跟社區做一些先進能力,同時需要透過資料來輔助判斷階段重心是提升框架核心能力覆蓋率,還是要建立新能力。
5. 框架面向使用者群體的客服成本是多少?如何降低?
收集客服數據,沉澱高品質的FAQ,確保增量問題不被重複客服,引入AIGC智慧客服等方式降低增量能力客服成本。
| 4.2 框架度量-全景建設
解決思路
統一定義並梳理指標來源,結合上下游平台提取資料、對缺失資料收集並持久化,透過快照等形式完成資料層聚合和差異抹平;中間層會按照定義的大盤指標對資料進行統計擬合校準,包括專案覆蓋率、核心能力使用率、存取率、研發環節效率等等;上層會按不同的業務部門、時間區段等提供可切換的覆蓋率、效能、品質等數據看板。
資料來源層:
資料統計層:
大盤指標層:
交付(各模組的數據看板):
營運模組:
| 4.3 業務實踐
整體Rome業務實務如下圖:截止2022年,落地了1400多個工程項目,資產庫的數量有100多個,到店多數Web項目是用Rome開發,大家打開美團App,可以看到到店業務H5頁面都是透過Rome進行開發的,有B端系統、C端的H5,還有我們美團內部的React 。
5 總結及工程框架趨勢思考
工程框架不止於CLI。要從需求交付的角度來做框架,整個工程連結可能涉及應用建立、應用認證、開發基建配置、依賴安裝、編碼、Mock、調試,包括提交Lint、還有Git、、Int、Build、、灰度、等等。
我們要核心關注高頻的、規模化、價值比較高的環節:
依賴安裝環節,因為本地開發和線上部署都會使用到,如果這部分是目前核心的耗時點(發布總300s,依賴安裝100s),下個階段建置就可以先放一放,把依賴環節的優化提上日程;
開發編譯環節,很多時候開發環節我們提升了50秒,看起來好像沒有那麼高,但我們團隊如果是1000人有幾千個項目,調試編譯頻次是很高的,全量落地後規模化效果就會非常強;
發布鏈路層面:交付鏈路中涉及整個研發的全部上下游,單純做單點的工程優化(如本地構建優化)效果不一定好,可能到後來只是在卷幾秒的差異。部署階段依賴、建置快取復用可能可以直接降低10min/次;另外部署時管線節點非同步觸發、測試環境聚焦提速快速看到效果,線上再補充管理所需的品質分析、卡控等
鏈路流轉環節:工程框架和上游的設計協作平台怎麼流轉、下游如何和部署平台聯動,他們的耗時可能也比較高,這部分也需要關注,因為對使用我們這套工具的同學來說,不關注這個能力是誰提供,而是我們在開發需求的時候,他明顯會感覺到你們整體提供的這套產品,我用起來很難受,可能不一定是工程框架部分,單體都不錯,一起用就是不夠順滑。
未來趨勢(個人階段觀點):
第一方面是工程框架要做開發連結的深度整合,可以類比業界的,我們企業內也可以類比這些成熟的像SaaS產品去做;
第二方面是先前提到的Rust基建、建置切換/Vite、輔助開發工具,確保生態完善,公司內可以平滑升級;
AI時代:編碼;如何結合公司內AI基建把歷史業務範本、元件庫、資產庫做提示產生是一個可以結合的點(框架有相對嚴格的資產生產結構規範,可以提升下游編碼時資產消費準確率);透過知識庫問答降低技術項目的客服成本等。