How to create a Chat app with Bun Using webSockets
Lets Create a Bun Server
bun init
Just press enter.. enter..
Run the file
bun run index.ts`
Implementing WebSockets in JavaScript
Let’s create a simple WebSocket connection in JavaScript. Firstly, ensure your server supports WebSocket connections.
// Creating a new WebSocket instance
const socket = new WebSocket('ws://your-websocket-server.com');
// Connection opened
socket.addEventListener('open', (event) => {
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', (event) => {
console.log('Message from server:', event.data);
});
// Connection closed
socket.addEventListener('close', (event) => {
console.log('Server connection closed:', event.data);
});
In this snippet:
- We create a new
WebSocket
instance, passing the WebSocket server URL. - We attach an event listener for the
open
event, which triggers when the connection is established, sending a greeting to the server. - We listen for any messages from the server with the
message
event. - Finally, we have a listener for the
close
event, which triggers when the connection is closed.
Let's Build a simple WebSocket server with Bun
First rename index.ts to server.ts
index.ts
const server = Bun.serve({
port: 8080,
fetch(req, server) {
// upgrade the request to a WebSocket
if (server.upgrade(req)) {
return; // do not return a Response
}
return new Response("Upgrade failed :(", { status: 500 });
}, // upgrade logic
websocket: {
async message(ws, message) {
console.log("Message was received from server:",message)
ws.send("I received your message")
}, // a message is received
open(ws) {
console.log("Connection opened")
}, // a socket is opened
close(ws, code, message) {
console.log("Connection closed")
}, // a socket is closed
drain(ws) {}, // the socket is ready to receive more data
},
});
console.log(`Listening on ${server.hostname}:${server.port}`);
Now, to start your server, run the following command in the terminal:
bun run server.ts
Creating Chat Room
First let's create a client's UI (a html page)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WebSocket client</title>
</head>
<body>
<button id="sendmessagebutton">Broadcast Message</button>
<button id="sendtoserver">Send Message to server</button>
<p id="logging">Logging:</p>
<script src="client.js"></script>
</body>
</html>
- The "Broadcast Message" button is for sending a message for broadcasting
- The "Send message to server" is for sending message only to server
- The paragraph is for logging things on the client
Now let's change a little bit the client.js
// Creating a new WebSocket instance
const socket = new WebSocket('ws://localhost:8080');
// Connection opened
socket.addEventListener('open', (event) => {
var sayhi = {
"type": "SENDTOSERVER",
"payload": {
"message": "Hello server, How are you?"
}
}
socket.send(JSON.stringify(sayhi));
document.getElementById("logging").innerText += "\n" + "You sent this mesage to the server: " + sayhi.payload.message
document.getElementById("sendmessagebutton").addEventListener("click", () => {
var newmessage = {
"type": "BROADCAST",
"payload": {
"author": "A USER",
"message": "Hi everyone!"
}
}
socket.send(JSON.stringify(newmessage))
document.getElementById("logging").innerText += "\n" + "You sent this mesage for broadcasting to the server: " + newmessage.payload.message
})
document.getElementById("sendtoserver").addEventListener("click", () => {
var newmessage = {
"type": "SENDTOSERVER",
"payload": {
"author": "A USER",
"message": "This message is for server only"
}
}
socket.send(JSON.stringify(newmessage))
})
});
// Listen for messages
socket.addEventListener('message', (event) => {
try {
var message = JSON.parse(event.data);
if (message.type === 'BROADCAST') {
document.getElementById("logging").innerText += "\n" + "A client broadcasted: " + message.payload.message
} else {
document.getElementById("logging").innerText += "\n" + "You received this message: " + message.payload.message
}
} catch (e) {
console.log('Wrong format');
return;
}
});
// Connection closed
socket.addEventListener('close', (event) => {
console.log('Server connection closed:', event.data);
});
We will change the server so it can differentiate the messages that are for broadcasting and for server only.
const wsserver = Bun.serve({
port: 8080,
fetch(req, server) {
// upgrade the request to a WebSocket
if (server.upgrade(req)) {
return; // do not return a Response
}
return new Response("Upgrade failed :(", { status: 500 });
}, // upgrade logic
websocket: {
async message(ws, msg) {
console.log("Message was received from server:", msg)
var message;
try {
message = JSON.parse(msg.toString());
} catch (e) {
console.log('Wrong format');
return;
}
if (message.type === 'BROADCAST') {
// Broadcast the message to all connected clients
var newmessage = {
"type": "BROADCAST",
"payload": {
"author": "Server",
"message": message.payload.message
}
}
ws.publish("chat",JSON.stringify(newmessage))
}
if (message.type === 'SENDTOSERVER') {
var respond = {
"type": "SERVER_MESSAGE",
"payload": {
"author": "Server",
"message": "I received your message:<<" + message.payload.message + ">>"
}
}
ws.send(JSON.stringify(respond));
}
}, // a message is received
async open(ws) {
ws.subscribe("chat")
console.log("Connection opened and you subscribed on chat")
}, // a socket is opened
async close(ws, code, message) {
console.log("Connection closed")
}, // a socket is closed
async drain(ws) { }, // the socket is ready to receive more data
},
});
console.log(`Listening on ${wsserver.hostname}:${wsserver.port}`);
Let's test things:
run node server.js
Then press the Go Live button on visual studio code to fire up a client
You should see this:
If you open a second tab you will connect a second client:
Then you can broadcast messages(press "Broadcast Message") The server will receive the message and will broadcast it to the clients (except sender)
Also, you can send messages only to the server and get a response
That's for now!
You can find the code of this article here : GitHub Repository
Sources
bun.sh Set per-socket contextual data on a WebSocket with Bun