Real-time features need a connection that stays open after the first request, so WebSocket is a fit for chat, presence, dashboards, and browser-to-server updates. In Node.js, a small local server can accept a client, send a greeting, and echo a message before the application grows into routes, rooms, or authentication.
The ws package provides the server implementation because current Node.js releases include a WebSocket client API but not a built-in WebSocket server. The server and client files use .mjs modules, bind to 127.0.0.1, and listen on port 8080 so the first test stays on the local machine.
The local smoke test keeps the terminal proof simple by using a Node-based client from the same package. A browser client can connect to the same ws://127.0.0.1:8080 endpoint later, while production deployment should add TLS, authentication, origin checks, shutdown handling, and process management before exposing the listener.
If the project does not have package metadata yet, initialize it before adding runtime dependencies.
Related: How to create a Node.js project with npm
$ npm install ws added 1 package, and audited 2 packages in 443ms found 0 vulnerabilities
ws supplies both WebSocketServer and a Node-based client for the local smoke test.
Related: How to install a Node.js dependency
$ npm list ws --depth=0 websocket-demo@1.0.0 /home/developer/websocket-demo `-- ws@8.21.0
import { WebSocketServer } from "ws"; const host = "127.0.0.1"; const port = Number(process.env.PORT) || 8080; const server = new WebSocketServer({ host, port }); server.on("connection", (socket) => { socket.send("server: ready"); socket.on("message", (message) => { socket.send(`server: ${message.toString()}`); }); }); server.on("listening", () => { console.log(`WebSocket server listening at ws://${host}:${port}`); });
Binding to 127.0.0.1 keeps the listener local. Use a deliberate public bind address only after TLS, authentication, and firewall rules are planned.
import WebSocket from "ws"; const url = process.argv[2] ?? "ws://127.0.0.1:8080"; const socket = new WebSocket(url); socket.on("open", () => { socket.send("hello from client"); }); socket.on("message", (message) => { const text = message.toString(); console.log(text); if (text === "server: hello from client") { socket.close(); } }); socket.on("close", () => { console.log("client: closed"); });
$ node --check server.mjs
No output means Node.js parsed the server file without a syntax error.
$ node --check client.mjs
No output means Node.js parsed the client file without a syntax error.
$ node server.mjs WebSocket server listening at ws://127.0.0.1:8080
Keep this terminal open while the client connects.
$ node client.mjs server: ready server: hello from client client: closed
Pass another URL such as wss://app.example.com/socket as the first argument when testing a deployed endpoint.