Skip to main content

[Chat App] Optimization - Shared Connection

// App.jsx
function App() {
const sharedWorkerRef = useRef(null);
const isSocketInit = useRef(false);

const [isSocketConnected, setIsSocketConnected] = useState(false);

const isConnectionInit = useRef(false);
const [isConnectionBuilt, setIsConnectionBuilt] = useState(false);

useEffect(() => {
const listenSocketConnection = (event) => {
if (event.data.action === "$connect") {
setIsSocketConnected(true);
}
};

if (!isSocketInit.current) {
// NOTE: it's weird that only onmeesage will work
sharedWorkerRef.current = new SharedWorker('/shared-worker.js', { type: 'module' });
sharedWorkerRef.current.port.onmessage = listenSocketConnection;
isSocketInit.current = true;
}

return () => {
sharedWorkerRef.current?.port.removeEventListener("message", listenSocketConnection);
};
}, []);
}


// shared-worker.js
const endpoint = '<web socket endpoint>'

const connectChatRoomSocket = (port) => {
const socket = new WebSocket(endpoint);

socket.onopen = () => {
port.postMessage({ action: "$connect" });
}

socket.onmessage = (event) => {
connections.forEach(port => {
port.postMessage(JSON.parse(event.data));
});
}

return socket;
}

let socket
let connections = [];


self.onconnect = (event) => {
const port = event.ports[0];
connections.push(port);

if (!socket) {
socket = connectChatRoomSocket(port);
} else {
port.postMessage({ action: "$connect" });
}

port.onmessage = (event) => {
if (event.data.action === "delete_connection") {
connections = connections.filter(connection => connection !== port);

if (connections.length === 0) {
socket.send(JSON.stringify(event.data));
socket.close();
socket = null;
}
} else {
socket.send(JSON.stringify(event.data));
}
}
}


Reference

  • GreatFrontend - Chat App