[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