Quick Summary

Building real-time applications with Vue.js, Express.js, and WebSockets enables seamless, instant communication between users and servers, making it ideal for chat applications, live notifications, and collaborative tools. Vue.js ensures a reactive and interactive frontend, while Express.js provides a lightweight, scalable backend to handle multiple connections efficiently. WebSockets empower real-time data exchange by maintaining a persistent, bidirectional connection without the overhead of frequent HTTP requests.

Table of Contents

Introduction

Real-time apps are everywhere, from chat applications, stock market dashboards, and collaborative tools to live notifications. They are transforming industries with instant messaging, real-time updates, and live tracking. Technologies like Vue js, Express js, and WebSockets are suitable solutions for real-time communications.

In this blog tutorial, we will build a real-time chat application using Vue.js for the front end, Express.js for the back end, and WebSockets for communication. We will discuss setting up your development environment, establishing a WebSocket connection, and efficiently handling real-time data flow.

However, developing scalable and real-time applications requires expertise. If you want to build a seamless real-time experience, it’s best to hire Vuejs developers with hands-on experience in modern frameworks. At Bacancy Technology, we have a team of skilled Vue.js developers who help businesses create fast, interactive, and user-friendly applications.

Let’s delve into how to build Vue js real-time applications with Express js and WebSockets and the reasons why this is an ideal stack for real-time apps.

Why Use Vue js With Express js and Websockets?

To develop real-time apps, you require a lightweight, efficient, scalable tech stack to handle continuous data exchange. That’s where Vue.js, Express.js, and WebSockets come into the picture. These technologies offer unique advantages that assist you to create dynamic real-time development.

1. Vue.js – A Fast and Reactive Frontend Framework

Vue.js is a progressive JavaScript framework known for its simplicity and flexibility. It is widely used for dynamic and real-time applications because of its:

  • Reactive data binding will automatically update the UI when data changes.
  • Component-based architecture helps to manage complex UIs efficiently.
  • Lightweight and fast, it ensures high performance with minimal resource consumption.

2. Express.js – A Scalable Backend for Handling Requests

Express.js is a minimalist Node.js framework that makes backend development fast and efficient. It is ideal for real-time applications because:

  • It handles multiple connections efficiently and develops on non-blocking architecture.
  • It’s lightweight and flexible and will seamlessly integrate with WebSockets.
  • Fast API development helps quickly to set up RESTful APIs and WebSocket connections.

While combined with WebSockets, Express.js acts as a robust bridge between the front end (Vue.js) and real-time data streams.

3. WebSockets – Robust Real-Time Communication Support

Traditional HTTP requests are inefficient for real-time applications since they rely on repeated polling. WebSockets provide a persistent connection between the client and server, allowing data to flow instantly.
Key benefits of WebSockets:

  • Low latency and instant updates are suitable choices for chat apps, live notifications, and dashboards.
  • Bidirectional communication enables seamless data exchange without constant requests.
  • Efficient resource utilization reduces server load compared to long polling.

Steps to Create Real-Time Apps With Vue.js, Express js, and WebSockets

In this tutorial, we will learn and explore how to develop a real-time small chat application using VueJS, ExpressJS, and Websockets. So, without further delay, let’s get started.

Prerequisites:

  • Basic knowledge of ExpressJS and VueJS
  • VS code or any other IDE
  • Familiarity with Javascript and HTML

Backend setup with express and socket.io:

Here, we are going to use ExpressJS as a backend. So, create an empty folder and run the below command to create an Express app.

npm init

Run the below command to install all the dependencies.

npm i express socket.io

Then, create one file named index.js and paste the below code to create an express server:

Copy Text
const express = require('express');


const app = express();


const port = 4000;


const server = app.listen(port, () => {
    console.log("app listening at port:" + port);
})

Now, using socket.io, we need to implement logic to establish a connection between the front end and the back end. Also, we will analyze the Websocket, so whenever we get any data from the websocket, it will broadcast that data.

Copy Text
const io = require('socket.io')(server);


io.on('connection', function(socket) {
    socket.on('SEND_MESSAGE', function(data) {
        io.emit('MESSAGE', data);
    });
});

In above code, using socket.on method, we are continuously reviewing websocket and whenever we receive data, using io.emit method, we will broadcast received data. As a result, final version of index.js file will look like this-

index.js:

Copy Text
const express = require('express');


const app = express();


const port = 4000;


const server = app.listen(port, () => {
    console.log("app listening at port:" + port);
})


const io = require('socket.io')(server);


io.on('connection', function(socket) {
    socket.on('SEND_MESSAGE', function(data) {
        io.emit('MESSAGE', data);
    });
});

Now, run the below command in your terminal to run the server.

Copy Text
node .\index.js

Front-end setup using vue-cli

Now, we are setting up the front end using Vue-cli. We will create a Vue3 project by running the below command:

Copy Text
vue create chat-room

Moreover, inside chat-room folder, run the below command to run the Vue project:

Copy Text
npm run serve

The local host will display the default screen as shown below:

welcome to your vue.js app

Now, create one component inside the components folder named ChatRoom.vue and import this component inside the App.vue file. So, after this, your App.vue file and folder structure will look like this:

App.Vue:

Copy Text
<template>
  <ChatRoom />
</template>


<script setup>
import ChatRoom from './components/ChatRoom.vue';
</script>
App.vue
Real-time performance, real-time results!

Partner with our Vue js development company to build cutting-edge applications with instant data synchronization and a flawless user experience.

Steps to Integrate Websocket between the backend and frontend

Now, it’s time to run the command below to install socket.io-client in your Vue project.

Copy Text
npm i socket.io-client

Now, whenever users enter their username and click on the join button, we will establish a connection between the client and the server and implement a method to listen to data from the server continuously.

Copy Text
<form v-if="!isUserJoined" @submit.prevent="pingServer">
	<div>            
    <label>Enter username to join:</label>
      	<div>
    		<input type="text" v-model="user" />
      </div>
     		<button type="submit" class="btn btn-success">Join</button>
</div>
</form>
Copy Text
<script setup>
import io from "socket.io-client";


// vue imports
import { ref } from "vue";


const user = ref("");
const messages = ref([]);
const isUserJoined = ref(false);
const socket = ref(null);

const pingServer = () => {
  socket.value = io("localhost:4000", { transports: ["websocket"] });
  socket.value.on("MESSAGE", (data) => {
    messages.value = [...messages.value, data];
  });
  isUserJoined.value = true;
}
</script>

Now, if user is joined then we will allow user to broadcast a message as shown below:

Copy Text
<div>
  <form v-if="!isUserJoined" @submit.prevent="pingServer">
    <div>
      <label for="user">Enter username to join:</label>
      <div>
        <input type="text" v-model="user" />
      </div>
      <button type="submit">Join</button>
    </div>
  </form>
  <form v-else @submit.prevent="sendMessage">
    <div>
      <input type="text" v-model="message" placeholder="Type Message" />
      <button type="submit">Send</button>
    </div>
  </form>
</div>
Copy Text
<script setup>
import io from "socket.io-client";


// vue imports
import { ref } from "vue";


const user = ref("");
const message = ref("");
const messages = ref([]);
const isUserJoined = ref(false);
const socket = ref(null);

const pingServer = () => {
  socket.value = io("localhost:4000", { transports: ["websocket"] });
  socket.value.on("MESSAGE", (data) => {
    messages.value = [...messages.value, data];
  });
  isUserJoined.value = true;
}


const sendMessage = (e) => {
  e.preventDefault();
  socket.value.emit("SEND_MESSAGE", {
    user: user.value,
    message: message.value,
    socket_id: socket.value.id,
  });
  message.value = "";
}


</script>

Here, the emit() method sends an object with a message to the server using a websocket, and the server broadcasts this object. Next, we will provide functionality for users to leave our chat room.

Copy Text
<div v-if="isUserJoined">  
<button type="button" @click="leaveRoom">Leave room</button>
</div>
Copy Text
const leaveRoom = () => {
  socket.value.disconnect();
  user.value = "";
  message.value = "";
  messages.value = [];
  isUserJoined.value = false;
}

Now, let’s apply some CSS to improve the UI of our Chat room application, and after that, this is how our App.vue and ChatRoom.vue will look at the end:

App.vue:

Copy Text
<template>  
  <ChatRoom />
</template>


<script setup>
import ChatRoom from './components/ChatRoom.vue';
</script>


<style>
* {
  margin: 0;
  padding: 0;
}
</style>


ChatRoom.vue:

Copy Text
<template>
  <div class="wrapper">
    <div class="card mt-3">
      <div class="card-body">
        <div class="card-title">
          <h3>Chat Room</h3>
          <div v-if="isUserJoined" class="leave-container">
            <button type="button" @click="leaveRoom" class="btn btn-danger">Leave room</button>
          </div>
        </div>
        <div class="card-body message-body" v-if="messages.length > 0">
          <div class="message-container" :class="msg.socket_id == socket.id && 'sender-msg'" v-for="(msg, index) in messages" :key="index">
            <div class="messages">
              <p class="username">{{ msg.user }}</p>
              <p>{{ msg.message }}</p>
            </div>
          </div>
        </div>
      </div>
      <div class="card-footer">
        <form v-if="!isUserJoined" @submit.prevent="pingServer">
          <div class="form-group">
            <label for="user">Enter username to join:</label>
            <div class="input-container">
              <input type="text" v-model="user" class="form-control" />
            </div>
            <button type="submit" class="btn btn-success">Join</button>
          </div>
        </form>
        <form v-else @submit.prevent="sendMessage">
          <div class="form-group msg-container">
            <input type="text" v-model="message" placeholder="Type Message" class="form-control" />
            <button type="submit" class="btn btn-success">Send</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</template>


<script setup>
import io from "socket.io-client";


// vue imports
import { ref } from "vue";




const socket = ref(null);


const user = ref("");
const message = ref("");
const messages = ref([]);
const isUserJoined = ref(false);


const sendMessage = (e) => {
  e.preventDefault();
  socket.value.emit("SEND_MESSAGE", {
    user: user.value,
    message: message.value,
    socket_id: socket.value.id,
  });
  message.value = "";
}


const pingServer = () => {
  socket.value = io("localhost:4000", { transports: ["websocket"] });
  socket.value.on("MESSAGE", (data) => {
    messages.value = [...messages.value, data];
  });
  isUserJoined.value = true;
}


const leaveRoom = () => {
  socket.value.disconnect();
  user.value = "";
  message.value = "";
  messages.value = [];
  isUserJoined.value = false;
}
</script>


<style scoped>
::-webkit-scrollbar {
  display: none;
}
.wrapper {
  background: #e8eaff;
  min-height: 100vh;
}


.card-title {
  margin-bottom: 30px;
  padding: 20px;
  background: #153f5e;
  display: flex;
  justify-content: space-between;
  align-items: center;
}


.leave-container {
  display: flex;
  justify-content: flex-end;
}


.message-body {
  padding: 20px;
  max-width: 700px;
  margin: auto;
  max-height: 60vh;
  overflow-y: scroll;
}


.card-title h3 {
  text-align: center;
  color: #fff;
  text-transform: uppercase;
}


.form-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
  justify-content: center;
}


.msg-container {
  width: 100%;
  position: fixed;
  bottom: 50px;
  flex-direction: row;
}


.form-group label {
  color: #153f5e;
  font-weight: bolder;
}


.form-group .input-container {
  display: flex;
  justify-content: center;
  width: 100%;
}


.form-group input {
  height: 20px;
  max-width: 300px;
  width: 100%;
  padding: 10px;
  border-radius: 5px;
  color: #153f5e;
}


.form-group input:focus-visible {
  border: 2px solid #153f5e;
  outline: none
}


.btn {
  color: #fff;
  border: none;
  outline: none;
  cursor: pointer;
  padding: 10px 30px;
  border-radius: 50px;
}


.btn.btn-success {
  background: #35d87a;
}


.btn.btn-danger {
  background: #c5243f;
}


.message-container {
  display: flex;
  justify-content: flex-start;
}


.messages {
  color: #153f5e;
  width: 200px;
  border-radius: 10px;
  padding: 0 10px 10px 10px;
  background: #fff;
  box-shadow: 2px 2px #d7d7d7;
  position: relative;
  margin-bottom: 20px;
}


.messages::after {
  border-width: 0px 20px 20px 0;
  border-color: transparent #fff transparent transparent;
  top: 0;
  left: -10px;    
  position: absolute;
  content: "";
  width: 0;
  height: 0;
  border-style: solid;
}


.messages .username {
  font-weight: bolder;
  padding-bottom: 10px;
}


.sender-msg {
  justify-content: flex-end;
}


.sender-msg .messages::after {
  left: auto;
  right: -10px;
  border-width: 0px 0px 20px 20px;
  border-color: #fff transparent transparent #fff;
}
</style>

Github repo
Here’s the source code for the Front-end and Back-End. You can check out our clone repos and explore our ChatRoom functionalities, which are mentioned below.
https://github.com/jemis-maru/chat-demo-front

https://github.com/jemis-maru/chat-demo-back

Best Practices Optimizing and Securing Real-Time Applications

A real-time application must be fast, reliable, and secure. Hence, here are some best practices to ensure your Vue.js, Express.js, and WebSockets-powered app runs smoother and protects data.

  • Always use WSS:// instead of ws:// to encrypt data over TLS for secure WebSockets.
  • Enable WebSocket message compression (e.g., per message-deflate) to reduce the payload size.
  • Avoid sending excessive WebSocket events; optimize by batching data when possible.
  • Implement automatic reconnection logic to maintain a seamless experience.
  • Configure CORS settings properly to prevent unauthorized access.
  • Utilize token-based authentication (JWT) before allowing connections to authenticate WebSocket connections.
  • WebSockets don’t naturally scale across multiple instances, so use solutions like Redis Pub/Sub to synchronize messages across servers.
  • Set up a timeout to disconnect inactive users and free up resources to close idle connections.
  • You can use tools like Prometheus, Socket.IO Admin UI, or New Relic to track WebSocket traffic and errors.

Conclusion

Now, you can build real-time applications using Vue.js, Express.js, and WebSockets. Follow the step-by-step guide to create a flexible and innovative real-time app that delivers instant communication and a seamless user experience.

With its robust ability to develop chat or live updates, Vue js, Websockets, and Express js will ensure efficiency, security, and performance. However, dynamic real-time apps require expertise that helps you to optimize performance and secure data exchanges. You can connect with Vue.js consulting services to streamline the process. An expert Vue.js professional can ensure your application is optimized, scalable, and secure with their guidance to overcome the technical complexities.

Frequently Asked Questions (FAQs)

Common real-time app issues include dropped WebSocket connections due to network instability and latency problems from server overload or distance. Also, there could be data synchronization errors between clients and the server, which can lead to inconsistent states.

You can implement authentication using JSON Web Tokens (JWT) or session-based authentication. Authorization can be handled by validating user roles and permissions on the server side before broadcasting messages.

Yes, WebSockets can be integrated into mobile apps using Vue.js with frameworks like Ionic or Quasar and an Express.js backend, enabling real-time communication in mobile applications.

You can use browser developer tools and WebSocket testing tools like Postman or wscat to log WebSocket events on the server and client to track connection status and message flow.

Want to Build Innovative Vue js Real-time Applications?

Partner with our Vue js experts to craft engaging, dynamic, seamless, real-time applications. We ensure high performance, scalability, and real-time data synchronization for your application.

Contact Us

Build Your Agile Team

Hire Skilled Developer From Us

solutions@bacancy.com

Your Success Is Guaranteed !

We accelerate the release of digital product and guaranteed their success

We Use Slack, Jira & GitHub for Accurate Deployment and Effective Communication.

How Can We Help You?