Building and Deploying a React App with Socket.IO Using TypeScript, Yarn, Vite, and Nginx on Ubuntu Server

Date

Contents

Introduction

This tutorial is a step by step guide on how to create a basic ReactJS app in TypeScript that uses Socket.IO for real-time communication. We will start by building a simple web application that receives and sends messages to/from a Socket.IO server. We will set the server up and then deploy the app and the Socket.IO server on a Ubuntu server hosted in DigitalOcean.

Prerequisites:

  • Basic understanding of TypeScript and React
  • A Digital Ocean Ubuntu Server
  • A GitHub account

Tools

  • Vite A next-generation front-end build tool developed by the creator of Vue.js. It provides a faster and leaner development experience for modern web projects.
  • yarn A fast, reliable, and secure JavaScript package manager.
  • Nginx Nginx is a powerful web server software that can also be used as a reverse proxy, load balancer, and HTTP cache.
  • ReactJS with Typescript React is a popular JavaScript library for building user interfaces, particularly single-page applications. TypeScript is a statically typed superset of JavaScript that compiles to plain JavaScript.
  • Ubuntu Server 18.04.6 LTS A Linux distribution that is well-suited for hosting servers.
  • Socket.IO A library that enables real-time, bidirectional and event-based communication between the browser and the server. It’s made up of two parts: a client-side library that runs in the browser, and a server-side library for Node.js
  • Node.js Node.js is an open-source, cross-platform, JavaScript runtime environment that executes JavaScript code outside a web browser.

  • Git * Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.

Install tools (On server and locally)

Before we start, let's ensure we have all the necessary tools installed both on our local machine and on our Digital Ocean Ubuntu server. These tools include Node.js, Yarn, Git, and Nginx.

Install Node.js

We will install Node.js using NVM (Node Version Manager)

Important: After installing NVM you will need to open a new terminal.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

Then let's install Node.js by using the following command:

nvm install v16.20.1

Let's verify Node.js has been installed

node --version

Install Yarn

After Node.js is installed, we will now install Yarn

npm install --global yarn yarn --version

The next steps will require root access. If you're logged in as a non-root user, you can use the sudo command to get root access.

Update the package lists

sudo apt-get update

Install Git

sudo apt-get install git git --version

Install vite globally

yarn global add create-vite

Installing nginx

Lastly, install Nginx

sudo apt-get install nginx -y nginx -v

Step 1 - Creating a GitHub Repository

First, create a new empty repository on GitHub. For this example, let's call it "my-socketio-app". After creating the repository, clone it to your local machine:

git clone https://github.com/<your_username>/my-socketio-app.git

Step 2 - Setting Up the React App

Navigate to the cloned repository folder, then create a new Vite project with react-ts template

cd my-socketio-app npx create-vite . --template react-ts

After creating the project, stage and commit the changes:

git add . git commit -m "Initialize React app with Vite" git push

Step 3 - Installing Socket.IO Client

Inside the project directory, install the Socket.IO client:

yarn add socket.io-client

Then, commit the changes:

git add . git commit -m "Install socket.io client" git push

Step 4 - Setting Up the Socket.IO Client

Create a new socket.ts file inside the src folder and add the following code (Replace IP address with your server's address):

1 2 3 4 5 6 import { io } from "socket.io-client"; const socket = io("http://<your_server_ip>:3000"); export default socket;

Step 5 - Using Socket.IO in a React Component

Next, we'll create a React component that listens for a 'welcome' event from the server and sends a message to the server: Create a new MyClientComponent.tsx file inside the src folder and add the following code:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import React from 'react'; import socket from './socket'; const MyClientComponent: React.FC = () => { const sendMsg = () => { socket.emit('message', 'Hello from client!'); }; React.useEffect(() => { socket.on('welcome', (msg: string) => { console.log(msg); }); socket.on('message', (msg: string) => { console.log(msg); }); return () => { socket.off('message'); socket.off('welcome'); }; }, []); return ( <div> <h1>MyClientComponent</h1> <button onClick={sendMsg}>Send Message</button> </div> ); }; export default MyClientComponent;

The next thing is to modify src/main.tsx to include the MyClientComponent instead of the App component, the file should look like the following:

1 2 3 4 5 6 7 8 9 10 import React from 'react' import ReactDOM from 'react-dom/client' import MyClientComponent from './MyClientComponent.tsx' import './index.css' ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( <React.StrictMode> <MyClientComponent /> </React.StrictMode>, )

Step 6 - Building the Socket.IO Server

First, create a new directory server in your my-socketio-app directory and initialize a new yarn project inside it:

mkdir server cd server yarn init -y

After that, install the necessary packages:

yarn add express socket.io cors yarn add -D typescript ts-node @types/node @types/express

Create a tsconfig.json file in the server directory with the following content:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { "compilerOptions": { "module": "commonjs", "esModuleInterop": true, "target": "es6", "noImplicitAny": true, "moduleResolution": "node", "sourceMap": true, "outDir": "dist", "baseUrl": ".", "paths": { "*": ["node_modules/*"] } }, "include": ["src"] }

After that, create a new src directory in the server directory, and create a new file server.ts inside the src directory with the following content:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import express from 'express'; import { createServer } from 'http'; import { Server, Socket } from 'socket.io'; const app = express(); const httpServer = createServer(app); const io = new Server(httpServer); io.on('connection', (socket: Socket) => { console.log('a user connected'); socket.emit('welcome', 'Welcome! You are connected.'); socket.on('disconnect', () => { console.log('user disconnected'); }); socket.on('message', (msg: string) => { console.log('message: ' + msg); socket.emit('message', 'Message received!'); }); }); httpServer.listen(3000, () => { console.log('listening on *:3000'); });

Finally, add the following scripts to your package.json file:

1 2 3 4 5 "scripts": { "start": "node dist/server.js", "build": "tsc", "dev": "ts-node src/server.ts" },

After setting up the server go back to the root directory of the project. And then stage and commit the changes:

git add . git commit -m "Setup Socket.IO server" git push

Step 7 - Deploying the Project

SSH into your Ubuntu server and install all the tools as you did it with your local environment. After you are done installing everything navigate to the /var/www directory, then clone your GitHub repository:

cd /var/www git clone https://github.com/<your_username>/my-socketio-app.git

Navigate to the my-socketio-app directory and install the necessary packages:

cd my-socketio-app yarn install

Before you can run the application, we need to compile the TypeScript code into JavaScript:

yarn build

Next, configure Nginx to serve our React app:

sudo nano /etc/nginx/sites-available/default

Update the file to look like this:

sudo nano /etc/nginx/sites-available/defaultserver { listen 80 default_server; listen [::]:80 default_server; root /var/www/my-socketio-app/dist; server_name _; location / { try_files $uri $uri/ =404; } }

After modifying the root entry in the file, run the following command to make the changes take effect:

sudo service nginx reload

Now you should be able to see your React app if you visit your server's address.

After setting up and running our frontend React app, we need to build our server and also run it, let's start by installing all the necessary packages:

cd server yarn install

Now we can build the server:

yarn build

We got our server ready, for a production environment, I recommend using PM2 to manage the server process, so let's install it:

yarn global add pm2 pm2 start dist/server.js --name my-socketio-app-server pm2 startup pm2 save

We should see our Socket.io server now running, to make sure of that, run the following command:

pm2 status

If we navigate to our IP address and then to the Network tab in the browser, we should see a CORS Error.

CORS Error

CORS errors are thrown when a web application tries to access a resource from a domain (origin) different from its own. The browser has this security feature which blocks these requests unless the server includes the appropriate headers to allow the request.

To fix this error let's edit our server/src/server.ts file and add a cors directive to look like the following (Important: Avoid any slashes at the end of the IP address):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import express from 'express'; import { createServer } from 'http'; import { Server, Socket } from 'socket.io'; const app = express(); const httpServer = createServer(app); const io = new Server(httpServer, { cors: { origin: "http://<your_server_ip>", methods: ["GET", "POST"] } }); io.on('connection', (socket: Socket) => { console.log('a user connected'); socket.emit('welcome', 'Welcome! You are connected.'); socket.on('disconnect', () => { console.log('user disconnected'); }); socket.on('message', (msg: string) => { console.log('message: ' + msg); socket.emit('message', 'Message received!'); }); }); httpServer.listen(3000, () => { console.log('listening on *:3000'); });

After saving changes run the build command again and restart the pm2 service:

yarn build pm2 restart my-socketio-app-server

You can now access your React app in a web browser by visiting your server's IP address.

Socketio connection

Conclusion

In this tutorial, we've seen how tocreate a basic React app using TypeScript and Socket.IO, and then deploying it on a Ubuntu server in Digital Ocean using yarn, vite, and Nginx. This set-up can be used as a starting point for more complex applications. Happy coding!