百度外賣運營平台前端組件化升級之路
前言
看他人的套路,想自己的事情。今日早讀文章由 百度外賣新品類研發部門前端負責人@林溪分享。
據看朋友圈,@林溪本周6.18在【活動】「零廣告,全乾貨」iWeb峰會上海站,最後500位參會名額限免來襲!這個分享主題為《通用H5模版平台》,有興趣的童鞋可以去觀摩。
正文從這開始~
一、背景
隨著外賣業務的高速發展,加上外賣在擴品類方面的快速布局,大量的業務開發紛至沓來,運營後端的開發量更是暴增。由於頻繁迭代,運營後端架構表現出臃腫,各業務集中混布,耦合關係複雜,而且存在著大量重複性開發。後來,對業務進行了拆分,在架構層面更清晰,更好維護;引入了組件化解決方案,基於react和成熟開源的組件庫開發。大大提高了開發效率,但現在仍然面臨著一些問題:
開發量大:大部分產品還在迅速擴展階段,每一個用戶端功能迭代後面往往都需要運營後端的多個模塊的支持,運營後端開發在前端開發中佔比較大,工時較多。
重複開發:部分業務組件存在重複開發,業務組件間沒有共享,通用邏輯重複開發的情況也比較嚴重。
開發幸福感低:大部分業務較雷同,對資料庫增刪改查,重複邏輯開發,技術含量較低,屬於體力密集行勞動,開發者開發幸福感較低。
二、運營後端平台組件化演進過程
2.1 FIS時代
FIS是百度前端劃時代的構建工具,解決前端工程中資源載入(非同步、同步、按需、預載入、依賴管理、合并、內嵌)、模塊化開發、自動化工具、開發規範、代碼部署等問題。
基於FIS的模塊,非常適合於運營後端這樣的擁有多模塊的系統,首先命名空間對命名衝突是一種很好的隔離,其次FIS對模塊資源的優秀管理也讓不用命名空間下模塊的調用變的非常簡單,第三,FIS天生與PHP(ODP)結合得很好,伺服器環境部署和聯調都包含在FIS方案之中。隨著webpack等新打包方案的崛起,我們依然沒有放棄把FIS作為多模塊依賴和調用的解決方案,依然在使用FIS的編譯目錄結構,與我們的後端服務進行無縫結合。
FIS時代組件化的問題:
1、FIS時代的運營後端其實更多的是模塊化,而不是組件化,兩者的區別是模塊封裝的是大塊業務邏輯,基本上不能復用。只有一些通用組件進行了封裝,能進行部分復用,但也只限於代碼里看得見的組件,並沒有一個豐富的通用組件庫。
2、FIS時代的組件很多都是基於繼承模式,由於文檔不全,繼承最大的問題是很難直觀看到這個組件全部的介面和功能,往往需要不停查找父組件。繼承層級過深也會導致組件的可維護性變的非常差。
3、沒有豐富的基礎組件,也沒有組件共享機制,開發時往往還需要開發基礎組件,開發效率低。
React火起來之後,我們看到了React相比於依賴jquery的方案的強大優勢,果斷引入了React,開始了真正的組件化之路。
2.2 第二代組件化解決方案 - React來襲
React以絕對優勢席捲而來,擺脫了dom操作、狀態機、單向數據流讓我們更專註於實現業務邏輯,把我們從原先需要去實現的細節中浪費掉的時間給找了回來,而一些優秀的開源社區組件庫更多直接提高開發效率到一個新的數量級。
React時代的運營後端開發使用react+redux架構,如下:
React統一的生命周期構成,使得不同的人寫出來的代碼也驚人的一致,極大地提供了代碼的可維護性。而Redux的應用,使得視圖層,數據層分層更清晰。應用中所有的 state 都以一個對象樹的形式儲存在一個單一的 store 中。惟一改變 state 的辦法是觸發 action,一個描述發生什麼的對象。為了描述 action 如何改變 state 樹,你需要編寫 reducers。下面GIF描述redux工作原理:
第二代組件化方案的優點:
1、代碼可維護性好,基於Redux統一生命周期的組件具有統一的編碼風格,基於Redux的分層也使得代碼更結構清晰。
2、開發效率提升,使用第三方組件庫,大大節省了通用組件的開發時間,能將精力集中於業務開發。
3、組件復用性有提升,組件化思想真正的深入人心,組件的顆粒變細,可復用概率提高。
雖然開發效率提高了,開發幸福感有所提升,但並沒有完全解決營運後端開發需要投入大量人員的現狀,重複開發依然沒有得到徹底的解決。可以看到運營後台系統的界面還是很有規律的,其實MIS系統絕大部分界面也就是增刪改查。從現在的業務來看,增刪改查的需求,保守的說能佔到50%。而現在我們還在重複的寫著這些頁面,重複著實現增刪改查,重複著代碼複製,然後修改這樣的工作,所以分析系統特徵,將通用部分,抽象建模進行集成,工廠式量產替代小手工生產,提高人效,是我們一直要追求的目標。由此我們進行了第二代組件化方案的升級。
三、第三代組件化方案
就像蒸汽機的發明替代了手工勞動,使人們感到幸福,電氣時代替代蒸汽機,使人們得到享受,而人工智慧時代用機器替代人類枯燥的勞動,人們變成絕對的主宰;第二代組件化使前端進入電氣時代,下一個時代就是用智能去除枯燥重複的勞動。這是第三代組件化設計初衷。
3.1 目標
第三代組件化方案分三步走:
第一步:對通用業務模型頁面進行抽象建模,封裝通用邏輯,開發者可以配置和實現頁面中差異化部分,提高開發效率。
第二步:搭建組件共享和配置平台,通過平台工具可視化配置第一步中的頁面,進一步提高開發效率,通過組件共享機制,提高組件復用率。
第三步:集成更多的業務模型,積累更多組件,進一步完善可視化配置工具平台。
3.2 通用業務模型抽象集成
3.2.1 業務模型分析
目前運營後端頁面最通用的模型是檢索,檢索頁面基本上包含檢索區,操作按鈕區,數據表格區,分頁區。檢索、分頁的用戶操作都是一樣的,可以通用處理。不同的是檢索區,操作按鈕事件和表格的每一列。如果用戶能配置檢索區,操作按鈕區和表格列,還能指定使用的服務,那這種頁面就能抽象成一個大組件。
另一個通用模型就是增刪改查所用到的表單,通過配置表單項,生成表單,然後集中處理驗證、提交、清空等通用邏輯。
3.2.2 業務模型組件設計原則
1.約定大於配置。通過一些強制約定簡化配置。
2.保持配置項簡單、一致。這一點很重要,保持簡單,使用時就不用參照手冊,利於使用和推廣,但是配置簡單勢必會犧牲一下靈活性,還是易用性優先,兼顧一部分的靈活性配置。
3.2.3 檢索模型組件實現
最終模型代碼如下:
流程圖如下:
通過配置過濾項生成頁面,通過服務配置指定數據獲取方式。使用了業務模型組件之後,只處理自組件的用戶交互事件,頁面上其他事情就不用管了,比如檢索按鈕,清空按鈕,翻頁處理等都由大組件集中處理了。
交互圖如下:
父組件xp-searchPage負責主要的處理邏輯,子組件通過事件與父組件進行交互,父組件將最終數據通過事件通知給table組件,最終完成數據的渲染。
3.2.3.1 檢索組件使用配置
過濾項的配置:
constfilterComponents=[{
component: Input ,
label: 手機號",
name: shop_phone ,
value:utils.getQueryString( phoneNumber )
},{
component: MerchantStatus ,
label: 商戶狀態 ,
name: shop_status
},{
component: Button ,
label: 查詢 ,
name: submit ,
},{
component: Reset ,
label: 重置",
name: reset
}];
過濾項配置規範:
表格項的配置如下:
consttableComponents=[{
component: Text ,
label: 序號",
name: no ,
width:40
},{
component: Input ,
label: 項目編號",
name: task_no ,
width:120,
action:this.updateNo
},
{
component: Command ,
label: 操作 ,
name:[ 分配 , 廢棄 ],
action:[this.dispatch,this.drop],
width:100
}]
表格列配置規範:
服務配置:
filterChange(params,source){
console.log( source: ,source);
if(source== button ||source== pagination ){
letpass=true;
if(params[ shop_phone ]&&!/^1d$/.test(params[ shop_phone ])){
pass=false;
this.$alert( 請輸入正確的手機號");
pass=false
}
if(!pass)return;
returnapi.getTaskPollList(params);
}
}
filterChange需要返回 ajax請求的promise對象, 在filterChange中可以進行校驗。
3.2.3.2 檢索模型組件子組件規範
有了框架,我們需要具體實現業務的子組件,只要按照以下規範,所有的組件都能被配置為過濾項或者表格列組件,具體規範如下:
filter子組件
filter組件props 規範:
當過濾項值發生變化時,調用valueChange,valueChange可以調用多次,不同的key會產生不同的參數,例如,三級聯動的省市區選擇列表,可以調用三次。
this.valueChange( shop_province_id ,item_id);
this.valueChange( shop_city_id ,item_id);
this.valueChange( shop_town_id ,item_id);
系統在載入組件時會自動注入並處理valueChange,使子組件能和filter進行交互,當過濾區清空按鈕點擊時,調用reset實現組件重新初始化。
table子組件
talbe 列(單元格)組件props 規範:
雖然只有4個配置項,但也可以靈活使用,例如系統提供的Command列組件,name是一個數組,只要在編寫子組件時,能正確解析屬性值,name屬性可以隨意傳。
通過自定義filter組件和table組件,能實現任何個性化的定製,在電銷系統中實際使用了這套模型組件系統,也很好的滿足業務需求。
三、組件共享和配置平台
整體架構如下:
3.2.1 組件共享機制設計
(1)通過組件共享工具,對所需要的組件進行配置,每次提交代碼時自動上傳到共享平台,如果代碼有變更,會增加版本號。
(2)通過組件共享工具,能下載指定的組件代碼,開發者可以對代碼進行修改。
之所以沒有使用npm或者是git做為管理工具,是因為業務組件不同於基礎通用組件,業務組件往往分散,只需要零散的共享,npm或者git對於大量的共享需求來說,太過於繁瑣,工作量大,如果使用npm或者是git做為管理工具,開發者不管是為每一個業務組件publish還是創建git項目,都是巨大工作量,最終只能是導致開發者不願去做這件事情,平台得不到補充和更新,就會失去意義。
此外,npm或者git這一類的工具偏向通用庫的使用,版本概念強,業務組件通用性肯定不如通用基礎組件,所以必須滿足開發者能對業務組件進行少量的修改的需要,所以下載的是源代碼,弱化版本或者庫的概念,開發者可以自由修改,之後也能共享這個版本。
3.3.2 組件組裝工具
工具平台界面如下:
通過拖拽組件生成JSON,生成的json是一個樹形結果,組件層級關係和樹的子節點一一對應。
點擊代碼,展示最終生成頁面的代碼
3.3.3 組件組裝工具實現
拖拽
每一個基礎組件在渲染時都會被包裹一層容器,容器處理drag & drop事件,當drop 時,在對應的tree上添加或插入子節點。容器中默認插入一個佔位容器,處理drop事件進行其他節點的插入
渲染
深度優先遍歷樹節點,從葉子節點開始渲染,追層往上渲染,
渲染時,先載入組件,然後實時編譯改組件,進行註冊和屬性拼裝之後,動態創建改組件。
實時編譯
組件共享平台共享的組件都是源代碼,沒有編譯過,需要在用到的時候進行編譯,構建在VUE之上的第三代組件化解決方案使用了Vue官方提供的工具 Vuiefy來進行實時渲染。
四、結語
第三代組件化解決方案能徹底解決重複開發和開發幸福感低的問題,極大提高開發效率,提高人效。總結一下,優點如下:
(1)模型組件一次性封裝該模型通用邏輯,徹底解決重複性邏輯開發
(2)對模型的業務組件進行共享,提高組件復用
(3)通過可視化拖拽生成代碼,進一步提高開發速度
(4)組件 - 共享 - 復用,形成一個良性循環,越累積,平台功效越大
目前,我們搭建組件共享和可視化配置平台處於剛還起步狀態,後面還需要不斷完善和優化,讓第三代組件化解決方案發揮更大的功效。
關於本文
作者:@溪總
點擊展開全文


※從前端小白到技術專家,這裡有3點可執行的建議
※「大產品小細節」5分鐘了解格式塔原則
※Safari 11.0 已發布,新特性都在這兒了!
※三年來,從未如此隨性
※【第961期】圖解 React Virtual DOM
TAG:前端早讀課 |
※運滿滿運營平台的架構升級之路
※榮耀或因線下渠道架設推進手機區隔化運營
※運營取消流量漫遊費為5G網路逐步推廣鋪路
※「國際站運營」兩步設置好關鍵詞,平台流量倍增
※三大運營商7月起取消流量漫遊,省內流量升級國內
※《千年3》十周年再創運營佳績 盛大遊戲強化頂級IP矩陣
※全網免流!QQ瀏覽器又一次成功的運營升級改造
※牽手運營商發力線下零售 榮耀V20進入印度市場
※搶先打探!梁平百里竹海旅遊度假區5月亮相試運營
※5G為運營商網路重構注入加速度
※打通74個節點化運營,釘釘助跑車置寶數字化工作新賽道
※三大運營商7月1日起取消流量漫遊費 省內流量升級為國內流量
※交大海外產業升級IP運營研修課程
※推動全球創新 安創成長營運營五期共孵化海內外項目89個
※項目∣江蘇最大鐵路貨場開通運營;山東最大鐵路物流園將投運
※全球最大「超級船廠」正式開始運營
※多家房企改名去地產化 龍頭房企城市運營路徑漸明
※網約車平台運營模式升級,滴滴合作的司管、租賃公司的心躁動了
※共享汽車走到十字路口:追逐技術風口還是提升運營效率?
※滬江高級運營總監路盛華:如何通過精細化運營打造增長引擎