DEV Community

Cover image for Hono with Server Sent Events 🔥💌
Yanael
Yanael

Posted on

Hono with Server Sent Events 🔥💌

Hono is a web framework designed to run on any JavaScript runtime, making it suitable for edge deployments. It can be combined with Server-Sent Events (SSE) to create real-time web applications with a focus on sending server updates to the client.

  +--------+     +--------+
  | Client |<--->| Server |
  +---+----+     +----+---+
      |               |
      | 1. GET /sse   |
      +-------------->|
      | 2. 200 OK     |
      | (SSE Headers) |
      |<--------------+
      | 3. Event 1    |
      | 'data:...'    |
      |<--------------+
      | 4. Event 2    |
      | 'data:...'    |
      |<--------------+
     ...             ...
Enter fullscreen mode Exit fullscreen mode

Setting up SSE with Hono

1. Setting Headers

For SSE to function correctly, specific headers need to be set. By setting them up inside a middleware, we can ensure they're consistently applied.

app.use('/sse/*', async (c, next) => {
    c.header('Content-Type', 'text/event-stream');
    c.header('Cache-Control', 'no-cache');
    c.header('Connection', 'keep-alive');
    await next();
});
Enter fullscreen mode Exit fullscreen mode

These headers ensure the client maintains an open connection and receives the streamed events as intended.

2. Sending Data with SSE Format

With Hono, we can utilize its streaming feature to start streaming content:

app.get('/sse', (c) => {
    return c.stream(async (stream) => {
        stream.write('data: hello\n\n');
        stream.write('data: world\n\n');
    });
});
Enter fullscreen mode Exit fullscreen mode

3. Using Custom Event Types

Beyond basic data, SSE allows us to send custom event types to handle specific client-side actions:

stream.write('event: close\n');
stream.write('data: close\n\n');
Enter fullscreen mode Exit fullscreen mode

4. Adding Event IDs

To keep track of events, especially useful for error recovery:

stream.write('id: 0\n');
Enter fullscreen mode Exit fullscreen mode

5. Setting Retry Intervals

In case of a connection drop, instruct the client when to attempt a reconnection:

stream.write('retry: 1000\n'); // In milliseconds
Enter fullscreen mode Exit fullscreen mode

A Complete Hono-SSE Endpoint Example

import { Hono } from 'hono'
import { cors } from 'hono/cors'


const app = new Hono()

app.use('*', cors(
    {
        origin: '*',
        allowMethods: ['GET'],
        allowHeaders: ['Content-Type'],
    }
))

app.get('/', (c) => c.text('Hello Hono!'))

app.use('/sse/*', async (c, next) => {
    c.header('Content-Type', 'text/event-stream');
    c.header('Cache-Control', 'no-cache');
    c.header('Connection', 'keep-alive');
    await next();
});

app.get('/sse', (c) => {

    return c.stream(async (stream) => {
        stream.write('retry: 1000\n');

        stream.write('id: 0\n');
        stream.write('data: hello\n\n');

        stream.write('id: 1\n');
        stream.write('data: world\n\n');

        stream.write('event: close\n');
        stream.write('data: close\n\n');
    })

});

export default app;
Enter fullscreen mode Exit fullscreen mode

Client-Side Implementation

To use the power of SSE on the client side, a simple listener can be implemented:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>SSE Example</title>
</head>

<body>
    <h1>SSE Example</h1>
    <div id="sse-data"></div>

    <script>
        const baseURL = "http://localhost:3000";
        const sseData = document.getElementById('sse-data');

        const eventSource = new EventSource(`${baseURL}/sse`);

        eventSource.onmessage = (event) => {
            sseData.innerHTML += event.data + '<br>';
        };

        eventSource.addEventListener("close", (event) => {
            console.log('Received "close" event. Closing connection...');
            eventSource.close();
        });

        eventSource.onerror = (error) => {
            console.error('EventSource error:', error);
        };
    </script>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

Visit the page in your browser, and watch as SSE seamlessly delivers server updates.

Conclusion

Combining Hono with SSE opens doors to real-time, dynamic web applications.

Consider exploring advanced Hono features and more about SSE:

Code


Receive my stream of work on:

Top comments (0)