當前位置:
首頁 > 科技 > SparkUI:一個可供參考的前端開發實踐

SparkUI:一個可供參考的前端開發實踐

寫在前面

SparkUI 是一套完整且靈活的前端開發解決方案。該方案基於 React,由 Modula 應用狀態管理框架、一系列可重用的前端組件、以及構建 SPA 所需的各類支持庫組成。該方案重視可重用性、靈活性、可測試性以及開發效率,解決了前端社區常見的一些針對商業前端應用開發的痛點,如複雜狀態、Side Effect,組件拆分等,更在工程實踐、文檔化、本身代碼質量等方面達到較高標準,為前後端分離架構下的商業前端應用開發提供了堅實的基礎。目前 SparkUI 已成功應用在 FreeWheel 的前端項目中。

Spark UI 的誕生和演進

技術選型

FreeWheel 產生升級原有前端框架、開始重新設計 SparkUI 的想法大約始於兩年前。2015 年 7 月之前,FreeWheel 其實已有一套基於 jQuery 的前端開發框架,但由於當時 jQuery 的版本較老、技術棧陳舊、整個框架維護不佳,而且缺乏一套可供新同事學習的文檔,再加之 React 的興起,因此我們決定對原有前端框架進行升級。

另一方面,縱觀整個大局勢下,也有越來越多的互聯網公司都在轉向 React.js 去開發前端組件,除了性能因素外,很大一部分原因是用 jQuery 去寫很複雜的 DOM 操作,後期代碼會變得越來越難維護。

當時,JavaScript 框架中的「當紅者」除了 React 外還包括 Angular、Vue 等,我們的前端團隊主要對 React 和 Angular 兩者進行了技術選型的評估。評估的各項指標顯示,React.js 相對 Angular.js 的學習曲線更低,而且也較為符合我們當時的基本想法——使用組件化的設計思想,所以,基於 React 開發前端開發框架的行動也隨之展開。

FreeWheel 新老前端框架對比

迭代升級

FreeWheel 真正開始啟動 SparkUI 是在一年半之前,這一年多也經歷了幾次比較大的迭代,從最初的 0.X 版本到 Spark 1.0 的版本,大概是以下幾個逐步過渡階段:

0.X 版本主要是基於 Flux 的應用狀態管理框架。因為 React 本身只是在 MVC 架構下的視圖這一層,只能用來構建視圖組件(View Component),本身並沒有狀態管理的能力,而頂層組件的狀態也愈發難以維護,因此當時的 React 生態圈中,React+Flux 這類比較經典的架構在 FreeWheel 之外的其他許多公司也得到更為頻繁的應用。

但伴隨 FreeWheel 前端應用過程中頁面交互越來越複雜,組件繁多的同時,各個組件狀態又非常繁雜,而且狀態間存在諸多映射關係,因此 Flux 在狀態管理中的表現也越來越滿足不了我們的需求。當時開發社區中出現了新的狀態管理的理念和技術——Redux,所以在從 0.X 版本提升到 Spark1.0 的過程中,我們在狀態管理設計的思想上也從 Flux 切換到了 Redux。

1.0 版本之後已經全面引入了 Redux 作為狀態管理的框架,但這並不意味著是完全照搬 Redux 的狀態管理機制。實際上,FreeWheel 僅僅用到了 Redux 基本狀態的存取介面和一些基本工具,在此基礎上, SparkUI 框架的核心模塊(其內部稱之為 Modula)在整個狀態管理中扮演了重要的角色,這其中也引入了諸如對象樹(Model Tree)這類的概念——因為在 Redux 中的狀態並沒有層級,而都是平行展開,但 FreeWheel 的應用中,一個對象可能存在非常複雜的層級結構,所以需要引入 Model Tree 對應用數據進行集中管理(Modula 相關設計理念將在後文中具體闡述)。

各階段中的應用狀態管理框架對比

除了狀態管理框架的調整之外,1.0 還引入了「函數式編程」的理念。所謂的「函數式編程」理念,是將在框架內部狀態的流轉完全用一種函數式的編程方式來實現。「函數式編程」最大的優勢,就是把一個程序動態運行的過程以一種函數的方式來將其抽象。如果狀態扭轉過程是一個函數的話,其實能夠保證傳給函數的原始對象的狀態不被改變,只是函數以新的狀態輸出。當一個應用比較複雜的時候,這樣能夠保證高效地跟蹤和管理應用狀態的改變。在 SparkUI 框架里,它也正作為一個基本的編程範式在使用。

同時,社區對「函數式編程」中 Side Effect 的作用一直有不同的聲音,但在實際應用中,我們發現 Side Effect 很難避免。比如說兩個組件之間在操作上存在關聯性——在一個 Grid 里操作完之後勢必要影響另外一個 Grid 的展示或行為,這個過程我們也是通過 Side Effect 來支持的。

因此可以說,Spark1.0 基本完成了對 0.X 版本的一次徹底的革新,但同時也導致原有產品中使用 0.X 的頁面和應用需要切換到完全不同的 API,這個過程也成為我們的一段重要經驗。之後框架的升級改造,我們堅持的基本原則是,所有的改變都是以向後兼容(Backward Compatible)的方式修改,給應用方提供平滑過渡的過程。到目前為止,1.0 版本的整個框架處於相對比較穩定的狀態,也已經在我們的生產環境里廣泛使用。

SparkUI 架構整體解析

SparkUI,可以理解為我們所謂的分層設計理念,整個 SparkUI 的架構和功能如下:

最底層就是 React 提供的 API,主要提供了基本組件的創建,包括生命周期管理的 API 等等。

接著在此之上封裝了 Modula 模塊,Modula 模塊主要是做應用狀態的管理,其本身還是使用了 Redux 來進行實際狀態的存取和事件的分發, 並利用 Immutable.js 來保證對象樹(Model Tree)的不可變性。

Modula 之上提供了一部分狀態管理中所用到的、做 SPA(Single Page Application)所依賴的工具。

這層工具之上是 SparkUI 的組件庫。因為 FreeWheel 當前主要以商業應用為主,其特點在於界面的變化和演進相對而言會更慢,但卻特彆強調新、舊界面間的高度一致性。所以我們在應用中抽象出了前端的組件庫(比如有稱之為 Grid——高度定製化的一種表單的組件等),而所有的應用又會利用這些組件實現它們各自的功能。

SparkUI 框架

Modula 模塊

SparkUI 框架的設計過程中其實吸收了很多 Redux 狀態管理的思想,現在也是使用了 Redux 來進行應用狀態的存取和事件的分發,但和 Redux 最大的區別在於,狀態管理複雜程度以及應用狀態數量不同,其管理思路也具有一定的差異性。

上文中提到的 SparkUI 框架核心模塊——Modula 實際上就是基於 Redux(但並不限於 Redux)的管理,它與部分 Redux 生態(如 Redux-devtools)兼容,且已完整封裝並隱藏了底層的 Redux。下圖簡要介紹了 Modula 與 React、Redux 的關係:

Modula 應用狀態管理框架

例如,在 Redux 里,應用狀態的結構完全是平展開的,不存在任何的層級關係,因為缺乏一個對象化的組織,所以要在狀態眾多的情況下,在 Redux 的 Store 上找到某個狀態就只能依靠純記憶。而 Modula 引入了對象樹(Model Tree)後,所有的狀態都可以被對象化,即通過預先定義好的結構來組織狀態。儘管是比較複雜的組件,在頁面上的展示可能也只是一個表單或 Table。

如果給這個 Table 設定一個較為複雜的狀態——加一個搜索條,搜索條本身有簡單搜索和複雜搜索的區分,上面還有複雜的工具欄、動作條,其本身或許還需要支持翻頁等。如此多的狀態之下,用 Redux 的方式可能會有好幾百個狀態在一個 Store 里,於是管理起來就會非常困難;但 Modula 就可以組織得更好,下面是 Modula 主要的設計理念:

Application State=Initial State+Deltas,其中 Delta 是由 Actions 觸發的(借鑒 Flux, Elm);

Application State 可以由一棵 Model Tree 來描述,這棵樹的每個節點都是一個可以描述有效業務實體的 Model(借鑒 Redux,Elm);

由一個給定的 Application State 到另一個 State 的 Transition 可以由 Model Tree 提供的 Reactions 所描述,一次成功的 Action 到 Reaction 的匹配會將 Model Tree 演變為下一個狀態(原創);

Side Effect 是上述 State Transitions 的結果,它包含了一個更新的 Model 實例,以及零至多個 Callback Functions(借鑒 Elm);

對於 Modula 中 Side Effect 問題的處理,Modula 模塊中的 Receiver 可以返回 Side Effect,一個 Side Effect 可以是 Sender 或 Bubble Event 的引用,也可以是一段匿名函數(箭頭函數);List-A 讀取完成時會根據 List-A 中包含的 ID,自動觸發讀取 List-B。

所以目前在狀況管理上,Modula 相對於 Redux 會是比較適應複雜前端狀態的應用改進。

前端路由框架 Spark Router

此外,為了能夠支持構建典型的 SPA,我們開發了一個叫 Spark Router 的組件。它主要也是基於 Modula,相比於 React Router(其狀態並不存儲在 Redux 的 Store 上),Spark Router 里的狀態管理能夠和應用中其他部分的狀態管理採用同樣的機制。

此前,應用狀態都分散在 React Router 的 State 與 Modula Model(Redux state)里,兩者經常遇到同步問題,我們的解決方案是將路由相關的 State 也合併進 Modula 中。因而,Spark Router 主要是針對 Model 配置路由,Component 可根據 Model 切換相應界面,這樣就不必再在 Spark Router 的狀態管理和應用中其他部分的狀態管理之間添加同步設計,也讓程序變得更簡單。

SparkUI 當前的應用

SparkUI 目前已經在 FreeWheel 的生產環境中使用了超過一年的時間。我們內部幾乎所有的 UI 產品都開始在使用 SparkUI。但現階段還仍處於從舊有實踐過渡到新的基於 SparkUI 實踐的過程。

我們之所以會自己設計和搭建基於 React 的前端 MVC 解決方案,也在於 FreeWheel 的系統是廣告資源管理系統,該系統的客戶群體大多有非常複雜的工作流,並且是要通過 UI 來實現,因而導致了前端的應用狀態多且複雜。所以,SparkUI 框架的特點,或者說其應用場景即:擅長於用來構建有比較複雜的前端狀態的應用。

我們在實踐過程中也借鑒了很多業界比較好的實踐,包括 Redux、Mobx 等,而且能被重用的東西我們都盡量重用,比如 Elemental 這類基礎組件,這樣可以在很大程度上降低使用者在 SparkUI 上需要的額外學習成本。此外,我們專門為 SparkUI 做了一個 Documentation Portal,其中有非常豐富的演示能幫助需要使用 SparkUI 的同事來學習。目前,在 FreeWheel 內部,前端團隊會定期給其他團隊做使用交流和分享,並及時同步最新的一些改進。

SparkUI 目前還只是供 FreeWheel 公司內部使用,暫未開源。但據了解,FreeWheel 和其母公司 Comcast 都非常鼓勵開源,目前也已開始對開源 SparkUI 走相關法務流程。FreeWheel 首席架構師張晗表示:「SparkUI 可能並不會全部開源,如組件庫這類屬於產品特定需求的部分會被拿掉,像 Modula 這樣的通用模型部分則會屬於開源的範疇。如果你的應用需要複雜的前端功能,特別是需要對具有相互關係的狀態進行較多維護時,就可以考慮使用我們的 Modula。」

SparkUI 的未來規劃

首先,我們目前需要對框架核心的升級進行性能優化。雖然 React 框架本身的性能也在不斷優化,但它其實並不以性能見長,影響性能很重要的一點就是狀態變化的計算,根據狀態變化的計算來重新渲染頁面。尤其當狀態比較多的時候,此類檢查就會比較費時。對此,我們會提出並引入一些標記方式,通過在對象樹(Model Tree)上標識一個範圍,只要在這個範圍里的子狀態被更新,服務狀態所對應到的視圖(View)就需要重新被渲染(Render)。

其次,我們還在不斷完善單頁 Web 應用的資質。因為 FreeWheel 在做新的前端框架以及前端產品的升級過程中也同時在做前後端的分離。同時,我們的業務系統也做前後端的分離。所以說我們也希望把所有的展示邏輯、非數據邏輯都盡量地移到前端實現,最終整個應用可以變成 SPA。目前,我們已經有對路由、國際化的支持,現階段還在開發許可權模塊,目前的許可權控制是在伺服器端,接下來的目標是增強對許可權控制、會話(Session)的管理。

今日薦文

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 InfoQ 的精彩文章:

揭秘智能時代的新運維,CNUTCon大會日程總覽
加速企業數字化轉型,首屆Spring Summit技術峰會圓滿落幕
為什麼 30 歲的工程師容易跳槽?
如何製作一個聊天機器人?

TAG:InfoQ |

您可能感興趣

Unreal Studio,一個提供實驗、自由、按需開發的VR可視化平台
VUE+WebPack:開發一款太空版植物大戰殭屍的前端頁游
研發實戰:現在開始,用Unity為Magic Leap One開發MR內容
Facebook正在開發一種「Talk the Walk」的AI
打通前後端構建一個Vue+Express的開發環境
一些可供參考的小程序開發案例@WeGeek
開發者從代碼中發現一款配有Face ID的iPad Pro
Niantic Labs推出面向開發者的全新AR多人實時競技平台
第一個Wear OS Android P開發者預覽版終於在這裡了
Block.one宣布推出Demux,可簡化複雜的DAPP開發
《Superhot VR》開發商:正在開發一款硬核VR體驗
Mozilla將開發全新的虛擬現實API—WebXR
如何開發一個基於 Docker 的 Python 應用
Unity與Unreal 相繼發布新功能支持AR開發
Facebook:一批開發者已經拿到了Santa Cruz開發機
NI FlexRIO 使用Kintex UltraScale FPGA和夾層I/O模塊,滿足客戶定製前端開發
Python web開發:Flask的URL和視圖
谷歌發布 Android KTX 預覽版:提供相應 API 層,讓Kotlin開發更簡潔
新MacBook Pro馬上發布!蘋果WWDC開發者大會開幕
Oculus開始向開發者提供VR一體機Santa Cruz