cross-sse
v0.1.1
Published
Cross-platform Server-Sent Events client for browsers and WeChat Mini Program. 跨端 SSE 客户端,支持浏览器和微信小程序。
Maintainers
Readme
cross-sse
跨端 Server-Sent Events 客户端:浏览器 / H5 / 微信小程序统一 API,专为 AI 流式对话场景设计。
A cross-platform SSE client for browsers, H5 and WeChat Mini Program, built for streaming AI chat.
为什么做这个
主流 SSE 库要么只支持浏览器(依赖 fetch 或 EventSource),要么和 uniapp 强耦合。在做企业级 AI 对话应用时,需要在「同一份业务代码」里同时跑浏览器 H5 端和微信小程序端,于是抽出了这个零依赖的跨端实现。
核心要点:
- 浏览器 / H5:基于 @microsoft/fetch-event-source(peerDependency,可选)支持自定义 Header、POST、AbortController
- 微信小程序:基于
wx.request的enableChunked+onChunkReceived,自实现 SSE 协议解析器(无需 polyfill) - 零运行时依赖(小程序入口)、统一错误模型、可独立使用的解析器、完整 TypeScript 类型
- 解析器单元测试覆盖:UTF-8 多字节边界、
\r\n/\n/\r三种行尾、字节流任意切分、多 data 行合并等场景
安装
bun add cross-sse
# 浏览器场景额外安装
bun add @microsoft/fetch-event-source用法
浏览器 / H5
import { sse } from 'cross-sse'
const handle = sse({
url: 'https://api.example.com/chat/stream',
method: 'POST',
headers: {
Authorization: 'Bearer xxx',
'Content-Type': 'application/json',
},
body: { prompt: '你好' },
onMessage(msg) {
// msg.event / msg.data / msg.id / msg.retry
console.log(msg.data)
},
onClose() {
console.log('stream end')
},
onError(err) {
console.error(err.code, err.message)
},
})
// 中止
handle.abort()微信小程序
import { sse } from 'cross-sse/weapp'
const handle = sse({
url: 'https://api.example.com/chat/stream',
method: 'POST',
headers: {
Authorization: 'Bearer xxx',
'Content-Type': 'application/json',
},
body: { prompt: '你好' },
onMessage(msg) {
console.log(msg.data)
},
onClose() {},
onError(err) {
wx.showToast({ title: err.message, icon: 'none' })
},
})
// 离开页面时
handle.abort()微信小程序基础库要求:
wx.request的enableChunked需要 ≥ 2.20.0- 内置
TextDecoder需要 ≥ 2.21.0;更低版本请通过decoder选项传入 polyfill
手动策略(用于自定义平台 / 测试)
import { sse, type SseStrategy } from 'cross-sse/manual'
const myStrategy: SseStrategy = (options) => {
// 自己实现请求与字节流;可以复用 SseParser
// ...
return { abort() {}, get aborted() { return false } }
}
const handle = sse(myStrategy, { url: '...', onMessage: console.log })直接使用解析器
如果你已经有自己的网络层,只想要一个标准 SSE 解析器:
import { SseParser } from 'cross-sse/parser'
const parser = new SseParser((msg) => {
console.log(msg.event, msg.data)
})
// 微信小程序等环境可传入自定义 decoder
const parser2 = new SseParser((msg) => { /* ... */ }, {
decoder: new TextDecoder('utf-8'),
})
parser.feed(new Uint8Array([/* 字节块 1 */]))
parser.feed(new Uint8Array([/* 字节块 2 */]))
// ...
parser.reset() // 中止或重连时清空内部状态API
sse(options): SseHandle
| 选项 | 类型 | 说明 |
|---|---|---|
| url | string | 必填 |
| method | 'GET' \| 'POST' \| 'PUT' \| 'DELETE' | 默认 GET |
| headers | Record<string, string> | 自定义请求头 |
| body | string \| Record<string, unknown> | 对象会被 JSON.stringify |
| onMessage | (msg: SseMessage) => void | 每条消息回调 |
| onClose | () => void | 流正常结束 |
| onError | (err: SseError) => void | 出错(终态) |
| decoder | { decode(input?: Uint8Array): string } | 自定义文本解码器 |
注:当前内置策略(web / weapp)在
abort()后静默结束,不会触发onError。
SseMessage
interface SseMessage {
event: string // 默认 'message'
data: string // 多行 data: 用 \n 连接
id: string
retry: number | undefined
}SseError
class SseError extends Error {
code:
| 'NETWORK_ERROR'
| 'BAD_STATUS'
| 'PARSE_ERROR'
| 'UNSUPPORTED_PLATFORM'
}SseHandle
interface SseHandle {
abort(): void
readonly aborted: boolean
}与原生 EventSource 对比
| 能力 | 原生 EventSource | 本库(浏览器) | 本库(小程序) | |---|---|---|---| | 自定义 Header | ❌ | ✅ | ✅ | | POST/PUT | ❌ | ✅ | ✅ | | 中止 | 只能 close | AbortController | abort | | 后台 tab 保持 | 依赖浏览器 | 默认开启 | n/a | | 微信小程序 | ❌ | ❌ | ✅ |
开发
# 安装依赖
bun install
# 运行测试
bun test
# 构建库 + 类型声明
bun run prepublishOnly发布
bun run prepublishOnly
npm publish --registry https://registry.npmjs.org/实战来源
抽取自一套企业级 AI 对话产品,同时跑浏览器和微信小程序两端,主要用于:
- 流式对话(chunked 文本输出)
- 长任务进度推送
- 后端事件通知
代码经过线上生产验证。
License
MIT © 2026 Liu Xiaosong
