Guide

WebSocket

Nitro natively support a cross platform WebSocket API


Nitro natively supports runtime agnostic WebSocket API using CrossWS and H3 WebSocket.

Read more in WebSocket in MDN.
Read more in CrossWS.

Opt-in to the experimental feature

WebSockets support is currently experimental. See unjs/nitro#2171 for platform support status.

In order to enable websocket support you need to enable the experimental websocket feature flag.

export default defineNitroConfig({
  experimental: {
    websocket: true
  }
})

Usage

Create a websocket handler in routes/_ws.ts (or server/routes/_ws.ts for Nuxt).

You can use any route like routes/chatroom.ts to register upgrade handler on /chatroom.
_ws.ts
export default defineWebSocketHandler({
  open(peer) {
    console.log("[ws] open", peer);
  },

  message(peer, message) {
    console.log("[ws] message", peer, message);
    if (message.text().includes("ping")) {
      peer.send("pong");
    }
  },

  close(peer, event) {
    console.log("[ws] close", peer, event);
  },

  error(peer, error) {
    console.log("[ws] error", peer, error);
  },
});
Nitro allows you defining multiple websocket handlers using same routing of event handlers.

Use a client to connect to server. Example: (routes/websocket.ts or server/routes/websocket.ts for Nuxt)

index.ts
export default defineEventHandler(() => {
  return $fetch(
    "https://raw.githubusercontent.com/unjs/crossws/main/examples/h3/public/index.html"
  );
});

Now you can try it on /websocket route!

Check out our chat demo using Nitro Websocket API.

Server Sent Events (SSE)

As an alternative to WebSockets, you can use Server-sent events

Example

Create an SSE handler in routes/sse.ts (or server/routes/sse.ts for Nuxt).

sse.ts
export default defineEventHandler(async (event) => {
  const eventStream = createEventStream(event)
  
  const interval = setInterval(async () => {
    await eventStream.push(`Message @ ${new Date().toLocaleTimeString()}`)
  }, 1000)
  
  eventStream.onClosed(async () => {
    clearInterval(interval)
    await eventStream.close()
  })
  
  return eventStream.send()
})

Then connect to this SSE endpoint from the client

const eventSource = new EventSource('http://localhost:3000/sse')
    
eventSource.onmessage = (event) => {
  console.log(event.data)
}
Read more in SSE guide in H3.