Setting Up Socket.io with Express in Node.js Server and Client Configuration
Learn how to set up Socket.io with your Express Node.js server installation, server configuration, client setup, CORS, and authentication middleware.
Setting Up Socket.io with Express in Node.js
Socket.io is the most popular WebSocket library for Node.js. It adds auto-reconnection, rooms, and fallback support on top of raw WebSockets.
Step 1: Install Socket.io
npm install socket.io
Step 2: Server Setup
// src/server.js const http = require("http"); const express = require("express"); const socketio = require("socket.io"); const app = require("./app"); const server = http.createServer(app); const io = socketio(server, { cors: { origin: process.env.CLIENT_URL, methods: ["GET", "POST"], credentials: true } }); // Store io globally for use in routes app.set("io", io); // Socket.io events require("./config/socketEvents")(io); const PORT = process.env.PORT || 3000; server.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
Step 3: Socket Events Handler
// src/config/socketEvents.js module.exports = (io) => { // Authentication middleware io.use(async (socket, next) => { try { const token = socket.handshake.auth.token; if (!token) { return next(new Error("Authentication required")); } const decoded = jwt.verify(token, process.env.JWT_SECRET); const user = await User.findById(decoded._id); if (!user) { return next(new Error("User not found")); } socket.user = user; socket.userId = user._id.toString(); next(); } catch (err) { next(new Error("Authentication failed")); } }); io.on("connection", (socket) => { console.log(`User connected: ${socket.user.firstName}`); // Store online user onlineUsers.set(socket.userId, socket.id); // Join personal room (for direct notifications) socket.join(socket.userId); // Handle events socket.on("join:chat", (data) => handleJoinChat(socket, data)); socket.on("message:send", (data) => handleMessageSend(socket, io, data)); socket.on("typing:start", (data) => handleTypingStart(socket, data)); socket.on("typing:stop", (data) => handleTypingStop(socket, data)); socket.on("disconnect", () => { console.log(`User disconnected: ${socket.user.firstName}`); onlineUsers.delete(socket.userId); }); }); }; const onlineUsers = new Map(); module.exports.onlineUsers = onlineUsers;
Step 4: Client Setup (React)
npm install socket.io-client
// src/utils/socket.js import { io } from "socket.io-client"; const getCookie = (name) => { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(";").shift(); }; const token = getCookie("token"); export const socket = io(process.env.VITE_SOCKET_URL || "http://localhost:3000", { withCredentials: true, auth: { token } }); socket.on("connect", () => { console.log("Connected to server:", socket.id); }); socket.on("disconnect", () => { console.log("Disconnected from server"); }); socket.on("connect_error", (err) => { console.error("Connection error:", err.message); });
Step 5: Using Socket.io in React Components
import { useEffect, useState } from "react"; import { socket } from "../utils/socket"; const ChatComponent = ({ targetUserId }) => { const [messages, setMessages] = useState([]); useEffect(() => { // Join chat room socket.emit("join:chat", { targetUserId }); // Listen for new messages socket.on("message:received", (message) => { setMessages((prev) => [...prev, message]); }); // Listen for typing socket.on("typing:update", (data) => { // Update typing indicator }); // Cleanup on unmount return () => { socket.off("message:received"); socket.off("typing:update"); }; }, [targetUserId]); const sendMessage = (text) => { socket.emit("message:send", { targetUserId, text }); }; return ( <div> {messages.map((msg) => ( <div key={msg._id}>{msg.text}</div> ))} <button onClick={() => sendMessage("Hello!")}>Send</button> </div> ); };
The Takeaway
Setting up Socket.io involves: creating an HTTP server with Express, initializing socketio with CORS config, adding JWT authentication middleware, handling connection and disconnection events, storing online users, and setting up event handlers. On the client, connect with io() passing the auth token, and listen for events with socket.on() and emit with socket.emit(). Always clean up listeners in React useEffect.
Create an HTTP server from the Express app (http.createServer(app)), initialize socketio with CORS config (socketio(server, { cors: { origin, credentials: true } })), add authentication middleware with io.use(), handle connection events with io.on('connection', ...), and listen on the HTTP server (not the Express app).
Use io.use() middleware: read the token from socket.handshake.auth.token, verify with jwt.verify(), find the user, and attach to socket.user. If verification fails, call next(new Error('Authentication failed')). The client passes the token in the auth option when connecting.
Install socket.io-client, import { io } from 'socket.io-client', connect with io(url, { withCredentials: true, auth: { token } }), listen with socket.on('event', callback), and emit with socket.emit('event', data). Clean up listeners in useEffect return with socket.off().
withCredentials: true allows the client to send cookies (including the JWT auth token) with cross-origin WebSocket connections. Without it, the auth middleware can't verify the user, and the connection will be rejected.
In useEffect, emit join events with socket.emit(), listen for events with socket.on(), and return a cleanup function that calls socket.off() for each event. This prevents duplicate listeners when the component re-renders or unmounts.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

