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.

  1. Create a Bucket block
  2. Bind a domain name in domain name management
  3. Set up static web hosting in the base Settings
  4. 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/distUpload 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