vue+websocket+express+mongodb real-time project (live chat)

Continue to the previous project Use vuejs to imitate NetEasy Cloud music (for listening and searching) Later, I found that the previous project was very confused simply managed with vue's model, and then I went to see vuex, and planned to do a project practice, but did not want to do a duplicate project. This time, I gave up my face and planned to go out of style.Combining background nodejs, and data baseMongoDB To develop a real-time chat system.This system can be said to be a unified system, but also a dream to realize front-end programmers, to eat everything from front to back.Consider yourself a more complete project.Project Address: https://github.com/hua1995116/webchat Make a star if you feel good.

technology stack

  • Front end vue, vue-router, vuex
  • Backend nodejs, express
  • Database mongodb
  • Communications websocket
  • Scaffolding tool vue-cli

Structure
├─build 
├─config 
-models (store mongoose object)
-schemas (schemas model for mongoose)
├─src 
│ │ App.vue 
main.js (main entrance)
│ ├─assets 
-components
-router (vue-router routing)
│ └─store(vuex) 
-static (static resource)

Start by building a project with scaffolding tools.Like this:

vue init webpack my-project-name

The structure is roughly like this

OK!Since we're a real-world project, I won't talk much about these configuration issues.Otherwise, it's off the topic again.Otherwise, they will be beaten by the younger brothers and sisters.

Front end

First, look at the page layout under the src directory.(
main.js//main entrance

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
// Use museui components
import MuseUI from 'muse-ui'
import 'muse-ui/dist/muse-ui.css'
Vue.use(MuseUI)
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  template: '<App/>',
  components: {App}
})

We chose muse-ui to make the whole project look beautiful, let alone say the UI framework is really beautiful.Don't believe you can see it muse-ui .The rest are the default configurations for scaffolding.

route/router.js

import Vue from 'vue'
import Router from 'vue-router'
import Index from '@/components/Index'
import Robot from '@/components/Robot'
import Home from '@/components/Home'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Index',
      component: Index
    },
    {
      path: '/robot',
      name: 'Robot',
      component: Robot
    },
    {
      path: '/home',
      name: 'Home',
      component: Home
    }
  ]
})

You can see that there are three routes. That's right. We just wrote three routes. The first one is a chat room with you, and the second one is a chat with our lovely white one, which is ours. Turing Robot .Have a play when you're free.The third piece is our personal center, although it's nothing.But after all, it looks good, oh~forget, we are out of mind, how can we just look at the face?

components/Chat.vue

created() {
    const that = this
    this.socket = io.connect('http://qiufengh.com:8081')
    this.socket.on('message', function(obj) {
        that.$store.commit('addroomdetailinfos', obj)
        window.scrollTo(0, 900000)
    })
    this.socket.on('logout', function (obj) {
        that.$store.commit('setusers', obj)
    })
},
this.socket = io.connect('http://qiufengh.com:8081')

  

This sentence is mainly used to connect your current service. When you download the following items, remember to change to your own service and port.Because both Index and Chat are set, you need to change the connection in both Index.vue and Chat to your own service.socket.on() is used to accept messages.socket.emit() is used to send messages.Look here at socket.io you don't understand socket.io .With this, you can interact with the server.The server will be explained later.

store/index.js

state: {
 //Store User
  user: {
    name: '',
    src: ''
  },
  //Store history
  messhistory: {
    infos: []
  },
  //Store room information for future multi-room use
  roomdetail: {
    id: '',
    users: {},
    infos: []
  },
  //Store robot introductory remarks
  robotmsg: [{
    message: 'Hi~Anything you want to know can ask me',
    user: 'robot'
  }],
  //Chat Page Display Control
  chattoggle: false,
  //Login Page Display Control
  logintoggle: false,
  //Registration Page Display Control
  registertoggle: true,
  //Tip box display control
  dialog: false,
   //Tip box content
  dialoginfo: ''
}

Since there is too much control code, please move on to my github address. https://github.com/hua1995116/webchat/

Server Side

Because there is too much webpack code in dev-server.js under build, it is too messy to explain.The main thing to look at is the server side for packaging.The two codes are the same.(
prod.server.js (root)

var express = require('express');
var config = require('./config/index');
var port = process.env.PORT || config.dev.port;

var app = express();

var router = express.Router();
//For static display entrance
router.get('/',function(req,res,next){
    req.url = './index.html';
    next();
});

app.use(router);

require('./config/routes')(app)
/*Introduce*/
var mongoose = require('mongoose')
//log file
var morgan = require('morgan')
//sesstion storage
var bodyParser = require('body-parser')
var cookieParser = require('cookie-parser')
var session = require('cookie-session')
//For asynchronous callbacks
mongoose.Promise = require('bluebird')
global.db = mongoose.connect("mongodb://localhost:27017/vuechat")

//Jsonization of data submitted by the server
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))
//sesstion storage
app.use(cookieParser())
app.use(session({
  secret: 'vuechat',
  resave: false,
  saveUninitialized: true
}))

var env = process.env.NODE_ENV || 'development'
if ('development' === app.get('env')) {
  app.set('showStackError', true)
  app.use(morgan(':method :url :status'))
  app.locals.pretty = true
  mongoose.set('debug', true)
}

var server = app.listen(port)

//websocket
// var http = require('http').Server(app);
var io = require('socket.io')(server);
var Message = require('./models/message')
var users = {}
io.on('connection', function (socket) {
  //Listen for users to post chat content
  socket.on('message', function (obj) {
    //Broadcast published messages to all clients
    io.emit('message', obj)
    var mess = {
      username: obj.username,
      src:obj.src,
      msg: obj.msg,
      roomid:'room1'
    }
    var message = new Message(mess)
    //Store incoming messages
    message.save(function (err, mess) {
      if (err) {
        console.log(err)
      }
        console.log(mess)
    })
    console.log(obj.username + 'Say:' + obj.msg)
  })
  socket.on('login',function (obj) {
    users[obj.name] = obj
    //Used to listen to users in chat rooms
    io.emit('login', users)
  })
  socket.on('logout',function (name) {
    delete users[name]
    //User monitor exits chat room
    io.emit('logout', users)
  })
})

//Declare static resource address
app.use(express.static('./dist'));

schema model

schema/user.js

var mongoose = require('mongoose')
//For md5 encryption
var bcrypt = require('bcryptjs')
//Number of Salts Added
var SALT_WORK_FACTOR = 10
var UserSchema = new mongoose.Schema({
  name: {
    unique: true,
    type: String
  },
  password: String,
  src: String,
  meta: {
    createAt: {
      type: Date,
      default: Date.now()
    },
    updateAt: {
      type: Date,
      default: Date.now()
    }
  }
});
//Encrypt password
UserSchema.pre('save', function (next) {
  var user = this
  if (this.isNew) {
    this.createAt = this.updateAt = Date.now()
  }
  else {
    this.updateAt = Date.now()
  }
  bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
    if (err) return next(err)

    bcrypt.hash(user.password, salt, function (err, hash) {
      if (err) return next(err)

      user.password = hash
      next()
    })
  })
})
//Used to compare passwords correctly
UserSchema.methods = {
  comparePassword: function (_password, cb) {
    bcrypt.compare(_password, this.password, function (err, isMatch) {
      if (err) return cb(err)
      cb(null, isMatch)
    })
  }
}

UserSchema.statics = {
  fetch: function (cb) {
    return this
      .find({})
      .sort('meta.updateAt')
      .exec(cb)
  },
  findById: function (id, cb) {
    return this
      .findOne({_id: id})
      .exec(cb)
  }
}

module.exports = UserSchema

This is mainly used for an md5 module, you can view the bcryptjs

schema/message.js

var mongoose = require('mongoose')
//Chat Logging Model
var MessageSchema = new mongoose.Schema({
  username: String,
  src:String,
  msg: String,
  roomid:String,
  time: {
    type: Date,
    default: Date.now()
  }
})
//Static method
MessageSchema.statics = {
  fetch: function (cb) {
    return this
      .find({})
      .sort('time')
      .exec(cb)
  },
  findById: function (id, cb) {
    return this
      .findOne({_id: id})
      .exec(cb)
  }
}
module.exports = MessageSchema

Server routes
config/routes.js talks about a registered handle, others please go to the project to view

app.post('/user/signup', function (req, res) {
    //Get Submitted Data
    var _user = req.body
    console.log(_user)
    User.findOne({name: _user.name}, function (err, user) {
      if (err) {
        console.log(err)
      }
      if (user) {
        res.json({
          errno: 1,
          data: 'User name already exists'
        })
      } else {
        var user = new User(_user)
        user.save(function (err, user) {
          if (err) {
            console.log(err)
          }
          res.json({
            errno: 0,
            data: 'login was successful'
          })
        })
      }
    })
  })

Mainly used to verify that the user name is duplicated.

That's the core part.For other details, please check my github address (with detailed comments, questions that you don't understand, and suggestions for improvement from your predecessors):
Address: https://github.com/hua1995116/webchat 
Online viewing address: http://www.qiufengh.com:8081/#/

npm install -----Installation Dependency
npm run dev -----Function
npm run build -----Pack
node prod.server.js -----Run after packaging
//Remember to replace
Index.vue and Chat.vue Lower io.connect('http://qiufengh.com:8081')
http://qiufengh.com:8081 changed to its project address.

Last few pictures.(

 

Keywords: Javascript Vue Mongoose socket github

Added by Citizen on Fri, 05 Jul 2019 19:54:12 +0300