[TOC]
Xmit 在 Web 端和小程序端使用的 SDK,通过 wasm 方式进行调用。
先 xmit 主项目编译成动态库(interface.h, libxmit-solo.a),然后再通过 bridge 把 js 层跟 c++ 层的通信打通。
Web 端把 wasm 运行在 worker 环境中,所以需要主线程接口层 + worker 逻辑层 + wasm。为了避免出现请求失败的情况,编译的时候把 worker 跟 wasm 都内联在一起。
小程序端把 wasm 运行在主线程,所以只要主线程逻辑层 + wasm。由于小程序的 wasm 加载需要指定特定路径,所以不能把 wasm 内联进 js 代码中,需要生成独立的两个文件。
- worker 线程
- 模块入口(src/worker/worker.ts),wasm 的初始化跟与主线程的通信主要放在这里。
- Client 模块(src/worker/xmit-client.ts),对应 xmit 协议的 client 概念,一个连接对应一个 client,一个 client 上有多个 stream 来收发消息。
- Engine 模块(src/worker/xmit-engine.ts),负责管理 Client。
- 主线程
- 模块入口(src/xmit/index.ts),主要负责 wasm 跟 worker 的初始化,事件绑定,以及暴露一个创建 xmit 实例的接口;
- 具体xmit实例(src/xmit/instance.ts),跟 Client 概念对齐,创建 Stream、收发消息、连接状态回调。
- 模块入口(src/mp/xmit.ts),负责 wasm 的加载,跟 wasm 的通信封装,以及暴露一个创建 xmit 实例的接口;
- Client 模块(src/mp/client.ts),对应 xmit 协议的 client 概念。
- Loader 模块(src/mp/glue.ts),小程序版本的 wasm 加载规则需要指定 wasm 文件的路径来加载,需要一个加载模块来实现指定路径加载的能力。
- 小程序注意事项
- 小程序环境中没有 TextCodec API,需要自己加 polyfill。
- 小程序环境中没有 performance API,而 wasm 中的时钟获取依赖 js performance API,我们可以使用
wx.getPerformance
接口来平替。详情见src/mp/performace.polyfill.js
。 - 小程序开发者工具跟真机的表现差异很大,调试的时候需要两边都兼容。
import Xmit, { StreamMode, StreamPriority } from '@xverse/xmit-core';
await Xmit.ready; // wasm 加载
// 如有 worker 之间通信的场景,则需要借助 MessageChannel
const channel1 = new MessageChannel();
channel1.port2.onmessage = (data: any) => {
// ...
};
const xmit = Xmit.createInstance({
messagePortConfigs: [{
port: channel1.port1,
// 独立纯函数,没有外部依赖和 this
// 从主线程传参到 worker 线程过程中,参数是不能为函数的,所以会先把函数做一次 string 化处理,因此函数不能有外部依赖和 this。
rule: (type, data) => {
return true;
},
}, {
// null 说明回给主线程
port: null,
// 独立纯函数
hook: (type, data) => {
return data.slice(2);
},
}],
});
// 各类事件回调注册
xmit.on('xxx', () => {});
...
// xmit 协议开始执行
xmit.start({
cnid, // connection id,建连前跟后台交互协商获得
externalTick, //
});
// 创建发消息用的 stream,不同 stream 之间的区别是优先级和是否允许乱序,还有消息有效期。
const stream = xmit.createStream({
label: 'xrtc-xmit-data',
mode: StreamMode.SemiReliableOrdered,
priority: StreamPriority.Normal,
lifetimeMS: 3000,
});
stream.send(xxx);
...
// 断连后停止 xmit
xmit.stop();
因为小程序版本是运行在主线程的,不需要额外支持 worker 之间通信的能力。
import Xmit from 'path/to/xmit-core.js';
const XmitCore = new Xmit('path/to/wasm'); // 不需要包括文件名
await XmitCore.ready;
const xmit = XmitCore.createInstance();
// 各类事件回调注册
xmit.on('xxx', () => {});
...
// xmit 协议开始执行
xmit.start({
cnid, // connection id,建连前跟后台交互协商获得
externalTick,
});
// 创建发消息用的 stream,不同 stream 之间的区别是优先级和是否允许乱序,还有消息有效期。
const stream = xmit.createStream({
label: 'xrtc-xmit-data',
mode: StreamMode.SemiReliableOrdered,
priority: StreamPriority.Normal,
lifetimeMS: 3000,
});
stream.send(xxx);
// 断连后
xmit.stop();
因为 Coding 的 CI 环境过于老旧恶心难搞,目前还是通过本地构建的方式进行发布。
在 packages/xmit
目录下,执行 pnpm run build
进行构建,会同时输出 Web 版和小程序版产物。
Web 版本的包变动通过执行 pnpm run release:fix/minor/major
来进行。
版本变更后,执行 npm publish --access public
进行发布。需要有 npm 发包权限。
小程序的包需要手动修改 package-mp.json
文件。
发布时需要在 packages/xmit/mp-dist
目录下执行 npm publish --access public
进行发布。
使用方在安装后需要手动拷贝文件到开发目录中,例如 cpy node_modules/@xverse/xmit-mp-core/libxmit-mp.wasm ./js/libs/ --flat && cpy node_modules/@xverse/xmit-mp-core/xmit-core.js ./js/libs/ --flat
。 (使用了 cpy-cli
这个 npm 包)。