網易雲音樂(以下簡稱「雲音樂」)的前端團隊大概在 4 年前初具規模,4 年多的快速發展過程當中做了很多 0 到 1 的平台,造成了平台深井,比如研發的體系,部署的體系,監控的體系等,這些體系在雲音樂初期快速發展中起到了非常大的作用。但是隨着人員的更迭及業務不斷的發展,初期各自發展的垂直體系遇到了和產品後期同樣的問題,新增一個功能越來越複雜,涉及的鏈路越來越長,花費的代價越來越高,用戶需要在各自的平台跳入跳出,會有各種各樣的卡點,導致效率降低。如何串聯各平台場景,打破平台深井,這是雲音樂前端工程化面臨的第一個挑戰。
除去研發之外,所有的應用在上線前還需要經歷測試和部署以及上線後的運維,但是每種應用類型在每個階段的關注點不一樣,所依賴的服務也不一樣,比如 Node 應用的部署會依賴雲原生,但是 H5 的應用依賴 NOS 的靜態資源服務。如何使用一套架構支持不同應用類型的全生命周期發布,這是雲音樂前端工程化面臨的第二個挑戰。
雲音樂的業務從單一的播放器發展到社區生態的過程中,為了體驗和效率之間的平衡,湧現了多種多樣的應用形態,比如 H5 的應用、RN 的應用、中後台的應用、Node 應用等;為了一些極致的體驗,在 H5 下又細分離線和閃開,RN 又細分為拆包應用。這些不同的應用類型,工程規範不一致,腳手架也不一致,導致開發同學在上手時有一定的成本,也造成了維護上的困難。如何使用一套架構去收斂這些不同的研發體系,這是雲音樂前端工程化面臨的第三個挑戰。
本篇文章着重針對前兩個挑戰分享解決思路,我們也發起了一個代號為 Febase 的項目,這個項目目標是針對前端開發者,通過一站式應用研發平台,提升開發部署的效率和體驗,並且降低後續應用擴展的維護成本。
在 Febase 之前,雲音樂沒有完整流程的研發體系,部署前的流程基本都在線下完成,也沒有研發流程管控的概念,開發在即將上線之前,先將代碼合併到 master 再進行部署。這裡會存在幾個問題,一個是沒有統一的研發流程,無法做標準化;一個是有可能上線前的代碼存在問題,即便是經過了 QA 的測試,但是代碼已經合併到 master,有可能會讓其他人再次將錯誤的代碼帶上線。所以在產品層面上,我們設計了以應用為中心的全生命周期的研發工作流,將各自分散的體系按照研發的維護來串聯各平台的關鍵節點,每種應用類型都會經歷從初始化、開發、構建、編譯、部署、監控的流程,在各自垂直的鏈路上提供不同的差異化能力來完成,這樣既收斂了用戶的心智,也有了統一的工具產品來提升整體的基建水平。
我們先來看下 Febase 的整體架構,我們將各類公共技術所屬平台進行服務下沉,統一整個控制台入口,中間層通過自研的流程引擎來編排不同應用類型的部署流程,極大提升了後續新增業務類型的擴展性,前端通過微前端的方式進行自定義擴展,各業務組可以基於此擴展能力定製屬於自己的頁面,無須另起平台。
工程化里最重要的就是研發過程管控,由於 Febase 本身需要支持多種不同的應用,而每種應用類型的研發流程是不同的,下面展示了 GraphQL 應用和 RN 應用的差異。
可以看到不僅流程不一樣,UI 也不一樣,傳統的方式,硬編碼當然也可以解決問題,但是隨着應用類型不斷擴充,代碼可維護性會直線降低。
那麼如何能夠更好的使用技術手段進行解耦呢,我們想到了流程引擎,業界比較流行的流程引擎就是BPMN,也有對應的 Node 實現,但對於我們而言,一方面是場景沒有這麼複雜,另一方面還需要針對 UI 進行編排,所以我們選擇自研一個簡單的編排引擎,最終效果是針對上面的場景可以通過下面的代碼來實現,比如 GraphQL 的研發流程:
服務端側定義:
前端側定義:
只需要分別定義 Node 側和前端側就可以完成一種應用類型的擴展。在 Node 側的定義中endpoint指定了推進到該節點時需要執行的服務,比如 Review 節點,下面就創建了一個 CR 的流程:
Review 節點 Node 側:
前端側只需要通過 useWorkflow 的 hooks 傳入當前發布的 ID 即可獲取到流程進行到哪裡的狀態:
流程視圖側代碼:
通過自研的流程引擎,我們將流程狀態管理與具體的業務邏輯解耦,並通過流程引擎驅動前端視圖的變更,以此降低了業務邏輯開發的複雜度。
實際上在 Febase 的流程相對較為簡單,只需要支持並行、串行、跳過、回退能力即可,業界大部分流程編排都是通過 XML 文件來定義的,我們這裡採用了 JS 的方式,主要是省去了解析 XML 的成本,JS 的定義可以直接存儲為 JSON 格式;其次我們提供了前端的視圖配合套件,可以方便地進行前後端狀態的綁定。當用戶創建一次開發需求的時候就創建了一個流程,這個流程狀態關聯了流程的 ID,每當流程觸發了下一步,流程引擎就會執行對應的邏輯並更新流程的狀態進行存儲,回退同樣是對流程的狀態進行變更然後存儲。調試階段可以將狀態放置在內存中,如果是生產環境我們就將流程的狀態存儲在 MongoDB 中,因為流程的狀態非常適合文檔型數據庫的存儲。
那麼,流程引擎核心的一個點是如何處理需要掛起的邏輯的?很多節點的邏輯是需要三方服務來完成的,在 Febase 里是通過下面的方式:
引擎通知外部系統進行處理,通知時會傳遞 fid 和 pid,fid 是當前流程 ID,其中 pid 表示發出此 RPC 請求的 Stage 對應的是 process ID
外部系統通過返回 pending 狀態碼,表示該請求需要異步處理
引擎接收到 pending 狀態碼後,會設置自身狀態為 Suspended,並對當前的快照進行保存
外部系統處理完畢後,通過之前的 fid 和 pid 讓引擎繼續之前的流程
舉個例子,下面的代碼首先註冊了兩個 RPC 服務,然後定義了'quality'的並行的流程,分別是 Lint 和 Review,Review 這裡返回的狀態『suspended』,是因為 Review 是需要手動執行的,這裡就是一個掛起的異步操作:
上面的代碼執行將會產生下面的數據結構:
在執行後的數據結構里,因為 Lint 是直接通過的,所以 Lint 節點的狀態是'succeeded',Review 是一個掛起操作,所以 Review 的狀態是'suspended',當其他用戶進行 Review 通過的動作後, 就會通知流程引擎繼續根據這個數據結構進行後續的執行。流程引擎的執行其實就是遍歷這個數據結構調用服務的過程。
針對不同應用類型的發布,我們定義了如下接口,這樣我們就可以通過不同的實現來解耦掉部署服務的調用,這樣是面向對象中常見的操作方式。
DeployProvider 定義:
針對靜態部署我們實現上述定義的接口:
H5 部署:
這樣我們就可以通過統一的部署服務來屏蔽不同應用的差異:
部署服務:
Febase 除去為自身提供服務外,業務還有一些基於 Febase 本身的擴展,比如雲音樂桌面端的日誌平台,Febase 充當了元數據信息管理的角色;第二個是每個業務組或多或少有一些特定的業務訴求,這些訴求不適合通過公共的產品方式來承載,比如對於活動的監控,只是其中某個業務組的訴求,所以 Febase 通過開放能力來支持業務的二次開發,既降低了成本,又避免了多煙囪的產生。
對第三方平台,使用特殊請求頭。通過白名單的方式來指定開放接口,然後在每個業務邏輯實現中,根據請求來源,單獨地做權限校驗。過去這種職責不單一、面向過程式的鑒權方式,將會導致開放接口難以維護和擴展,無法承載多變的業務對 Febase 底層能力開放的訴求,我們的解法是提供聲明式的鑒權配置及多消費場景的統一認證機制,抽取單獨的接口網關。
在後端的接口中,用聲明式的方式描述接口所需的最低權限。在應用啟動時,會收集全部的路由 + 權限聲明,並存入數據庫中。並將路由與權限信息註冊至網關。由於路由與權限信息都做了入庫,所以也可以在管理後台中,對接口的權限做配置管理。對於多消費場景,統一使用 Febase 派發的用戶 Token 進行認證和鑒權。只有滿足權限要求的請求,才會打到 Febase 後端。
單獨的網關設計還有另外一個好處,就是第三方應用同樣可以將接口註冊到網關上,使用統一的鑒權服務,比如下方的雲鹿素材就屬於業務組維護的第三方應用:
除去接口外,Febase 在產品側提供了多個維度的自定義能力,分別是業務組 - 應用 - 概覽三級維度,下圖描述了 Febase 提供的三個擴展點:
業務組維度用戶可以在業務組維度插入多個自定義的頁面,用來管理團隊各項技術建設。
應用維度
同樣在應用維度,針對應用的特殊場景也可以定義,比如下方的活動策略就是專門為雲音樂的年度報告所創建的,也是業務組基於 Febase 的開放能力自行開發的。
概覽維度
用戶只需要在設置頁面填寫如下信息就可以導入一個頁面,平台支持微前端和 iframe 兩種方式:
其核心是藉助了 qiankun 的能力,只需要根據設定的 URL 來動態加載對應的資源然後渲染即可,關鍵代碼如下:
最終我們通過 Febase 使用聯合與開放的策略成功統一了雲音樂的前端基礎設施,覆蓋音樂事業部所有前端研發人員,日均構建次數 350+,活躍應用 220+;也提供了自定義的擴展能力,幫助業務最小成本地接入到 Febase 平台。後續針對應用類型的擴展也變得非常簡單,比如我們針對 GraphQL 提供的支持,基本復用了當前的平台能力。
如果你也面臨同樣的問題與挑戰,期望通過一種非常優雅的方式來解決,希望這篇文章的過程和實現能夠帶給你一些啟發。最後也感謝螞蟻提供的 Kitchen 插件,在產品交互設計上給我們提供了很多靈感。
作者簡介
葛星,網易雲音樂前端開發專家,前端公共技術團隊負責人,網易集團大前端委員會委員。十餘年從業經歷,曾是阿里集團最大的中後台設計系統工廠 Fusion Design 核心架構師,從前端工程化到全棧技術體系,以及前端智能化均有所涉獵。
在前端規模化 UI 生產領域及架構領域有深入的研究,包括但不限於設計系統、應用框架、低代碼搭建、微前端等。
GMTC全球大前端技術大會即將在今年9月落地北京,大會策劃涵蓋前端 DevOps、前端性能優化、IoT 動態應用開發、TypeScript、跨端技術選型、低代碼等 12 個技術專題,與BATT大廠專家線下交流,共同探尋大前端的未來技術方向。
點擊底部【閱讀原文】直達大會日程頁,感興趣的同學,聯繫票務經理:+86 18514549229
