During the front-end time, I updated the version of create-react-app
the scaffolded react
project webpack
from 0 to 10, and ran into a lot of pitfalls, so today I am going to use it to build a chat room from scratch (go to TM's scaffolding, it will not be updated in my life, wdnmd)1.X
4.X
webpack 4.X
react
Completed features:
- User registration, login
- When the user enters/leaves the chat room, all users in the current chat room are notified.
- When a single user adds a group chat, all users can see it.
- Users can chat with anyone in real time
- Chat rooms record unread messages from users
- Click on the user's avatar to add a private chat
- Users can chat privately with each other in real time
- Users can keep chat lists and chat records offline
- User is entering function
Resource link : https://github.com/zhangyongwnag/chat_room
Article directory
1. Webpack configures React development and production environment
1. Initial download
npm init
npm i webpack webpack-cli -D
2. Configuration directory
3. Configure the react environment
package.json
Inject into dev
development environment and build
production environment. View full configuration
...
"scripts": {
"dev": "cross-env NODE_TYPE=development webpack-dev-server --progress --colors --config webpack.config.js --mode=development",
"build": "cross-env NODE_TYPE=production webpack -p --progress --colors --config webpack.config.js --mode=production"
},
...
We configured it specifically in the previous article webpack
, so here we only configure loader
the correct react
processing. View full configuration
Specify the current babel-loader
version for download plugin-proposal-class-properties
to be compatible with arrow function writing.
npm i @babel/plugin-proposal-class-properties @babel/preset-react -D
webpack.config.js
...
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',
options: {
include: path.join(__dirname, 'src'),
exclude: '/node_modules/', // 排除node_modules,第三方代码已经处理,不需要二次处理
}
}
},
...
Here we configure it separatelybabelrc
.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-transform-runtime",
[
"@babel/plugin-proposal-class-properties",
{
"loose": false
}
]
]
}
At this point, we have configured the completed react
development and production environments. Next, we start the project to test whether it meets react
the development environment.
index.js
Entry file
import React from 'react'
import ReactDOM from 'react-dom'
import App from './pages/App'
ReactDOM.render(<App/>,document.getElementById('app'))
if (module.hot){
module.hot.accept(() => {
})
}
app.js
Main file:
import React,{
Component} from 'react'
export default class App extends Component {
constructor(){
super()
}
render() {
return (
<div>
简易聊天
</div>
)
}
}
webpack.config.js
Hot loading configuration
...
// 热加载
devServer: {
host: '0.0.0.0', // host地址
port: '8080', // 端口
open: true, //自动拉起浏览器
hot: true, //热加载
hotOnly: true, // 热加载不更新
// proxy: {}, // 跨域
// bypass: {} // 拦截器
},
...
When we execute npm run dev
the startup hot reloading project
, we can see that the console compilation is completed. Next, when we open it, we http://localhost:8080
can see that the project has been started successfully and hot reloading can be loaded normally.
2. Write a static chat room page
1. Design drawing
Next, we start writing the page. We first draw a rough layout design
. Looking at this design, we first think of flex layout, with the chat list on the left and the chat record information on the right.
2. Draw PC layout
First draw a wrapper and use css background gradient
section {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: -webkit-linear-gradient(left top, #67c8b7, #3577cd); /* Safari 5.1 - 6.0 */
background: -o-linear-gradient(bottom right, #67c8b7, #3577cd); /* Opera 11.1 - 12.0 */
background: -moz-linear-gradient(bottom right, #67c8b7, #3577cd); /* Firefox 3.6 - 15 */
background: linear-gradient(to bottom right, #67c8b7, #3577cd); /* 标准的语法(必须放在最后) */
}
We can see that a gradient background is drawn. Next, we draw the main layout. Because there is a lot of logic code behind it, the process of drawing the layout will not be explained in detail here.
The layout is mainly troublesome because of chat records, including your own messages, other people’s messages, system service messages, etc.
If necessary, visit [source code](https://github.com/zhangyongwnag/chat_room
The effect of the PC page being basically drawn:
3. Responsive layout
Next, we add a few breakpoints and make a simple responsive layout
@media screen and (max-width: 967px) {
...
}
@media screen and (max-width: 667px) {
...
}
@media screen and (max-width: 479px) {
...
}
Effect:
①: max-width
967px: Computer with smaller resolution
②: max-width
667px: iPad client
③: max-width
479px: Mobile client
The layout is temporarily over
3. Start the mongodb database
1. Installation environment
node
:https://nodejs.org/zh-cn/download/mongodb
:https://www.mongodb.com/try/download/communityNosql manager for mongodb
:https://www.mongodbmanager.com/download
2. Start the mongodb database
data
After the installation is completed, we create a new folder in the root directory to store data:
Next, we enter bin
the directory, open the command line window, and execute: mongod --dbpath X:\mongdb\data
, the path here is data
the path to the folder we just created
. We can see that the startup is successful. The port is 27017. Next, we open mongo.exe in the bin directory
Here you can use the command line to operate data. The basic commands are not demonstrated here. We create a new new
database and insert a piece of data.
3. Connect to the database
Next, we use the visual application to connect to the database. The
connection is successful, and we can see the piece of data we just inserted using the command line.
4. Start the node server
1. Download
npm i mongoose express -D // Mongoose encapsulated mongodb, express middleware
npm i socket.io -S // Use socket.io to complete communication with the client
2. Initialization
Create folders in the root directory, server
folders containing index.js
main files, and module
folder configurations schame/model
, etc.
module
There are three configuration files stored in the folder User.js Room.js Records.js
, corresponding to the three tables of the database. users rooms records
Here we connect to chat
the database and start socket
the server.
-
Here are the following points:
-
1.
mongodb
During the connection to the database, establishmentschame/mode
will cause initialization failure.require
Synchronous loading is used when establishing here. -
2. When the database uses unique constraints (unique), it must be added
mongoose.set('useCreateIndex', true)
, otherwise the console will warn -
3. The only constraint of the database
_id
isObjectId
the type,mongoose
which provides us with a way to transfer the type:mongoose.Types.ObjectId
-
4.
useNewUrlParser
Set totrue
to avoid "Use of the currentURL
string parser is deprecated" warning -
5.
mongoose
Error report:DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor
, setuseUnifiedTopology
to betrue
able to solve
server/index.js
master file
let express = require('express')
let app = express() // express中间件
let http = require('http').Server(app) // 建立http通信
let io = require('socket.io')(http) // 创建socket服务端
let path = require('path') // 路径操作
let chalk = require('chalk') // 控制控制台颜色
let fs = require('fs') // fs操作文件系统
let mongoose = require('mongoose') // mongoose中间件
let db = 'chat' // 连接的数据库名称
let ObjectId = mongoose.Types.ObjectId // 用来处理数据库唯一约束_id为ObjectId
// 设置数据库可使用唯一约束
mongoose.set('useCreateIndex', true)
// 连接数据库
mongoose.connect(`mongodb://127.0.0.1:27017/${
db}`, {
useNewUrlParser: true, useUnifiedTopology: true}, err => {
console.log()
if (err) {
console.log(chalk.bgCyan(chalk.black(' S ')) + chalk.red(' Connect') + chalk.blue(` db.${
db}`) + chalk.red(' failure'))
} else {
console.log(chalk.bgCyan(chalk.black(' S ')) + chalk.green(' Connect') + chalk.blue(` db.${
db}`) + chalk.green(' successfully'))
}
})
let User = require('./module/User')
let Room = require('./module/Room')
let Records = require('./module/Records')
app.get('/', (req, res) => {
res.send('hello')
})
io.on('connection', socket => {
})
/**
* @description 启动服务器,因为绑定了socket.io服务端,这里要监听http服务,请勿express服务代替监听
*/
let server = http.listen(3001, '127.0.0.1', () => {
let host = server.address().address
let port = server.address().port
console.log()
console.log(chalk.bgGreen(chalk.black(' DONE ')) + chalk.green(` Compiled successfully at `) + chalk.blue(`${
new Date().toLocaleString()}`))
console.log()
console.log(chalk.bgBlue(chalk.black(' I ')) + ` Server running at : http://${
host}:${
port}`)
})
We package.json
add a command to start the server
package.json
Configuration file:
...
"scripts": {
"dev": "cross-env NODE_TYPE=development webpack-dev-server --progress --colors --config webpack.config.js --mode=development",
"build": "cross-env NODE_TYPE=production webpack -p --progress --colors --config webpack.config.js --mode=production",
"server": "node server/index.js"
},
...
Next, we execute npm run server
the startup server.
We see that the server is started. Visit http://127.0.0.1:3001/
to see the effect.
3. Design schame model
You can see that the server started successfully. Next, we design the database model
module/User.js
: users
Model
let mongoose = require('mongoose')
// 创建 Schema
let UserSchema = mongoose.Schema({
// 用户名称,唯一约束
user_name: {
type: String,
unique: true,
required: true
},
current_room_id: String, // 用户所处聊天室ID
socket_id: String // 用户的socketID
}, {
timestamps: {
createdAt: 'createTime',
updatedAt: 'updateTime'
}
})
// 创建 User model
let User = mongoose.model('User', UserSchema)
module.exports = User
module/Room.js
: rooms
Model
let mongoose = require('mongoose')
// 创建 Schema
let RoomSchema = mongoose.Schema({
user_id: String, // 用户ID
user_name: String, // 用户名称
room_name: String, // 聊天室名称
status: Number, // 0为群聊,其他为私聊
num: Number, // 聊天是在线人数
badge_number: Number, // 消息未读数
current_status: Boolean // 当前用户是否处在当前聊天室
}, {
timestamps: {
createdAt: 'createTime',
updatedAt: 'updateTime'
}
})
// 创建 Room model
let Room = mongoose.model('Room', RoomSchema)
module.exports = Room
module/Records.js
: records
Model
let mongoose = require('mongoose')
// 创建 Schema
let RecordSchema = mongoose.Schema({
user_id: String, // 用户ID
user_name: String, // 用户名称
room_name: String, // 聊天室名称
chat_content: String, // 聊天内容
status: Number // 是否为系统服务消息
}, {
timestamps: {
createdAt: 'createTime',
updatedAt: 'updateTime'
}
})
// 创建 Room model
let Records = mongoose.model('Records', RecordSchema)
module.exports = Records
4. Test model generates data
Next, we insert a piece of test data:
...
let User = require('./module/User')
let user = new User({
user_name: '测试',
current_room_id: '',
socket_id: ''
})
// 注册用户插入数据库
user.save()
.then(res => console.log('插入用户成功'))
.catch(err => console.log('插入用户失败:' + err))
...
We enter the database to view the results and we can see that the data was successfully inserted.