Birpc
Message-based two-way remote procedure call.
Install / Use
/learn @antfu-collective/BirpcREADME
birpc
Message-based two-way remote procedure call. Useful for WebSockets and Workers communication.
Features
- Intuitive - call remote functions just like locals, with Promise to get the response
- TypeScript - safe function calls for arguments and returns
- Protocol agonostic - WebSocket, MessageChannel, any protocols with messages communication would work!
- Zero deps, ~0.5KB
Examples
Using WebSocket
When using WebSocket, you need to pass your custom serializer and deserializer.
Client
import type { ServerFunctions } from './types'
const ws = new WebSocket('ws://url')
const clientFunctions: ClientFunctions = {
hey(name: string) {
return `Hey ${name} from client`
}
}
const rpc = createBirpc<ServerFunctions>(
clientFunctions,
{
post: data => ws.send(data),
on: fn => ws.on('message', fn),
// these are required when using WebSocket
serialize: v => JSON.stringify(v),
deserialize: v => JSON.parse(v),
},
)
await rpc.hi('Client') // Hi Client from server
Server
import type { ClientFunctions } from './types'
import { WebSocketServer } from 'ws'
const serverFunctions: ServerFunctions = {
hi(name: string) {
return `Hi ${name} from server`
}
}
const wss = new WebSocketServer()
wss.on('connection', (ws) => {
const rpc = createBirpc<ClientFunctions>(
serverFunctions,
{
post: data => ws.send(data),
on: fn => ws.on('message', fn),
serialize: v => JSON.stringify(v),
deserialize: v => JSON.parse(v),
},
)
await rpc.hey('Server') // Hey Server from client
})
Circular References
As JSON.stringify does not supporting circular references, we recommend using structured-clone-es as the serializer when you expect to have circular references.
import { parse, stringify } from 'structured-clone-es'
const rpc = createBirpc<ServerFunctions>(
functions,
{
post: data => ws.send(data),
on: fn => ws.on('message', fn),
// use structured-clone-es as serializer
serialize: v => stringify(v),
deserialize: v => parse(v),
},
)
Using MessageChannel
MessageChannel will automatically serialize the message and support circular references out-of-box.
export const channel = new MessageChannel()
Bob
import type { AliceFunctions } from './types'
import { channel } from './channel'
const Bob: BobFunctions = {
hey(name: string) {
return `Hey ${name}, I am Bob`
}
}
const rpc = createBirpc<AliceFunctions>(
Bob,
{
post: data => channel.port1.postMessage(data),
on: fn => channel.port1.on('message', fn),
},
)
await rpc.hi('Bob') // Hi Bob, I am Alice
Alice
import type { BobFunctions } from './types'
import { channel } from './channel'
const Alice: AliceFunctions = {
hi(name: string) {
return `Hi ${name}, I am Alice`
}
}
const rpc = createBirpc<BobFunctions>(
Alice,
{
post: data => channel.port2.postMessage(data),
on: fn => channel.port2.on('message', fn),
},
)
await rpc.hey('Alice') // Hey Alice, I am Bob
One-to-multiple Communication
Refer to ./test/group.test.ts as an example.
Sponsors
<p align="center"> <a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg"> <img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg'/> </a> </p>License
MIT License © 2021 Anthony Fu
Related Skills
node-connect
353.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
111.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
353.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
353.3kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
