前言
在现代 Electron 应用开发中,跨进程状态同步是一个绕不开的难题。无论是渲染进程与主进程之间的数据共享,还是多个渲染进程之间的状态同步,传统的 IPC 通信方案往往会导致代码臃肿、维护困难,甚至引发数据一致性问题。
前期调研
在调研社区现有解决方案时,我们发现:
- electron-redux:基于 Redux,但我们业务的技术栈已全面采用 Mobx,切换成本过高。
- electron-shared-state:基于 Immer,但功能较为局限,无法满足复杂场景需求。
更重要的是,我们发现社区缺乏基于 Mobx 的跨进程状态同步方案,于是决定从零打造一个专为 Electron 设计的跨进程状态同步库——electron-mst。
electron-mst是一个基于 Mobx-State-Tree (MST) 的 Electron 跨进程状态同步库,专为解决多进程状态管理而生。它通过中心化的状态管理、增量更新机制和简洁的 API 设计,让跨进程状态同步变得高效、简洁、可靠。
为什么选择 electron-mst?
- 高效:利用 Mobx-State-Tree 的增量更新机制,仅传输变化部分,大幅降低 IPC 通信开销。并且 API 设计简单易用(和直接使用 MST 无差别-最简DEMO),接入成本低。
- 简洁:通过代理模式自动处理状态同步,开发者只需关注业务逻辑,无需手动管理 IPC。
- 可靠:中心化的状态管理确保多进程间数据一致性,同时处理了进程崩溃、异常操作等边界情况。
无论你也是习惯了使用 Mobx 作为状态管理,或是正在为复杂的 IPC 通信头疼,还是希望找到一种更优雅的状态同步方案,electron-mst 都值得一试。
设计思路
以下是它的设计思路、核心功能以及具体介绍
设计目标
electron-mst 的核心目标是:
- 状态共享:在多个渲染进程之间共享统一的状态树(Store),主进程作为状态的中心管理者。
- 状态更新同步:任一进程的状态变化能实时同步到其他进程。
- 双向通信:支持渲染进程主动请求状态更新,以及主进程推送状态变化。
- 按需实例化:Store 实例化按需进行,避免资源浪费。
- 高性能:利用 Mobx-State-Tree 的增量更新机制,减少 IPC 通信开销。
功能亮点
- 状态共享与同步:通过主进程集中管理状态,确保多进程间数据一致性。
- 增量更新:利用 Mobx-State-Tree 的 Patch 机制,仅传输变化部分,降低 IPC 压力。
- 按需实例化:Store 实例化延迟到首次使用时,节省内存资源。
- 易用性:提供简洁的 API,支持 TypeScript 类型推断,降低接入成本。
- 健壮性:处理了进程崩溃、异常操作等边界情况,确保系统稳定性。
架构设计
electron-mst 采用中心化设计,主进程通过 StoreManager
管理所有 Store 实例的生命周期和状态同步。渲染进程通过 StoreProxy
与主进程通信,确保状态更新的实时性和一致性。
graph
subgraph 主进程
M_Store1[Store实例1]
M_Store2[Store实例2]
StoreManager
end
subgraph 渲染进程A
RA_Store1_Proxy[[Store实例1-代理]]
RA_Bridge[Electron MST Bridge]
end
subgraph 渲染进程B
RB_Store1_Proxy[[Store实例1-代理]]
RB_Bridge[Electron MST Bridge]
end
StoreManager -.- M_Store1
StoreManager -.- M_Store2
M_Store1 <-->|IPC| RA_Bridge
RA_Bridge <-.-> RA_Store1_Proxy
M_Store1 <-->|IPC| RB_Bridge
RB_Bridge <-.-> RB_Store1_Proxy
---
title: “中心化”模块关系
---
classDiagram
direction TB
StoreManager "1" *-- "*" MSTStore : 管理
MSTStore ..|> IMSTStore
MSTStore ..> Renderer : 监听Store“action”
StoreManager ..> Renderer : 监听Store“注册”
class IMSTStore {
<<interface>>
+syncState(from, to)
}
class MSTStore {
+store : IAnyModelType
+storeInstance : IAnyStateTreeNode
+observers : WebContents[]
+destroy(): void
+create(snapshot): IAnyStateTreeNode
+syncSate(from, to): void
}
class StoreManager {
-storeMap : Map
+init(options) : void
+destroy() : void
}
工作机制
-
状态同步:
- 渲染进程触发状态更新,通过 IPC 将 Action 发送到主进程。
- 主进程应用 Action 并生成 Patch,通过 IPC 将 Patch 推送到其他渲染进程。
- 渲染进程应用 Patch,完成状态同步。
sequenceDiagram
participant Renderer1 as 渲染进程A
participant Renderer2 as 渲染进程B
participant Renderer3 as 渲染进程C
participant IPCMainProcess as 主进程
Note over Renderer1: 用户触发状态更新
Renderer1->>Renderer1: 执行action修改状态
Renderer1->>IPCMainProcess: 发送action消息
IPCMainProcess->>IPCMainProcess: 应用动作更新状态
IPCMainProcess-->>IPCMainProcess: 生成状态更新的Patch
Note over IPCMainProcess: Patch只含需要更新的部分
IPCMainProcess-->>Renderer2: 发送Patch
Renderer2->>Renderer2: 应用Patch更新状态
IPCMainProcess-->>Renderer3: 发送Patch
Renderer3->>Renderer3: 应用Patch更新状态
-
Store 注册:
- 渲染进程首次请求 Store 时,主进程按需实例化 Store 并返回状态快照。
- 渲染进程应用快照,完成初始化同步。
flowchart LR
subgraph 渲染进程
A1[请求注册]
A2[应用快照]
end
subgraph 主进程
B1{Store 已实例化?}
B2[实例化 Store]
B3[返回快照]
end
A1 --> B1
B1 -- 否 --> B2 --> B3
B1 -- 是 --> B3
B3 --> A2
技术细节
- 增量更新:利用 Mobx-State-Tree 的 Patch 机制,仅传输变化部分,大幅降低 IPC 通信开销。
- 中心化管理:通过
StoreManager
统一管理 Store 实例,避免多进程间状态不一致。 - StoreProxy:通过代理模式拦截 Store 的 Action 调用,自动触发状态同步,确保数据一致性。
// StoreProxy 关键代码
const StoreProxyHandler = (storeName: string) => ({
get(target, key, receiver) {
const value = Reflect.get(target, key, receiver);
if (
typeof value === 'object' &&
isModelType(getChildType(target, key as string))
) {
// 递归代理,使得嵌套的 model 也能触发 action
return new Proxy(
value,
getStoreInstanceHandler(storeName)
);
}
// _isMSTAction: https://github.com/mobxjs/mobx-state-tree/blob/7097c4d6/src/core/action.ts#L41
if (
typeof value === 'function' &&
!!value._isMSTAction
) {
return (...args: any) => {
try {
const res = value.apply(this, args);
window.ElectronMST.callAction(
storeName,
{
name: key as string,
path: getPath(target),
args,
}
);
return res;
} catch (error: any) {
console.error(
`[storeInstanceHandler error] ${error?.message}`
);
throw error;
}
};
}
return value;
},
});
落地成效
electron-mst 已在内部业务中成功落地,显著提升了状态同步的效率和代码可维护性。作为首个基于 Mobx-State-Tree 的 Electron 跨进程状态同步库,项目已开源,欢迎交流与贡献:
总结
electron-mst 为 Electron 应用提供了一种高效、简洁、可靠的跨进程状态同步方案。它不仅解决了传统 IPC 通信的痛点,还为复杂业务场景提供了强大的状态管理能力。如果你正在寻找一种更好的 Electron 状态同步方案,不妨试试 electron-mst!