This article only explains some key knowledge points, please learn Fork source code.
If there is no one in the Demo page, you can create several new pages to copy the address to enter. Each page is an independent visitor, compatible with PC and mobile terminal access.
The Demo presentation
Making the source code
The original blog
The front-end implementation
Front-end technology stack
- Parcel: build tool, a zero-configuration package build tool
- Socket. IO: a cross-platform WebSocket communication library with a front-end and back-end consistent API that can trigger and respond to customized events.
The front-end interface
There is nothing to say about interface layout, just write it as you like. You can also refer directly to the project DEMO and source code.
Socket. IO profile
Socket. IO has a front-end and back-end API, so there is little difference between front-end and Node.
The main API for socket. IO is to fire and respond to custom events. You can fire any custom event name except connect, message, and Disconnect, which cannot be used. Below are some of the custom events used in this project.
Socket. IO’s official website
The client triggers a custom event: test
socket.emit('test', data)
The server responds to the event
socket.on('test', data => {})
Copy the code
Front-end trigger event
- Logging into chat rooms
- Send a message
Front-end response event
- The login status
- The system informs
- Message is sent
The source code parsing
Connecting to the server
import io from './assets/js/socket.io'
let socket = io('ws: / / 47.91.235.153:3000'// Connect to server socket.on('connect'.function () {
console.log('Connected to server successfully')})Copy the code
Logging into chat rooms
If the user name is not the same, you can close the login window to enter the chat room.
Send the login event
function userLogin () {
let loginName = document.getElementById('js-loginName').value
if (loginName === ' ') {
alert('You have to enter a username')}else{// Send the login event socket.emit('login', {
name: loginName
})
}
}
oLoginBtn.addEventListener('click', userLogin)
Respond to login status
socket.on('login'.function (data) {
if (data.status === 'ok') {
loginStatus = true
oLogin.style.visibility = 'hidden'
} else {
alert(data.text)
}
})
Copy the code
The system informs
The system notification can only be sent by the server. It mainly returns the notification of the user entering or leaving the room and the current online user.
socket.on('sys'.function(data) {// Number of people online ocount.innerhtml = data.count // Join the message list omessagebox. innerHTML += '<li class="sys">
<div class="name"<div > <div class="message">${data.text}</div> </li> '// traverse to show online userslet sUser = ' '
data.users.forEach(el => {
sUser += `<li>${el}</li>`
});
oUserBox.innerHTML = sUser
})
Copy the code
Message is sent
function sendMessage() {// Get the input boxlet oText = document.getElementById('js-text') // The current inputletSText = otext. value // If empty, do not commitif (sText === ' ') {
return false} // Trigger the message sending event socket.emit('message', {name: nickName, text: sText}) omessagebox. innerHTML += '<li class="my">
<div class="name">${nickName}</div>
<div class="message">${sText}</div> </li> '// reset the content to empty otext.value =' 'Omessagebox.scrolltop = omessagebox.scrollheight} oenter.adDeventListener ('click', sendMessage)
Copy the code
Receive group chat messages
Receives broadcast messages sent by the background, excluding those sent by the user.
socket.on('message'.function(data) {// Message list appends the message omessageBox. innerHTML += '<li> <div class="name">${data.name}</div>
<div class="message">${data.text}</div> </li> '// Message list scroll to the bottom omessagebox.scrollTop = omessagebox.scrollheight})Copy the code
Use Parcel development and packaging
Parcel is simple to use and doesn’t require any configuration to run and package applications
Parcel 英 文官网
# installation
npm install -g parcel-bundler
# Development: visit http://localhost:1234/
parcel index.html
# compiler
parcel build index.html
Copy the code
Node server implementation
The Node technology stack
- http
- socket.io
The Node end socket. IO
It has the same API as the front end, which I won’t explain here
io.on('connection'.function(socket) {// Respond to the event socket.on('test', data => {}) // Send the event socket.emit('test'// Broadcast to all IO. Emit ('test', data) // Broadcast to all but the current user socket.broadcast.emit('test', data)
})
Copy the code
The source code parsing
To enable the WebSocket
var app = require('http').createServer()
var io = require('socket.io'// WebSocket connection IO. On ('connection'.function(socket) {// All event-triggered responses are written here})function () {
console.log('WebSocket enabled port on *: 3000')})Copy the code
User login to chat room
Because it’s just a little exercise project, and there’s no real user-centric thing. Only one array users is used to store the current online user.
socket.on('login'.function(data) {// Check whether users have the same nameif (users.indexOf(data.name) >= 0) {
console.log(data.name + 'There is already a user with the same name. Please re-enter a nickname. '// Send the login failed event socket.emit('login', {
status: 'err',
text: 'There is already a user with the same name. Please re-enter a nickname. '})}else{// Add a user users.push(data.name) // Set the nickName socket.nickName = data.name console.log(data.name +) for the current user'Entered the room')
console.log('Current user', users) // Send system notification IO. Emit ('sys', {
text: socket.nickName + 'Entered the room', count: users.length, users: users}) // Send a successful login notification to socket.emit('login', {
status: 'ok'})}})Copy the code
Being pushed
Receive the message sent by the user and broadcast it to everyone except the sender
socket.on('message'.function (data) {
socket.broadcast.emit('message', data)
})
Copy the code
User Disconnection
socket.on('disconnect'.function () {
let index = users.indexOf(socket.nickName)
if(index >= 0) users.splice(index, 1) // Send system notification IO.'sys', {
text: socket.nickName + 'Left the room',
count: users.length,
users, users
})
console.log(socket.nickName + 'Left the room')
console.log('Current user', users)
})
Copy the code
The deployment of online
Although the project is small, it is also front and back separated, so as an exercise, the project code is deployed separately to different servers.
NodeJS server deployment
The back-end code is deployed to aliyun’s Hong Kong server, system CentOS 7. Docker is used to run a node environment container.
Docker Chinese Manual
Ali cloud server security is very high, but there are many pits, mainly pay attention to the following points.
- All external ports on the server are disabled by default. You need to add the corresponding security group policy on the console.
- Frequent local SSH and FTP operations may be blacklisted. You need to add the local IP address to the whitelist in cloud Shield and high anti-ddos IP address
- CentOS 7 replaces iptables with FirewallD by default
1, install FTP and Docker on the server. There are many ways to install Docker
$ Docker pull node
Copy the code
3, run the container and mount the local directory (all data in the container is cached, so some files that need to be changed frequently are directly mounted to the local directory)
$ docker run -it -p 3000:3000 \
$ --mount type=bind.source=/home/www/chat,target=/home/www/chat \
$ node:latest \
$ /bin/bash
Copy the code
4. Upload the code and run it in the container
Upload the code file to the server /home/www/chat and enter the container.
- index.js
- package.json
$ npm install
$ node index.js
Copy the code
If you exit the container, you need to re-enter the container
The container ID can be viewed with docker ps -a
$ docker exec -it f9dd88d7f
Go to the project directory in the container
$ cd /home/www/chat
# install dependencies
$ npm install
# Run the project
$ node index.js
Copy the code
Web Front-end Deployment
Front-end code deployment is much easier than back-end, because front-end code only some HTML, CSS, JS and other static files, just find a static server can be put.
For such projects, it is highly recommended to use Ali Cloud’s object storage OSS, super cheap basic version only costs 9 yuan a year.
- Create a Bucket block
- Bind a domain name in domain name management
- Set up static web hosting in the base Settings
- Package and upload the compiled front-end file
Packaged front-end code
$ parcel build index.html
Copy the code
The package will be successfully packaged/dist
Upload the directory to the OSS storage block created in Ali Cloud, reference the resources in the index. HTML directory as the root directory, move the index. HTML directory to the root directory, and then access it using the bound domain name