Home

Building a Real-Time Vue 3 App with WebSocket Integration

Real-time communication was a major feature in my web chat application, enabling instant data updates and interactivity. WebSockets are a popular technology for achieving this, allowing for full-duplex communication channels over a single, long-lived connection. In this article, I'll describe how to connect a Vue 3 application to a WebSocket server using Pinia, Vue's recommended state management library, and Vue's onMounted lifecycle hook.

First I needed a Vue app with Pinia as a store the following with command

npm init vue@latest

so Pinia will be added into main.ts

app.use(createPinia())

Create a useSocketStore store in your src/stores directory:

import { defineStore } from 'pinia';
import { io, Socket } from 'socket.io-client';

export const useSocketStore = defineStore('socket-store', {
  state: () => ({
    socket: null as Socket | null,
  }),
  getters: {
    getSocket(state) {
      return state.socket
    },
  },
  actions: {
    initSocket(userId: string) {
        // here in env var I have a backend API url with setup websockets
      this.socket = io(import.meta.env.VITE_SERVICE_URL, {
        query: { userId }
      })
    },
    setupListeners() {
      this.socket.on('connect', () => {
        ...
      })
      this.socket.on('connect_error', () => {
        ...
      })
      this.socket.on('disconnect', () => {
        ...
      })
      this.socket.on('message', (message: string) => {
        ...
      })
    },
    emitMessage() {
      this.socket?.emit(
        'message',
        ...
      )
    },
    disconnectSocket() {
      this.socket?.disconnect()
    },
  }
})

Then on a page Dashbaord.vue

<script setup lang="ts">
import { onMounted, onBeforeUnmount } from 'vue'
import { useRouter } from 'vue-router'
import { useSocketStore } from '@/stores/socket-store'

const router = useRouter()
const { getUser, findUserById } = useAuthStore()

const socketStore = useSocketStore()
const { initSocket, setupListeners, disconnectSocket } = socketStore

onMounted(async () => {
  // here I pass userId I pass it after login

  initSocket(userId)

  setupListeners()
})

onBeforeUnmount(() => {
  disconnectSocket()
})
</script>

<template>
  ...
</template>

Here is only essential part of websockets connection for frontend part. The whole code can be seen on github repo chat-web-app. In this post I wanted to highlight how to divide setup for websocket settings and the rest of application.

Thanks for reading