Feathers uses Server-Sent Events (SSE) for real-time communication between the server and client. SSE is built on top of standard HTTP, requires no additional dependencies, and works across all JavaScript runtimes.
When the sse option is set on the fetch client, the client will automatically establish an SSE connection during app.setup() to receive real-time events from the server via channels.
The sse option can be a string (the SSE service path) or an options object:
import { feathers } from 'feathers'
import { fetchClient } from 'feathers/client'
const app = feathers()
// Simple: just the SSE service path
app.configure(fetchClient(fetch, {
baseUrl: 'http://localhost:3030',
sse: 'sse'
}))
// With options
app.configure(fetchClient(fetch, {
baseUrl: 'http://localhost:3030',
sse: {
path: 'sse',
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
params: {
query: { channel: 'my-channel' }
}
}
}))
// Start the SSE connection
await app.setup()
| Option | Default | Description |
|---|---|---|
path | (required) | The SSE service path registered on the server |
reconnectionDelay | 1000 | Initial delay (ms) before reconnecting |
reconnectionDelayMax | 5000 | Maximum delay (ms) between reconnection attempts |
params | {} | Default params to pass when establishing the SSE connection (e.g. query parameters) |
The SSE service (app.service('<sse-path>')) emits the following events:
Emitted when the SSE connection is successfully established. The callback receives an AbortController that can be used to close the connection.
app.service('sse').on('connected', (controller: AbortController) => {
console.log('SSE connected')
// To disconnect later:
// controller.abort()
})
Emitted when the SSE connection is lost. The callback receives the error that caused the disconnection.
app.service('sse').on('disconnected', (error: Error) => {
console.log('SSE disconnected', error)
})
Emitted when a reconnection attempt is about to be made. The callback receives an object with delay, attempt, and timeout properties.
app.service('sse').on('reconnecting', (info) => {
console.log(`Reconnecting (attempt ${info.attempt}) in ${info.delay}ms`)
})
Once connected, real-time events published through channels are automatically dispatched to the appropriate service on the client:
const app = feathers()
app.configure(fetchClient(fetch, {
baseUrl: 'http://localhost:3030',
sse: 'sse'
}))
await app.setup()
// Listen for real-time events just like on the server
app.service('messages').on('created', (message) => {
console.log('New message created', message)
})
app.service('messages').on('patched', (message) => {
console.log('Message patched', message)
})
The SSE client automatically reconnects when the connection is lost. Reconnection uses exponential backoff with jitter:
reconnectionDelay (default 1000ms)reconnectionDelayMax (default 5000ms)To manually disconnect the SSE connection, use the AbortController provided by the connected event:
let controller: AbortController
app.service('sse').on('connected', (ctrl: AbortController) => {
controller = ctrl
})
await app.setup()
// Later, to disconnect:
controller.abort()