matrix-js-sdk — Matrix Web/Node 端的"老大哥"客户端 SDK
是什么
matrix-js-sdk 是 Matrix 协议官方的 JavaScript/TypeScript 客户端 SDK,跑在浏览器和 Node.js 里。Matrix 是开源的去中心化聊天协议(任何人都能自建服务器,服务器之间互通)。这个 SDK 给”想在 Web 或 Node 上做 Matrix 客户端 / 机器人 / 桥接器”的人用。
日常类比:像一台事件驱动的转译机。服务端用 HTTP+JSON 一直推 “Alice 加入了房间 R1”、“Bob 在房间 R2 发了消息”——SDK 把这堆 JSON 翻译成 Room、MatrixEvent、User 这些 JavaScript 对象,再触发 Room.timeline、User.presence 之类事件,UI 监听就行。
最小客户端长这样:
import { createClient } from "matrix-js-sdk";
const client = createClient({ baseUrl: "https://matrix.org" });await client.login("m.login.password", { user: "alice", password: "pw" });client.on("Room.timeline", (event, room) => { if (event.getType() === "m.room.message") { console.log(room.name, event.getContent().body); }});client.startClient(); // 后台开 sync loop它是 element-web(Element 公司的 Web 客户端,几百万行 React)的唯一数据源,也是大量 Matrix 机器人 / IRC-Discord-Slack 桥接器的标准依赖。
为什么重要
不理解这个项目,下面这些事都看不清:
- 为什么 element-web 一打开几秒后所有历史房间都”自己冒出来”——SDK 的 sync loop 在背后增量拉
- 为什么 Web 端加密聊天既能跑、又比原生客户端慢一拍——加密走 WASM 调用 matrix-rust-sdk 的 crypto,多过一层桥
- 为什么社区机器人几乎都用 Node + matrix-js-sdk——服务端 NPM 生态成熟,写起来比 Rust 快
- Matrix 整个协议设计能不能”在浏览器跑”,靠这个 SDK 一直在证明
核心要点
SDK 围绕 MatrixClient 一个核心对象组织:
-
同步循环(sync loop):调
startClient()之后 SDK 自己开始 long-poll/syncAPI,把服务端推来的增量事件喂给本地状态机。 -
房间状态机:每个
Room对象维护”成员列表 / 最近消息 / 加密配置”,新事件来时按 Matrix 协议规则更新状态——比如m.room.member改成员、m.room.message进时间线。 -
EventEmitter 接口:UI 不直接读对象,而是监听事件——
Room.timeline/RoomMember.membership/crypto.verification.request。React 客户端把这些事件桥到 state,UI 自动重渲。 -
加密层(crypto-api):Olm/Megolm 端到端加密。新版本通过 WASM 调用 matrix-rust-sdk 的 crypto crate——一份加密代码,Web 端和移动端共享,避免”iOS 解密对、Web 解密错”。
-
持久化:浏览器用 IndexedDB 存房间状态和加密 store,Node.js 用内存或自定义 store。
与 matrix-rust-sdk 的定位差异
这是这两个项目最容易混淆的地方,单独讲清楚:
- 历史顺序:matrix-js-sdk 先存在(2014-2015 年随协议诞生),matrix-rust-sdk 是 2020 年后才启动的”统一内核”项目
- 运行环境:js-sdk 跑在浏览器/Node.js;rust-sdk 通过 UniFFI/wasm-bindgen 同时给 Swift/Kotlin/JS 用
- 当前定位:js-sdk 是 element-web 专属底座;rust-sdk 是 element-x(iOS/Android 新客户端)+ Fractal + iamb 的共享内核
- 加密层:js-sdk 现在的 crypto 就是 rust-sdk crypto 的 WASM 封装——上下游关系,不是替代关系
- 未来走向:官方策略是 rust-sdk 作主力,js-sdk 维持但优先级降低
一句话:rust-sdk 是新一代多端内核,js-sdk 是老一代但仍是 Web 端事实标准。
实践案例
案例 1:element-web — UI 当 SDK 的”显示器”
element-web 的 React 组件不直接发 HTTP,全部通过 MatrixClient 实例:
const cli = MatrixClientPeg.get();cli.on("Room.timeline", (event, room) => store.dispatch(addEvent(event)));cli.sendTextMessage(roomId, "hello");UI 拿到事件就 setState,React 重渲。SDK 负责”对得起协议”,UI 负责”画得好看”。
案例 2:Node.js 桥接器 / 机器人
桥接器(如 matrix-appservice-irc)跑在 Node.js,监听 IRC 消息,转成 Matrix m.room.message 事件发出去:
client.on("Room.timeline", async (event, room) => { if (event.getSender() === botUser) return; await ircBridge.relay(room.name, event.getContent().body);});机器人也常用这套——监听消息、解析命令、回复。Node.js 生态成熟(Express/数据库/调度库都现成),写起来比 Rust 快很多。
案例 3:自建 Web 客户端 / 嵌入聊天组件
想给自己的 Web 应用加聊天功能——npm install matrix-js-sdk,登录拿 token,订阅 Room.timeline,用任意前端框架渲染就行。不用自己造协议轮子。
踩过的坑
-
同 IndexedDB 多实例 = 加密 store 损坏:别在同一个 origin 创多个
MatrixClient实例往同一个 IndexedDB 写——加密会话密钥会乱,历史消息直接解不开。必须单例。 -
设备验证是状态机不是一次函数调用:扫二维码 / SAS 短串验证要驱动 SDK 的
verification状态机,监听一系列事件才能完成。新人常以为调verify()就结束,结果对方那边没确认。 -
sync loop 默认全量拉,老用户打开慢:默认
/sync把所有房间状态都拉一遍,账号年限长 / 房间数百时首屏几十秒。需要开 lazy loading 或迁移到 sliding sync(MSC3575)才能”打开就看到第一屏”。 -
加密 API 在迁移中:老
client.crypto部分接口被标 deprecated,新crypto-api(WASM 桥到 rust-sdk)才是推荐入口。读老教程容易写出已废弃代码。 -
MXC 媒体 URI 不能直接喂
<img src>:Matrix 媒体用mxc://server/id自定义 scheme,要先调client.mxcUrlToHttp(mxc)转成 HTTPS URL;后续协议要求带 Authorization header,更复杂。 -
EventEmitter 内存泄漏:长跑的客户端要记得
client.removeListener,否则订阅者越积越多,每条新消息触发几千个失效回调。
适用 vs 不适用场景
适用:
- 做 Matrix Web 客户端(element-web 的同款栈)
- 做 Matrix Node.js 机器人 / IRC-Discord-Slack 桥接器
- 做”网页内嵌聊天”,需要纯前端方案
- 已有 JS/TS 团队,不想引入 Rust 工具链
不适用:
- 做 iOS/Android 原生客户端 → 用 matrix-rust-sdk + Swift/Kotlin binding
- 做 Matrix 服务端 → 用 Synapse(Python)或 Dendrite(Go)
- 想要”打开就看到第一屏”的极致冷启动 → matrix-rust-sdk + sliding sync 体验更好
- 极度计较前端体积 → SDK + WASM crypto 加起来体积不小
历史小故事(可跳过)
- 2014 年:Matrix 协议在 Element 公司前身(Amdocs Unified Communications)启动,第一个 SDK 就是 JS——目标是先在 Web 跑通。
- 2015-2016 年:JS SDK 配 Vector/Riot Web 客户端发布,是当时唯一的 Matrix 客户端栈。
- 2017-2019 年:Element 又给 iOS(Swift)/ Android(Kotlin)各做了一份 SDK,三份代码各自实现状态机,加密 bug 三端不一致。
- 2020 年:Element 启动 Rust 化,把核心移到 matrix-rust-sdk。js-sdk 角色从”唯一客户端栈”转为”Web/Node 专用栈”。
- 2022-2024 年:js-sdk 的加密层逐步替换为 WASM 调用 rust-sdk crypto,Web 和移动加密代码统一到一份 Rust。
- 2025-2026 年:js-sdk 仍是 element-web 底座;新功能优先在 rust-sdk 落地,js-sdk 跟进。
学到什么
- 事件驱动 + 房间状态机 是聊天客户端的常见骨架——服务端推增量事件,本地维护对象,UI 监听
- EventEmitter 接口让 SDK 与 UI 框架解耦——React/Vue/Svelte 都能吃同一份 SDK
- 加密能力下沉到 Rust + WASM 是趋势——一份核心 crypto 给所有平台用,避免多端实现 bug 不一致
- 老项目的”维护策略”很重要——js-sdk 没被 deprecate,但官方资源在 rust-sdk;选型时要看官方下注方向,不只看 stars
延伸阅读
- 仓库:matrix-org/matrix-js-sdk(README 含 module 划分)
- element-web 源码:element-hq/element-web(看 React 怎么吃 SDK 事件)
- Matrix 协议规范:spec.matrix.org(Client-Server API)
- Sliding sync MSC:MSC3575
- matrix-rust-sdk —— 多端共享的新一代内核,js-sdk 加密层依赖它
- synapse —— Matrix 主流服务端实现(Python),js-sdk 的对端
关联
- matrix-rust-sdk —— 新一代多端内核;js-sdk crypto 现在是它的 WASM 封装
- synapse —— Matrix 服务端,js-sdk HTTP 调的就是它
- dendrite —— 另一个 Matrix 服务端(Go),协议另一头
- axum —— Rust web 框架,社区桥接器后端常见栈
一句话总结
事件驱动的 Matrix Web/Node 客户端老大哥——element-web 的底座,新工具链在追赶但 Web 端十年事实标准还在它手里。
反向链接
- axum —— axum — 用 Rust 类型系统当『路由参数表』的 Web 框架
- botbuilder-js —— Bot Framework SDK JS — 微软多渠道 chatbot 的 Adapter + Middleware 抽象
- dendrite —— Dendrite — Go 写的第二代 Matrix homeserver,组件可拆可合
- element-android —— Element Android — Matrix 协议官方 Android 客户端(Kotlin + Realm)
- element-web —— Element Web — Matrix 协议旗舰 web 客户端(React + matrix-js-sdk)
- matrix-rust-sdk —— matrix-rust-sdk — Matrix 客户端的”共享发动机”
- rocket-chat —— Rocket.Chat — 开源 Slack 替代,Meteor + MongoDB 全栈实时聊天
- signal-ios —— Signal iOS — 让 iPhone 上的每条消息都只有两端能看见
- synapse —— Synapse — Matrix 协议的参考 homeserver,让聊天像电邮一样能跨服务器互通
- vodozemac —— vodozemac — Matrix 端到端加密的 Rust 内核