Skip to content

Commit 97f33d9

Browse files
docs: how to use with Nuxt
Related: socketio/socket.io#4894
1 parent 2324567 commit 97f33d9

File tree

2 files changed

+190
-0
lines changed

2 files changed

+190
-0
lines changed

src/pages/get-started/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ If you are new to Socket.IO, we recommend checking out our [tutorial](/docs/v4/t
2525
- [React](/how-to/use-with-react)
2626
- [Vue 3](/how-to/use-with-vue)
2727
- [Next.js](/how-to/use-with-nextjs)
28+
- [Nuxt](/how-to/use-with-nuxt)
2829

2930
## How to...
3031

src/pages/how-to/use-with-nuxt.md

+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
---
2+
title: How to use with Nuxt
3+
---
4+
5+
# How to use with Nuxt
6+
7+
This guide shows how to use Socket.IO within a [Nuxt](https://nuxt.com/) application.
8+
9+
## Server
10+
11+
Under the hood, Nuxt uses [Nitro](https://nitro.unjs.io/) to handle the HTTP requests.
12+
13+
There are two steps to attach a Socket.IO server to a Nitro server:
14+
15+
### Enable WebSockets
16+
17+
WebSockets support in Nitro is currently [experimental](https://github.com/unjs/nitro/issues/2171), so it needs to be manually enabled:
18+
19+
```diff title="nuxt.config.js"
20+
// https://nuxt.com/docs/api/configuration/nuxt-config
21+
22+
export default defineNuxtConfig({
23+
devtools: {
24+
enabled: true
25+
},
26+
+ nitro: {
27+
+ experimental: {
28+
+ websocket: true
29+
+ },
30+
+ }
31+
})
32+
```
33+
34+
Reference: https://nitro.unjs.io/guide/websocket
35+
36+
### Hook the Socket.IO server
37+
38+
Our Socket.IO server is created in a [Nitro plugin](https://nitro.unjs.io/guide/plugins):
39+
40+
```ts title="server/plugins/socket.io.ts"
41+
import type { NitroApp } from "nitropack";
42+
import { Server as Engine } from "engine.io";
43+
import { Server } from "socket.io";
44+
import { defineEventHandler } from "h3";
45+
46+
export default defineNitroPlugin((nitroApp: NitroApp) => {
47+
const engine = new Engine();
48+
const io = new Server();
49+
50+
io.bind(engine);
51+
52+
io.on("connection", (socket) => {
53+
// ...
54+
});
55+
56+
nitroApp.router.use("/socket.io/", defineEventHandler({
57+
handler(event) {
58+
engine.handleRequest(event.node.req, event.node.res);
59+
event._handled = true;
60+
},
61+
websocket: {
62+
open(peer) {
63+
const nodeContext = peer.ctx.node;
64+
const req = nodeContext.req;
65+
66+
// @ts-expect-error private method
67+
engine.prepare(req);
68+
69+
const rawSocket = nodeContext.req.socket;
70+
const websocket = nodeContext.ws;
71+
72+
// @ts-expect-error private method
73+
engine.onWebSocket(req, rawSocket, websocket);
74+
}
75+
}
76+
}));
77+
});
78+
```
79+
80+
And voilà!
81+
82+
## Client
83+
84+
On the client side, all tips from our [Vue 3 guide](/how-to/use-with-vue) are valid.
85+
86+
The only difference is that you need to exclude the Socket.IO client from server-side rendering (SSR):
87+
88+
89+
Structure:
90+
91+
```
92+
├── components
93+
│ ├── Connection.client.vue
94+
│ └── socket.ts
95+
...
96+
```
97+
98+
```js title="components/socket.ts"
99+
import { io } from "socket.io-client";
100+
101+
export const socket = io();
102+
```
103+
104+
105+
106+
```html title="components/Connection.client.vue"
107+
<script setup>
108+
import { socket } from "./socket";
109+
110+
const isConnected = ref(false);
111+
const transport = ref("N/A");
112+
113+
if (socket.connected) {
114+
onConnect();
115+
}
116+
117+
function onConnect() {
118+
isConnected.value = true;
119+
transport.value = socket.io.engine.transport.name;
120+
121+
socket.io.engine.on("upgrade", (rawTransport) => {
122+
transport.value = rawTransport.name;
123+
});
124+
}
125+
126+
function onDisconnect() {
127+
isConnected.value = false;
128+
transport.value = "N/A";
129+
}
130+
131+
socket.on("connect", onConnect);
132+
socket.on("disconnect", onDisconnect);
133+
134+
onBeforeUnmount(() => {
135+
socket.off("connect", onConnect);
136+
socket.off("disconnect", onDisconnect);
137+
});
138+
139+
</script>
140+
141+
<template>
142+
<div>
143+
<p>Status: {{ isConnected ? "connected" : "disconnected" }}</p>
144+
<p>Transport: {{ transport }}</p>
145+
</div>
146+
</template>
147+
148+
```
149+
150+
:::note
151+
152+
The `.client` suffix in `Connection.client.vue` indicates that the component is meant to be rendered only client-side (no SSR).
153+
154+
Reference: https://nuxt.com/docs/guide/directory-structure/components#client-components
155+
156+
:::
157+
158+
In the example above, the `transport` variable is the low-level transport used to establish the Socket.IO connection, which can be either:
159+
160+
- HTTP long-polling (`"polling"`)
161+
- [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) (`"websocket"`)
162+
- [WebTransport](https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API) (`"webtransport"`)
163+
164+
If everything went well, you should see:
165+
166+
```
167+
Status: connected
168+
Transport: websocket
169+
```
170+
171+
You can then exchange messages between the Socket.IO server and client with:
172+
173+
- `socket.emit()` to send messages
174+
175+
```js
176+
socket.emit("hello", "world");
177+
```
178+
179+
- `socket.on()` to receive messages
180+
181+
```js
182+
socket.on("hello", (value) => {
183+
// ...
184+
});
185+
```
186+
187+
That's all folks, thanks for reading!
188+
189+
[Back to the list of examples](/get-started/)

0 commit comments

Comments
 (0)