跳转到内容

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 翻译成 RoomMatrixEventUser 这些 JavaScript 对象,再触发 Room.timelineUser.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 一个核心对象组织:

  1. 同步循环(sync loop):调 startClient() 之后 SDK 自己开始 long-poll /sync API,把服务端推来的增量事件喂给本地状态机。

  2. 房间状态机:每个 Room 对象维护”成员列表 / 最近消息 / 加密配置”,新事件来时按 Matrix 协议规则更新状态——比如 m.room.member 改成员、m.room.message 进时间线。

  3. EventEmitter 接口:UI 不直接读对象,而是监听事件——Room.timeline / RoomMember.membership / crypto.verification.request。React 客户端把这些事件桥到 state,UI 自动重渲。

  4. 加密层(crypto-api):Olm/Megolm 端到端加密。新版本通过 WASM 调用 matrix-rust-sdk 的 crypto crate——一份加密代码,Web 端和移动端共享,避免”iOS 解密对、Web 解密错”。

  5. 持久化:浏览器用 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,用任意前端框架渲染就行。不用自己造协议轮子。

踩过的坑

  1. 同 IndexedDB 多实例 = 加密 store 损坏:别在同一个 origin 创多个 MatrixClient 实例往同一个 IndexedDB 写——加密会话密钥会乱,历史消息直接解不开。必须单例。

  2. 设备验证是状态机不是一次函数调用:扫二维码 / SAS 短串验证要驱动 SDK 的 verification 状态机,监听一系列事件才能完成。新人常以为调 verify() 就结束,结果对方那边没确认。

  3. sync loop 默认全量拉,老用户打开慢:默认 /sync 把所有房间状态都拉一遍,账号年限长 / 房间数百时首屏几十秒。需要开 lazy loading 或迁移到 sliding sync(MSC3575)才能”打开就看到第一屏”。

  4. 加密 API 在迁移中:老 client.crypto 部分接口被标 deprecated,新 crypto-api(WASM 桥到 rust-sdk)才是推荐入口。读老教程容易写出已废弃代码。

  5. MXC 媒体 URI 不能直接喂 <img src>:Matrix 媒体用 mxc://server/id 自定义 scheme,要先调 client.mxcUrlToHttp(mxc) 转成 HTTPS URL;后续协议要求带 Authorization header,更复杂。

  6. 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 跟进。

学到什么

  1. 事件驱动 + 房间状态机 是聊天客户端的常见骨架——服务端推增量事件,本地维护对象,UI 监听
  2. EventEmitter 接口让 SDK 与 UI 框架解耦——React/Vue/Svelte 都能吃同一份 SDK
  3. 加密能力下沉到 Rust + WASM 是趋势——一份核心 crypto 给所有平台用,避免多端实现 bug 不一致
  4. 老项目的”维护策略”很重要——js-sdk 没被 deprecate,但官方资源在 rust-sdk;选型时要看官方下注方向,不只看 stars

延伸阅读

关联

  • 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 内核