Skip to main content
Bun.serve() 支持服务器端 WebSockets,具备实时压缩、TLS 支持以及 Bun 原生的发布-订阅 API。
⚡️ 吞吐量提升 7 倍Bun 的 WebSockets 速度很快。在 Linux x64 上运行的简单聊天室中,Bun 每秒处理的消息数是 Node.js + "ws" 的 7 倍。Bun 内部的 WebSocket 实现基于 uWebSockets。

启动 WebSocket 服务器

以下服务器使用 Bun.serve 构建,会在 fetch 处理程序中将每个传入请求升级为 WebSocket 连接。你可以在 websocket 参数中声明套接字处理程序。
server.ts
Bun 支持以下 WebSocket 事件处理程序:
server.ts
在 Bun 中,你只需为每个服务器声明一次处理程序,而不是为每个套接字分别声明。你可以将单个 WebSocketHandler 对象传递给 Bun.serve(),其中包含 open、message、close、drain 和 error 方法。这种设计不同于客户端的 WebSocket 类,后者扩展了 EventTarget(onmessage、onopen、onclose)。客户端通常只会打开少量套接字连接,因此基于事件的 API 在客户端很适用。但服务器端往往会打开 大量 连接,这意味着:
  • 为每个连接添加/移除事件监听器所花费的时间会累积起来
  • 为每个连接存储回调函数引用会占用额外内存
  • 通常,人们会为每个连接创建新函数,这同样意味着更多的内存开销
在所有连接之间重复使用同一个处理程序对象,可以避免这两项开销。
每个处理程序的第一个参数都是负责处理该事件的 ServerWebSocket 实例。ServerWebSocket 类是一个快速的、原生 Bun 实现的 WebSocket,并提供了一些额外功能。
server.ts

发送消息

每个 ServerWebSocket 实例都有 .send() 方法用于向客户端发送消息,支持多种输入类型。
server.ts

头信息

升级成功后,Bun 会根据规范发送 101 Switching Protocols 响应。要为此 Response 附加额外的 headers,请将它们传递给 server.upgrade()。
server.ts

上下文数据

在 .upgrade() 调用中为新的 WebSocket 附加上下文 data。它可在 WebSocket 处理程序中的 ws.data 属性上访问。 要为 ws.data 进行强类型定义,可在 websocket 处理对象里添加 data 属性,从而为所有生命周期钩子中的 ws.data 指定类型。
server.ts
以前,你可以像 Bun.serve<MyData>({...}) 这样通过 Bun.serve 上的类型参数指定 ws.data 的类型。由于 TypeScript 的一项限制,Bun 移除了这种写法,改用 data 属性。
要从浏览器连接到此服务器,可以创建一个新的 WebSocket。
browser.js
用户身份识别浏览器会将页面上设置的 Cookie 与 WebSocket 升级请求一同发送。它们可在 fetch 处理程序中的 req.headers 上获取。解析这些 Cookie 以识别连接的用户,并据此设置 data。

发布/订阅

Bun 的 ServerWebSocket 包含用于基于主题进行广播的原生发布-订阅 API。你可以使用字符串标识符指定主题。单个套接字可以通过 .subscribe() 订阅主题,并通过 .publish() 向该主题的所有其他订阅者发送消息(不包括自身)。这种基于主题的广播 API 类似于 MQTT 和 Redis Pub/Sub。
server.ts
调用 .publish(topic, data) 会向主题的所有订阅者发送消息,_但不包括_调用 .publish() 的套接字。要向主题的所有订阅者发送消息,请使用 Server 实例上的 .publish() 方法。

压缩

使用 perMessageDeflate 参数启用逐消息压缩。
server.ts
要压缩单条消息,请将一个 boolean 作为第二个参数传递给 .send()。
要对压缩特性进行精细控制,请参考参考文档。

背压管理

ServerWebSocket 的 .send(message) 方法返回一个 number 表示操作结果。
  • -1 — 消息已入队,但存在背压(backpressure)
  • 0 — 由于连接问题,消息已丢弃
  • 1+ — 发送的字节数

超时和限制

默认情况下,Bun 会关闭处于空闲状态超过 120 秒的 WebSocket 连接。使用 idleTimeout 参数进行配置。
如果收到的消息大于 16 MB,Bun 也会关闭 WebSocket 连接。使用 maxPayloadLength 参数进行配置。

连接到 WebSocket 服务器

Bun 实现了 WebSocket 类。创建连接至 ws:// 或 wss:// 服务器的 WebSocket 客户端实例,类似于浏览器中的用法。
浏览器会将页面上设置的 Cookie 与 WebSocket 升级请求一同发送。这是 WebSocket API 的标准特性。 在 Bun 中,你还可以直接在构造函数中设置自定义请求头。这是 Bun 对 WebSocket 标准的特有扩展。在浏览器中无法使用。
给套接字添加事件监听器的方法:

背压管理

浏览器的 WebSocket API 无法减慢发送速度超过你处理速度的对端:传入的消息会无限制地缓存在内存中。Bun 添加了 pause() 和 resume(),用于暂停和恢复从底层套接字读取数据,从而让发送方感受到 TCP 背压。这是 Bun 特有的扩展。在浏览器中无法使用。
pause() 和 resume() 在操作生效时(或连接中的套接字打开后生效时)返回 true,没有可操作的套接字时则返回 false;socket.isPaused 用于报告当前状态。调用 pause() 时已经解码的消息仍可能被传递。ws 包中的 pause()、resume() 和 isPaused 对应相同的方法。

参考

See Typescript Definitions