Webpack 4.X + React + Node + Mongodb build a chat room from scratch (1)

During the front-end time, I updated the version of create-react-appthe scaffolded reactproject webpackfrom 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.X4.Xwebpack 4.Xreact

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


1. Webpack configures React development and production environment

1. Initial download

npm init
npm i webpack webpack-cli -D

2. Configuration directory

Insert image description here

3. Configure the react environment

package.jsonInject into devdevelopment environment and buildproduction 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 loaderthe correct reactprocessing. View full configuration


Specify the current babel-loaderversion for download plugin-proposal-class-propertiesto 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 reactdevelopment and production environments. Next, we start the project to test whether it meets reactthe development environment.

index.jsEntry 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.jsMain file:

import React,{
    
    Component} from 'react'

export default class App extends Component {
    
    
  constructor(){
    
    
    super()
  }
  render() {
    
    
    return (
      <div>
        简易聊天
      </div>
    )
  }
}

webpack.config.jsHot loading configuration

...
  // 热加载
  devServer: {
    host: '0.0.0.0', // host地址
    port: '8080', // 端口
    open: true, //自动拉起浏览器
    hot: true, //热加载
    hotOnly: true, // 热加载不更新
    // proxy: {}, // 跨域
    // bypass: {} // 拦截器
  },
...

When we execute npm run devthe startup hot reloading project
Insert image description here
, we can see that the console compilation is completed. Next, when we open it, we http://localhost:8080can see that the project has been started successfully and hot reloading can be loaded normally.
Project loaded successfully

2. Write a static chat room page

1. Design drawing

Next, we start writing the page. We first draw a rough layout design
Insert image description here
. 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.Insert image description here 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:
Insert image description here

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-width967px: Computer with smaller resolution
Insert image description here
②: max-width667px: iPad client
Insert image description here
③: max-width479px: Mobile client
Insert image description here
The layout is temporarily over

3. Start the mongodb database

1. Installation environment
2. Start the mongodb database

dataAfter the installation is completed, we create a new folder in the root directory to store data:
Insert image description here
Next, we enter binthe directory, open the command line window, and execute: mongod --dbpath X:\mongdb\data, the path here is datathe path to the folder we just created
Insert image description here
. 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 newdatabase and insert a piece of data.
Insert image description here

3. Connect to the database

Next, we use the visual application to connect to the database. The
Insert image description here
connection is successful, and we can see the piece of data we just inserted using the command line.
Insert image description here

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, serverfolders containing index.jsmain files, and modulefolder configurations schame/model, etc.

moduleThere 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
Insert image description here
Here we connect to chatthe database and start socketthe server.

Here are the following points:

1. mongodbDuring the connection to the database, establishment schame/modewill cause initialization failure. requireSynchronous 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 _idis ObjectIdthe type, mongoosewhich provides us with a way to transfer the type:mongoose.Types.ObjectId

4. useNewUrlParserSet to trueto avoid "Use of the current URLstring parser is deprecated" warning

5. mongooseError 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, set useUnifiedTopologyto be trueable to solve

server/index.jsmaster 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.jsonadd a command to start the server

package.jsonConfiguration 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 serverthe startup server.
Insert image description here
We see that the server is started. Visit http://127.0.0.1:3001/to see the effect.Insert image description here

3. Design schame model

You can see that the server started successfully. Next, we design the database model

module/User.js: usersModel

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: roomsModel

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: recordsModel

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.
Insert image description here

5. Related articles

Guess you like

Origin blog.csdn.net/Vue2018/article/details/107428772