WebSocket 助手
WebSocket 助手为 Hono 应用提供服务端 WebSocket 支持。目前已提供 Cloudflare Workers/Pages、Deno 与 Bun 的适配器。
导入
ts
import { Hono } from 'hono'
import { upgradeWebSocket } from 'hono/cloudflare-workers'ts
import { Hono } from 'hono'
import { upgradeWebSocket } from 'hono/deno'ts
import { Hono } from 'hono'
import { upgradeWebSocket, websocket } from 'hono/bun'
// ...
export default {
fetch: app.fetch,
websocket,
}若使用 Node.js,可参考 @hono/node-ws。
upgradeWebSocket()
upgradeWebSocket() 会返回一个用于处理 WebSocket 的处理器。
ts
const app = new Hono()
app.get(
'/ws',
upgradeWebSocket((c) => {
return {
onMessage(event, ws) {
console.log(`Message from client: ${event.data}`)
ws.send('Hello from server!')
},
onClose: () => {
console.log('Connection closed')
},
}
})
)可用事件包括:
onOpen—— 当前 Cloudflare Workers 尚未支持。onMessageonCloseonError
WARNING
如果在使用 WebSocket 助手的路由上同时使用会修改头部的中间件(例如 CORS),可能会遇到 “无法修改不可变头部” 的错误,因为 upgradeWebSocket() 内部也会修改头部。使用 WebSocket 助手与中间件时请格外注意。
RPC 模式
通过 WebSocket 助手定义的处理器可配合 RPC 模式使用。
ts
// server.ts
const wsApp = app.get(
'/ws',
upgradeWebSocket((c) => {
// ...
})
)
export type WebSocketApp = typeof wsApp
// client.ts
const client = hc<WebSocketApp>('http://localhost:8787')
const socket = client.ws.$ws() // 客户端的 WebSocket 对象示例
以下示例展示了如何使用 WebSocket 助手。
服务端与客户端
ts
// server.ts
import { Hono } from 'hono'
import { upgradeWebSocket } from 'hono/cloudflare-workers'
const app = new Hono().get(
'/ws',
upgradeWebSocket(() => {
return {
onMessage: (event) => {
console.log(event.data)
},
}
})
)
export default appts
// client.ts
import { hc } from 'hono/client'
import type app from './server'
const client = hc<typeof app>('http://localhost:8787')
const ws = client.ws.$ws(0)
ws.addEventListener('open', () => {
setInterval(() => {
ws.send(new Date().toString())
}, 1000)
})Bun + JSX
tsx
import { Hono } from 'hono'
import { createBunWebSocket } from 'hono/bun'
import { html } from 'hono/html'
const { upgradeWebSocket, websocket } = createBunWebSocket()
const app = new Hono()
app.get('/', (c) => {
return c.html(
<html>
<head>
<meta charset='UTF-8' />
</head>
<body>
<div id='now-time'></div>
{html`
<script>
const ws = new WebSocket('ws://localhost:3000/ws')
const $nowTime = document.getElementById('now-time')
ws.onmessage = (event) => {
$nowTime.textContent = event.data
}
</script>
`}
</body>
</html>
)
})
const ws = app.get(
'/ws',
upgradeWebSocket((c) => {
let intervalId
return {
onOpen(_event, ws) {
intervalId = setInterval(() => {
ws.send(new Date().toString())
}, 200)
},
onClose() {
clearInterval(intervalId)
},
}
})
)
export default {
fetch: app.fetch,
websocket,
}