近期准備開發一個數據分析 SDK,定位是作為數據中台向外輸出數據分析能力的載體,前端的功能表現類似低代碼平台的各種拖拉拽。作為中台能力的載體,SDK 未來很大概率會需要支持多種視圖層框架,比如Vue2/Vue3/React等。所以在技術架構上對視圖層框架的依賴性越輕,迭代的成本越低。基於這樣的目標,本文對前端狀態管理工具進行調研,在技術選型上應當盡量減輕與視圖框架的綁定程度,理想的目標是構建與視圖框架無關的數據/狀態管理層。
調研對象包括以下:
調研對象 | 說明 |
---|---|
Redux | 最早的基於Flux架構改進的狀態管理工具,生態繁榮,有豐富的中間件和插件滿足不同場景需求,較多搭配React |
Vuex | Vue專用的狀態管理工具,與 Redux 同屬 Flux 體系 |
Mobx | 基於響應式編程思想,近兩年成長為React社區最流行的狀態管理工具之一 |
Akita | 基於RxJS的響應式狀態管理工具 |
RxJS | RxJS並不是狀態管理工具,但其響應式的設計有很大想象空間 |
RxJS 跟狀態管理沒有任何關系,不過它天生適合編寫異步和基於事件的程序,有了這個前提,完全可以封裝一套基於 RxJS 的狀態管理架構,比如 Akita。同時RxJS 非常適合用來管理事件流,如果狀態管理工具能夠與 RxJS 比較好的搭配使用,能夠達到事半功倍的效果。本文的調研不涉及 RxJS,此處只列舉出它的作用,不做細節調研。
通過以下幾個維度進行對比(排名分先后):
對比維度 | 說明 |
---|---|
業務場景覆蓋率 | 工具本身搭配社區解決方案是否能夠覆蓋業務場景所需的能力 |
數據流 | 了解每個工具的數據流模式是所有調研的基礎 |
與視圖框架的綁定程度和改造成本 | 大部分狀態管理工具都可以兼容多種視圖框架,但一般需要適當的改造以提高開發便利性 |
風險和隱患 | 開源工具的選型都有一定隱患,主要考慮社區、生態以及開發團隊響應的及時性 |
性能 | 數據分析場景需要處理的數據量很大,對工具有一定性能要求,不過工具本身的性能遠未達到能夠成為應用的瓶頸的程度,所以此項僅作參考 |
學習曲線 | 結合當前研發人員的技術能力衡量上手成本和學習曲線,鑒於有一定的技術儲備時間,此維度的占比可以適當放低 |
數據分析SDK是純端側的產品,所以本文調研的幾個工具對於SSR的支持不在調研范圍之內。
業務場景覆蓋率
在進入調研之前,首先把數據分析 SDK (下文簡稱分析 SDK)的定位以及業務場景講清楚。
分析 SDK 是數據分析功能的承擔者,但 SDK本身不是一個可用的完整產品,上層需要一個分析平台作為宿主載體。以網易有數為例,網易有數是一個大數據平台,它包含很多功能,比如看板、報告定制、取數、多維分析等等。分析 SDK 在其中的角色就是這些功能的載體,網易有數平台將分析 SDK 集成進來,以可視化的形式提供分析相關的功能。下圖展示的是網易有數報告定制的頁面:
數據分析是一種類似的低代碼的業務場景,從技術角度上有以下特征:
- 數據量大且結構復雜;
- 事件流復雜、高頻且時序敏感;
- 組件結構復雜且互相之間存在大量的數據共享。
除此之外,之所以要做一個分析 SDK而不是分析平台,是因為中台的服務產出需要支持前台業務的接入,分析 SDK 的目標用戶是前台業務部門的各個分析平台。在這個前提下,分析 SDK 對技術有另外一個額外要求:
- 支持前台分析平台的技術棧。
而前台不止一個,不同業務線的技術棧也不統一,前端技術棧的契合度主要是組件要支持多種視圖層框架,比如React、Vue2、Vue3甚至Angular,所以分析 SDK的技術架構應當盡量減輕對視圖層框架的依賴程度,將核心業務邏輯從視圖層抽離出來。這樣的好處能夠降低支持不同視圖層框架時所投入的人力成本、時間成本和維護成本。這就是本文開頭所說的為什么要構建與視圖框架無關的數據/狀態管理層的原因。「Smart Modeling,Dumb View」,即邏輯集中在數據層,視圖層盡量只做展示(類似 React 的 Pure Component)。
結合分析 SDK的定位和業務場景,可以提煉出對狀態管理工具的幾點具體需求:
- 支持 state 按子模塊划分命名空間,以便支持復雜數據模型;
- 與視圖層框架沒有強綁定關系,以便支持多種視圖層框架;
- 支持時間回溯,比如undo/redo,這是編輯器的基本操作。
數據流
目前絕大多數狀態管理工具都遵循單向數據流原則,這項原則最早是由 Flux 帶入到前端領域,所以在了解各個狀態管理工具的數據流之前,有必要先搞清楚 Flux 架構。
這部分只考慮正常交互場景下的數據流向,也就是只考慮由view層觸發數據變動的情況,不考慮單元測試等非常規交互場景。
Flux
- Action是描述一個行為的對象,每個 action 里都包含兩部分信息:actionType 和 payload,分別代表行為的類型和攜帶的數據;
- Dispatcher是一個調度中心,它是 action 和 store 的連接中心。有兩個核心方法:
dispatch
方法:觸發一個 action,一般由 view 層調用;register
方法:用於注冊 actionType 的回調,在回調中操作 store。
- Store是數據倉庫以及數據操作的唯一場所,當數據發生變化時,向外廣播
change
事件; - View層監聽 store 的
change
事件,調用setState
方法來更新相應的組件狀態。
Flux 並沒有規定如何進行異步操作,比如接口的網絡請求,這種場景在前端應用中非常高頻。為了解決這種問題,有人提出了Action Creators的概念並在開發者社區獲得了認同,加入 Action Creator 之后的 Flux 數據流如下:
Action Creators 顧名思義就是 action 的「制造者」,在“制造”action之前可以進行任何行為,包括異步操作。比如以下代碼:
async function updateUserInfoCreator(){
// 第一步:異步獲取用戶信息
const info = awaitfetch('...');
//第二步:觸發action
dispatch({
actionType: 'UPDATE_USERINFO',
data: info
});
}
在 view 層調用 updateUserInfoCreator
函數即可。
Flux 的價值更多的體現在理論而非實用意義上,它提出的單向數據流模式被后續很多優秀的狀態管理工具借鑒。Facebook 提供了一個 Flux 實現,不過目前很少有開發者直接使用它,而是使用一些在 Flux 架構模式基礎上的改進方案,最廣泛的就是 Redux。
Redux
Redux 遵循 Flux 的單向數據流思想,與 Flux 不同的是,Redux 沒有 Dispatcher 的概念,而是將本屬於 Dispatcher 的 dispatch
方法內聚到了 Store 對象上。
- Redux 中 Action 的定位與 Flux 一致,都是描述一個具體行為的對象,包括 actionType 和 payload 兩部分信息;
- Redux 中的 Store 只有一個,也就是單一數據源,並且所有 state 共同組成了一個樹形結構。這與 Flux 不同,Flux 並沒有規定 Store 的個數限制以及 state 的組合方式,可以一個 store 對應所有 view,也可以每個 view 分別對應一個 store;
- Reducer 是 Redux 的專有概念,響應 action 並返回更新后的 state 發送到 store 中。Reducer 並不會修改 state,而是在 action 和 old state 基礎上計算出新的 state 值並發送給store,沒有任何副作用,更新 state 的行為是由 store 內部進行,對開發者不可見。
與 Flux 一樣,Redux 同樣沒有規定如何處理異步數據流。最原始的方案是上文提到的 Action Creators。不過 Redux提供了更優雅的解決方案:中間件。
關於 Redux 中間件的詳細使用方案就不介紹了,熟悉 Node.js 的開發者更容易理解中間件的概念,Express、Koa都實現了這種模式。
Redux 中間件同時也擴充了 dispatch
的行為,只要保證經過多個中間件的一系列連續行為的最后 dispatch
返回一個規范的 action對象即可,中間過程中可以 dispatch
一個 action creator 函數,這個函數內部還可以再次 dispatch
另一個 action。
中間件極大的豐富了 Redux 的可擴展性,孵化出很多優秀的異步數據流解決方案,比如 redux-thunk、redux-saga 等等。
綜合以上,Redux 的優勢有以下幾點:
- 單向數據流;
- 單一數據源,state聚合方便支持時間回溯;
- 引入數據不可變性理念( Reducer 本質是一個純函數),state 寫行為收斂;
- 可擴展性高。
Redux 同時也有一些被人詬病的缺點,主要有兩個:
- 繁瑣。各個角色分配的很精細,這樣的優點是行為單一邏輯嚴謹,缺點是樣板代碼(boilerplate code)數量大,尤其是 reducer,在復雜場景中需要寫大量的switch,可讀性差維護難度大,要理解一個狀態機往往需要配合好幾個代碼文件才能讀懂;
樣板代碼指的是為了完成一個功能所需的所有代碼。
- 復雜。Redux 默認只支持同步數據流,提供中間件機制讓開發者自己定制異步數據流,社區中的解決方案復雜度不一,復雜業務場景下的解決方案比如 redux-saga 的復雜度更是高出幾個量級,導致開發者在做技術選型和寫代碼時很頭疼。
在復雜度方面,Redux 跟前端這個行業很像,看上去非常簡單,稍一深入就卧了個槽。
另外,Redux 是函數式編程的推崇者,架構和API 設計對喜歡函數式編程的開發者非常友好。
Vuex
Vuex 是針對 Vue 的一種特異化的 Flux,保留了單向數據流的核心概念,同時吸取了部分 Redux 的理念。跟 Flux/Redux相比,Vuex 是更加全面的狀態管理解決方案,提供了異步操作支持,見下圖:
由於 Vuex只能搭配 Vue 使用,不具備適配多種視圖框架的能力,所以詳細的解析就不寫了,只簡單提一下它的優缺點。
Vuex的優點在於:
- 全面。Vuex 天然支持異步數據流,開發者不必操心選型問題。當然這個也有兩面性,如果存在 Vuex 覆蓋不了的業務場景(雖然概率很小),那么很大可能造成包括視圖層技術棧的整體遷移;
- 易用。包括兩方面,一是 API足夠簡單,
$store
對象直接掛載到 Vue 實例對象上;二是各角色划分清晰且職責單一( action 相對復雜一些),容易理解; - 響應式。與 Vue 的響應式特性天然結合,配合簡單易用的 API,Vue + Vuex 的組合在寫代碼時非常舒服。
這里額外說一點,Vue 與 React實現響應式的方式不一樣,React 是通過事件 push 機制實現,Vue 是借助 Proxy 進行 IO 劫持實現。
Vuex 的缺點,僅個人理解,有以下幾點:
- 適用面窄。與 Vue 強綁定,不適用於其他視圖框架。當然這也是跟它自身的定位有關,Vuex 本來就是針對 Vue 的解決方案,並沒有想成為一種通用方案。這算不上缺點,但在數據分析 SDK這個需求背景下確實不合適;
- 繁瑣。與 Redux 一樣,樣板代碼過多造成閱讀代碼的難度加強。
Vuex 和 Redux 本質上都是基於 Flux 的改進方案,核心思想同屬於 Flux 體系。接下來幾個是另外一套體系:響應式。
Mobx
Mobx 是一個基於函數式響應式編程(Functional Reactive Programming,簡稱 FRP)的狀態管理解決方案,同樣遵循單向數據流原則。
理解 Mobx 之前,必須先搞清楚兩個核心概念:observable
和 observer
。從名字上很好理解,observable
是可被觀察的對象,observer
是觀察者。這兩個概念被廣泛地使用在發布訂閱模式(Pub/Sub Pattern)、觀察者模式(Observer Pattern)以及響應式編程中。observable
對象的變化會“自動觸發” observer
對象執行對應的響應邏輯,而自動觸發的實現方式在不同的工具中存在差異,進而造成代碼范式、擴展性、性能等方面的差異。
在此背景之下,再去理解Mobx中的三個核心概念:
-
State - 狀態,顧名思義就是應用程序使用的狀態數據,在 Mobx 中,state 是一種 Observable 對象;
-
Actions - 動作,是任何一段可以改變 state 的代碼。Mobx中的 action 與 Redux 和 Vuex 中的 action 都不同,Redux 的action 是行為的描述對象,並不會改變 state;Vuex 中的 action 是可選的,一般是用來執行異步操作,而改變 state 的執行者是 mutation。Mobx 中 action 其實是一個抽象概念,action 的目的是修改 state,至於如何修改完全交給開發者自由發揮,也就是說 action 中可以包含任意邏輯的代碼,包括異步操作(action.bound/runInAction/flow);
-
Derivations - 衍生。Mobx 官方對 derivation 的定義如下:
有些不好理解,其實可以簡單粗暴的把 derivation 理解成 Observer 對象,它對 state 的改變做出響應,但是有一個條件,derivation只能消費 state,不能對 state 進行再次操作。
Derivation 分成兩種:
- Computed values - 計算值,類似 Vue 中的 computed value,基於 state 使用一個純函數計算出另外一個值;
- Reactions -反應,根據 state 改變自動觸發的一些副作用,比如渲染 UI。
至於什么時候用 Computed 什么時候用 Reaction 其實並沒有絕對的邊界,Reaction 可以解決絕大多數問題只不過需要自己寫代碼模擬 Computed(這一點也跟 Vue 中的 watch 和 computed 類似),如果應用中需要一個基於 state 的派生值同時這個值有一定的復用性,可以考慮使用 Computed。
Mobx的優點是,它沒有 Redux 和 Vuex 中那么多概念,樣板代碼的數量很小,代碼可讀性和可維護性高。基於這一點,Mobx 的上手也非常容易,開發者需要理解的概念越少越容易上手。此外,雖然 Mobx 是基於 FRP,但它的 API設計非常適合面向對象編程,比如 decorator 裝飾詞、class 是一等公民等等。而且有 Reactions 作為響應式編程和命令式編程的橋梁,開發者可以用更舒服的范式寫代碼。
decorator 還沒有成為 JavaScript 語言標准(ES)的一部分,Mobx 6中移除了 decorator 裝飾器語法,不過核心思想沒有改變。之所以移除 decorator,一方面是為了向 JavaScript 語言標准靠攏,另一方面是由於 decorator本身的代碼量很大,增大了打包后的 js 文件體積。
Mobx 雖然不是 Flux 系列,但有一點與 Flux 的設計理念相同:沒有規范 store 的組織模式。Redux 和 Vuex 中的 store 都是樹形結構,單一數據源並且方便快照(snapshot),這個優點讓兩者非常便於調試,並且支持時間回溯的場景上游刃有余。而 Mobx 並沒有這些優點,所以社區中涌現了一批補充方案,比如mobx-state-tree(簡稱MST)和mobx-keystone,核心思想就是將 store 的組織結構聚攏為樹狀,以便支持更友好的調試和時間回溯。
綜合以上,總結 Mobx的優點是:
- 簡單易學習;
- 代碼可讀性和可維護性高;
- OOP編碼范式,易於上手。
缺點有以下:
- 調試困難(與Redux/Vuex相比);
- 不支持時間回溯。
搭配使用一些社區解決方案,Mobx的以上缺點可以得到一定程度上的彌補。
有很多開發者認為 Redux更適合復雜的大型應用,Mobx 適合數據流相對簡單的應用。這其實並不絕對。Redux 嚴謹的代碼組織確實對復雜場景有加分,但 Mobx 也並不是不適用,而且市場中已經有很多 Mobx 解決復雜場景的實踐經驗,比如低代碼開發平台Mendix,而且 Mendix 的業務場景與數據分析有很高的相似度,這也從側面證明了 Mobx 與此類低代碼場景的契合度。
Akita
Akita是來自 Datorama 公司研發團隊的前端狀態管理方案,跟其他幾個競品相比,Akita 的資歷是最淺的。不過 Akita有一個優勢:與 Mobx一樣,Akita 經過了與數據分析類似業務場景的實踐驗證。Datorama 是一家提供數據解決方案的公司,它的業務場景與數據分析有很大的重合度,Akita 已經在 Datorama 的一些產品中得到了實踐和驗證。
Datorama 是 Angular 技術棧,Akita 最初就是為了解決Angular的狀態管理,后期開源后已經從 Angular 技術棧中剝離,對視圖層框架沒有強依賴關系。不過仍然保留了最核心的一點:基於 RxJS。在前端三大框架中,Angular 與 RxJS 的關系最緊密,Akita 最早作為 Angular 的狀態管理方案也對 RxJS 有強依賴,包括數據的封裝也是遵循 RxJS的“萬物皆流”的理念。
下圖是 Akita 的數據流:
同樣是單向數據流,Akita 有以下幾個角色:
- Store - 倉庫。Akita 中 Store 分為兩種:Basic Store 和 Entity Store。Basic Store 指的是常規的狀態數據,一般是一個純 JavaScript 對象,沒有額外附加的 API;Entity Store即實體 Store,Akita 將 Entity Store 類比為關系型數據庫的表(table),有一系列配套的 CURD API;
- Query - 查詢。Akita 限制 Store 中的數據不能被直接讀取,必須借助一個 Query 對象做橋接(類似 Vuex的 Getter )。與 Store 一樣,Query 也分為 Basic Query 和 Entity Query,兩者的主要區別是 API 的豐富程度,Basic Query 只有基本的條件查詢和全量查詢 API,Entity Query 搭配 Entity Store 使用,有更豐富的 API。另外,如圖中所示,Query 可以嵌套;
- Component - 組件,即視圖層;
- Service - 服務。Akita 中的 Service 與 Mobx 的 Action 有些類似,都是為了封裝更新 Store的邏輯,包括異步操作。
很明顯可以看出 Akita 的設計與關系型數據庫非常接近,說不定設計者是個關系型數據庫死忠粉。
Akita 與 Mobx/Flux 有一個相同的設計:沒有規范 Store 的組織模式。而且由於比較年輕,生態不繁榮,社區並沒有類似 MST 的解決方案,這造成在面對復雜數據場景下沒有既定的范式可遵循,代碼的健壯性非常依賴開發者的能力。Akita 的 Entity Store 是一個 class,可以將其他 Store 作為一個 property,以此來實現Store 的嵌套。但 JavaScript 對象之間復雜的引用關系很容易造成 memory leak,這同樣是對開發者自身能力的高要求。
Akita的優點主要有三個:
- 足夠簡單,核心概念比 Mobx 和 Flux 還少,對開發者來說,有足夠的定制空間。同時如上文所述,這是一把雙刃劍,對開發者的能力要求很高;
- 與關系型數據庫搭配順暢。Akita 的概念設計與關系型數據庫非常相似,這可能也是結合 Darorama 的業務特色,數據分析場景中的數據模型一般是一張二維表,Akita 的實體概念與 table 的搭配非常自然;
- 與 RxJS 無縫銜接。數據分析業務場景的事件流操作非常適合用 RxJS,Akita 底層基於 RxJS,這一點是其他競品沒有的優勢。
Akita 的缺點,如上文所述,有以下幾個:
- 對開發者的編碼能力要求很高;
- 社區不繁榮,生態不夠健全,沒有在市場中得到大范圍實踐驗證;
- 比較小眾,遇到問題可交流和參考的空間很小。
小結
綜合以上,各工具的基本情況如下:
是否支持划分命名空間 | 是否支持時間回溯 | |
---|---|---|
Redux | 是 | 是 |
Vuex | 是 | 是 |
Mobx | 需搭配社區解決方案 | 需搭配社區解決方案 |
Akita | 無規范無限制,開發者需自行組織代碼 | 插件支持 |
與視圖框架的綁定程度和改造成本
除了 Vuex 之外,其他幾個工具都沒有限制視圖層框架,只不過 Vue + Vuex 生態比較健全,使用其他狀態管理工具的情況比較少。Redux/Mobx/Akita 目前對 React的支持都很好,要配合 Vue 框架,為了提高編碼效率和維護成本,一般需要一定的改造成本。
是否綁定視圖框架 | 改造成本 | 其他 | |
---|---|---|---|
Redux | 否 | 高 | |
Vuex | 是 | - | 不適用 |
Mobx | 否 | 低 | 需搭配社區解決方案 |
Akita | 否 | 中 |
由於 Vuex 不具備兼容多種視圖層框架的能力,所以下文的各維度對比不再統計 Vuex。
當然理論上 Vuex 搭配 React 也不是不可能,但這種操作就太騷了,純粹為了用而用。
性能
數據分析業務場景需要處理的數據量遠大於常規 Web 應用,不過以這種數據的量級還遠未達到需要對工具性能要求非常苛刻的程度,所以對於性能的對比僅做參考。
這里的意思並不是說工具性能不重要,而是還沒有成為應用程序的性能瓶頸。本文調研的幾個工具都是很成熟的開源產品,已經經受了大量的業務驗證,雖然在性能上存在些許差距,但對應用性能表現的影響非常有限。
除非是涉及海量數據渲染的 web 應用,比如復雜的圖形應用(WebGL/Canvas/SVG),否則工具的性能大概率不會成為應用的性能瓶頸,尤其是比較成熟的、經過大量業務驗證的開源工具。
性能對比
以下參考自社區的兩份性能對比數據,一份是對比 Redux 和 Mobx,一份是對比 Redux 和 Akita。兩份數據都是配合 React 完成。
Redux vs Mobx
這張表格來自 Mobx 作者 Michel Weststrate 的實驗數據,場景是在包含不同數量級 items 的 todolist 應用上進行增/改操作,分別統計 Redux 和 Mobx 的耗時情況。從表格里可以看出 Mobx 有明顯的性能優勢。
這份數據僅作參考,一是因為這個實驗是2016年進行的,當時的 Redux和 Mobx 版本比較老舊。另外由於數據來自 Mobx 的作者,有些王婆賣瓜的嫌疑哈哈。不過實驗源碼是公開的,社區也比較認可。
Redux vs Akita
這份數據來自Performance Comparison of State Management Solutions in React,場景是生成一個 grid,每次生成100行,每行10列,然后隨機更新1000列的數據。測試進行10次,統計總耗時(單位s)。從上圖中可以明顯看出 Akita 的耗時遠大於 Redux,更新行為的耗時對比尤其明顯。Akita 畢竟比較“年輕”,很多方面趕不上老大哥 Redux 也很正常。
綜合上面的兩份實驗數據,可以得出結論:性能方面 Mobx > Redux > Akita。
之所以上述實驗僅做參考,一方面是因為實驗的場景與真實的業務場景差距很大,現實業務中不可能只用 Redux 或 Mobx,往往還需要配合其他解決方案,比如 redux-thunk 或 MST;另一方面是實驗本身並不絕對嚴謹,而且由於是搭配 React 進行,React 本身在不同邏輯場景下的性能表現也會直接影響實驗結果。
不過第二個實驗中涉及的一個點對本次調研工作非常有價值:狀態管理工具的批量(batch)更新能力。
批量更新
數據分析是重交互、重通信的事件密集型業務場景,很大可能在非常短的時間內發生多個事件,如果每個事件都觸發一次渲染流程(包括計算邏輯和渲染行為)的話,不僅會產生非常嚴重且無價值的性能損耗,而且如果涉及網絡請求的話還可能產生行為時序混亂進而造成結果的不正確,對業務產生無法預估的負面影響。
所謂批量更新是一個籠統的說法,在不同的工具中有不同的術語表達,不過核心目的是統一的,都是將一定時間內的 store 更新行為進行歸攏,消除中間態只產生最終結果。這種技術手段在前端還有另外一個叫法:防抖(debounce)。
Redux 本身並不具備批量更新能力,需要搭配社區解決方案,比如 redux-batched-subscribe 和 redux-batched-actions 。
Mobx 有一個底層 API:transaction
。這是個函數,作用是將一段時間內的所有更新行為按時序進行批量處理,所有行為處理完成之后才會通知 observer
執行回調,中間過程中不會產生任何回調。很明顯 transaction
是借鑒的數據庫中的事務概念。
Akita 與 Redux 一樣,本身同樣不具備批量更新的能力,但是由於它的底層基於 RxJS,可以使用 RxJS 的所有能力,在處理防抖場景下常用sampleTime
和debounceTime
兩個方法。
學習曲線
學習曲線/5分制 | 說明 | |
---|---|---|
Redux | 5 | Redux本身的學習難度不高,但Redux自身無法滿足復雜需求,需要額外的社區解決方案,增加了學習成本 |
Mobx | 4 | 同Redux一樣,需要學習額外的社區解決方案,但成本總量比Redux低 |
Akita | 4 | 由於Akita是基於RxJS構建,所以除了Akita本身,還需要理解RxJS的一些基本概念 |
風險與隱患
對於開源工具的選擇需要考慮的風險與隱患主要考慮其社區、生態以及背后團隊的響應及時性。
從這三個角度上對比,Redux 作為資歷最老的一個,各方面也是最好的,雖然目前有大量開發者對 Redux 的吐槽,但總的來說 Redux 的位置仍然很穩固,尤其是在 React社區。
Mobx 是近兩三年才逐漸占據主流,社區和生態也相對比較完善,開發團隊的響應速度也不錯。
Akita 跟前兩者比起來,最大的優勢就是開發團隊響應速度很快,目前處於上升期,開發團隊也比較活躍。但相對來說還是比較小眾,Akita 最早是面向 Angular 的,Angular 的開發者群體規模本身就比 React 和 Vue 小。 Akita 底層的 RxJS 更加小眾(雖然很好用)。目前圍繞 Akita 的復雜業務場景除了 Darorama 公司自己的業務之外,還沒有其他比較好的實踐驗證。
結論
綜合以上所有的調研維度,可以得出以下結論:
Redux | Mobx | Akita | |
---|---|---|---|
自身是否完全覆蓋業務需求 | 否 | 否 | 否 |
是否有成熟的補足方案 | 是 | 是 | 是 |
支持Vue的改造成本 | 高 | 中 | 中 |
是否支持批量更新 | 是 | 是 | 是 |
學習曲線(5分制) | 5 | 4 | 4 |
風險與隱患 | 低 | 低 | 中 |
性能(僅參考) | 中 | 高 | 低 |
綜合對比,在 Redux/Mobx/Akita 三者當中,數據分析 SDK 的狀態管理技術選型是:Mobx。
參考資料
- Flux架構的工作原理;
- 為 MobX 開啟 Time-Travelling 引擎;
- Build A View-Framework-Free Data Layer Based on MobX — Integration With Vue
- 用mobx構建大型項目的最佳實踐
- Becoming fully reactive: an in-depth explanation of MobX;
- 現代前端框架響應模型對比: Vue, Mobx, React, Redux;
- Mobx vs Reactive Stream Libraries;
- Defining data stores with Mobx;
- OOP and RxJS: Managing State in React with Akita;