Recently, I worked on an interesting project called SpeedBoard which is a real-time board for Agile and Scrum retrospectives. It's the kind of tool we use at work after our Scrum Sprint review to easily share our feedback about the last Sprint.
Since it was a very enriching experience, I thought that I would do a quick tutorial on how to set up a simple chat with the same technology stack which includes: MongoDB, Express, React, Node.js and is also called the MERN stack. I am also using Socket.IO for the real-time engine and Material-UI which is a UI framework for React based on Material Design.
In this tutorial, we will use Heroku for hosting our live project and Github for hosting our code and deploying it to Heroku, so make sure you already have an account with them, they both provide a free sign up.
Before we start, let's have a quick look at the structure of our project. Inside our root folder, we will have 2 subfolders: one called client which contains the React app and one called server with our Node.js server:
We will create the 2 files necessary for our server to work. The first one (Message.js) is the schema of the documents we will keep in our database. We will need 3 information: the name of the user who is posting a message in the chat, the content of its message and a timestamp to know when he posted his message.
The second one (index.js) is our main file, I won't go too much into details because that would make this tutorial a bit too long, but feel free to ask any question in the comments, I'll be glad to answer them or improve the comments directly in the code if necessary.
During the deployment of our app, we need to tell Heroku how to start our server. It can be done by using a Procfile that we will put at the root of our project. So let's create it and add the command line that will start our server:
The postinstall command, as you can guess, will be executed after Heroku has finished running the npm install command at the root of our folder. It's telling Heroku to also run the npm install command inside our client and server folder and will also build our React app for production.
Note: we are using the same database for both Dev and Live mode, if you want to use a different database, you can always create another one in Heroku like we have seen before and update your .env file with the credentials of your new database to make sure it won't interfere with the one in production.
Now, we are going create a new repository on GitHub, and we are going to connect it to Heroku so every time we will merge a Pull Request on the master branch, it will automatically deploy it on Heroku.
Hi , I faced the same issue , but in my case there was a .git folder present in my client folder which was preventing the deploy . just delete that .git folder and reinitialise your repository and the build will automatically start on heroku.
Hello, I have the same kind of issue first the same as syedabra003 but I added the node version to my package.json and then the error switched now to this one. I'm at the early step of the guide, when trying manual deploy with Heroku, I started from scratch two times but still the same result, 'npm run dev' runs fine on local so if any clues ? Thanks !
In case anybody else runs into the same issue, I think the client's package "name" needs to be "client", in case you copy in your own react app... Also, Procfile should not have ' ' around the 'web: ... ' part. Not 100% if that's what solved it for me, but oh well.
Yes, the Procfile should not include the single quote, I am using macOS and the command I wrote in the article is not adding the quote. Maybe it does under another OS? Anyway, the file should be like this:
github.com/armelpingault/speedchat...
So when you use _id.getTimestamp() you get the timestamp but it is not a field which is already present in the document but something which the function does and if you have the timestamp : true then this is a field in the document and doesn't require an extra function to be called.
Can you please explain why you use socket.broadcast.emit for your 'push' event? It seems like socket.emit would work just fine but it doesn't. I've read this cheat sheet and it doesn't seem to explain why it wouldn't work:
Thanks for the guide. I needed to install 'dotenv' and add require('dotenv').config(); to the top of index.js so that I could run it locally. I also needed to add this since I was using socket.io v3.0+:
Hi I have an issue to share with you guys. I got an issue if I wrap the with . You will have your code inside setState run twice. The possible way to fix this is to move the logic outside of setState. I have fix this two setState in App.js.
How to create a simple and beautiful chat with MongoDB, Express, React and Node.js (MERN stack) is an interesting topic. Get some important points which I didn't know before. Thanks for sharing it. If you want to know about the MERN Stack course then visit: cetpainfotech.com/technolgy/mern-s...
Hi Siddhant, well, like any other website, you can always use someone else name, and the point here is to show a tutorial about the MERN stack, not really about verifying the identity of a user. But you can always implement your own solution to verify your users' identity.
Writing a real-time application with popular web applications stacks like LAMP (PHP) has traditionally been very hard. It involves polling the server for changes, keeping track of timestamps, and it is a lot slower than it should be.
Sockets have traditionally been the solution around which most real-time systems are architected, providing a bi-directional communication channel between a client and a server. This means that the server can push messages to clients. Whenever an event occurs, the idea is that the server will get it and push it to the concerned connected clients.
Socket.IO is quite popular, it is used by Microsoft Office, Yammer, Zendesk, Trello,. and numerous other organizations to build robust real-time systems. It one of the most powerful JavaScript frameworks on GitHub, and most depended-upon NPM (Node Package Manager) module. Socket.IO also has a huge community, which means finding help is quite easy.
To get started with developing using the Socket.IO, you need to have Node and npm (node package manager) installed. If you do not have these, head over to Node setup to install node on your local system. Confirm that node and npm are installed by running the following commands in your terminal.
Whenever you need to start the server, instead of using the node app.js use, nodemon app.js. This will ensure that you do not need to restart the server whenever you change a file. It speeds up the development process.
Following is another example (this require Socket.IO), it will log "A user connected", every time a user goes to this page and "A user disconnected", every time someone navigates away/closes this page.
We have set up our server to log messages on connections and disconnections. We now have to include the client script and initialize the socket object there, so that clients can establish connections when required. The script is served by our io server at '/socket.io/socket.io.js'.
Broadcasting means sending a message to all connected clients. Broadcasting can be done at multiple levels. We can send the message to all the connected clients, to clients on a namespace and clients in a particular room. To broadcast an event to all the clients, we can use the io.sockets.emit method.
This was to send an event to everyone. Now, if we want to send an event to everyone, but the client that caused it (in the previous example, it was caused by new clients on connecting), we can use the socket.broadcast.emit.
Let us send the new user a welcome message and update the other clients about him/her joining. So, in your app.js file, on connection of client send him a welcome message and broadcast connected client number to all others.
Socket.IO allows you to "namespace" your sockets, which essentially means assigning different endpoints or paths. This is a useful feature to minimize the number of resources (TCP connections) and at the same time separate concerns within your application by introducing separation between communication channels. Multiple namespaces actually share the same WebSockets connection thus saving us socket ports on the server.
This will connect the client to the default namespace. All events on this namespace connection will be handled by the io object on the server. All the previous examples were utilizing default namespaces to communicate with the server and back.
Within each namespace, you can also define arbitrary channels that sockets can join and leave. These channels are called rooms. Rooms are used to further-separate concerns. Rooms also share the same socket connection like namespaces. One thing to keep in mind while using rooms is that they can only be joined on the server side.
We have worked on local servers until now, which will almost never give us errors related to connections, timeouts, etc. However, in real life production environments, handling such errors are of utmost importance. Therefore, we will now discuss how we can handle connection errors on the client side.
Socket.IO uses a very famous debugging module developed by ExpresJS's main author, called debug. Earlier Socket.IO used to log everything to the console making it quite difficult to debug the problem. After the v1.0 release, you can specify what you want to log.
The Socket.IO connection begins with the handshake. This makes the handshake a special part of the protocol. Apart from the handshake, all the other events and messages in the protocol are transferred over the socket.
Socket.IO is intended for use with web applications, and therefore it is assumed that these applications will always be able to use HTTP. It is because of this reasoning that the Socket.IO handshake takes place over HTTP using a POST request on the handshake URI (passed to the connect method).
c80f0f1006