The 'wasm owns state, JS is a thin shell' architecture as a reusable kit: a generic Session with an init/dispatch JSON protocol (state + effects envelope), plus a dependency-free browser runtime. The MoonBit core is the only decision point; the DOM shell only renders and executes effects.
┌─────────────────────────── 浏览器 ────────────────────────────┐
│ 你的 HTML/CSS moonbridge.mjs(运行时,~120 行) │
│ ▲ onState(state) │ 事件 JSON / 响应 JSON │
│ │ ▼ │
│ 用户交互 ──────▶ wasm.dispatch ──────▶ Session[M,E,F] │
│ (你的 update 归约函数) │
│ localStorage / 跳转 / │ effects │
│ toast ◀── effects 处理器注册表 ◀──┘ (由你的壳执行) │
└──────────────────────────────────────────────────────────────┘moon add 2d5rrr333/moonbridge// 你的状态 / 事件 / 副作用(应用自己的类型)
pub(all) struct State { count : Int } derive(ToJson)
pub enum Event { Inc; Dec } derive(Eq, Debug)
pub enum Effect {
Saved
Notified(message~ : String)
} derive(Eq, Debug)
// FromJson / ToJson 手写实现(wire format 完全由你定义)...
// 归约函数:纯函数,(state, event) -> (next state, effects)
fn update(state : State, ev : Event) -> (State, Array[Effect]) { ... }
// 组装 Session,然后导出两个 wasm 函数
let session : Session[State, Event, Effect] = Session::make(update)
#export_name("app_init")
pub fn app_init(stored : String) -> String {
// ...从 stored 恢复或取默认状态...
session.init(initial_state, []) // 存入状态并返回信封 JSON
}
#export_name("app_dispatch")
pub fn app_dispatch(event : String) -> String {
session.dispatch(event) // 协议机制全部在这里
}<script type="module">
import { bootBridge } from './moonbridge.mjs'; // 从本仓库 web/ 复制
const app = await bootBridge({
wasmUrl: 'wasm/app.wasm',
init: 'app_init', // 你的导出名
dispatch: 'app_dispatch',
initArgs: () => [localStorage.getItem('app.state') || ''],
onState: render, // (state) => void,按分区重绘
effects: {
save: (_eff, ctx) => localStorage.setItem('app.state', JSON.stringify(ctx.state)),
notify_error: eff => showToast(eff.message),
},
});
</script>{ "state": <你的状态 JSON,或 null>, "effects": [ { "type": "...", ... } ] }| 场景 | state | effects |
|---|---|---|
| 正常 init/dispatch | 新状态 | 你的 update 产出 |
| dispatch 先于 init(未初始化) | null | [{type: "notify_error", message: <文案>}] |
| 事件解码失败(非 JSON / 形状不对 / 未知 type) | 当前状态(不前滚) | [{type: "notify_error", message: <文案>}] |
Install
Download zipThe 'wasm owns state, JS is a thin shell' architecture as a reusable kit: a generic Session with an init/dispatch JSON protocol (state + effects envelope), plus a dependency-free browser runtime. The MoonBit core is the only decision point; the DOM shell only renders and executes effects.