V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bw2
V2EX  ›  程序员

全栈式的开发多人在线聊天室

  •  1
     
  •   bw2 ·
    bergwhite · 2017-07-25 05:57:35 +08:00 · 4035 次点击
    这是一个创建于 2673 天前的主题,其中的信息可能已经有所发展或是发生改变。

    技术栈

    觉得好的欢迎点个 star ^_^。

    • 前端:Express & EJS & ES6 & Less & Gulp
    • 后端:Express & SocketIO & MongoDB & REST API
    • 部署:Linux & PM2

    演示

    NChat-qrcode

    目录

    
    ├─bin
    │    www       // 后端 服务器
    │    database  // 后端 数据库
    │    socket    // 后端 socket
    |    router    // 后端 路由
    ├─sessions     // 后端 session
    ├─public
    │    src       // 前端 开发目录
    │    dist      // 前端 线上目录
    ├─routes       // 前端 路由
    ├─view         // 前端 页面
    ├─app.js       // 前端 服务器
    ├─gulpfile.js  // 前端 Gulp
    ├─package.json
    
    

    安装

    • 项目基于 MIT 协议开源
    • 启动项目以前,请确保已经安装 mongodb,并在 package.json 中修改 MongoDB 的安装路径(--dbpath )

    Windows 安装教程 | Linux 安装教程

    
    git clone https://github.com/bergwhite/nodejs-chat  // 克隆项目
    cd nodejs-chat  // 进入目录
    npm install  // 安装依赖
    npm run build  // 构建 线上代码
    npm run mongod // 开启 数据库
    npm run start // 开启 聊天室
    
    

    功能

    • 聊天

      • √ 群聊
      • × 私聊
      • √ 表情
      • × 斗图
      • × 更多表情
      • √ 聊天机器人(图灵)
    • 用户

      • √ 在线清单
      • √ 随机头像
      • √ 上线通知
      • √ 离线通知
      • √ 消息推送
      • × 上传头像
      • √ 在线统计
    • 房间

      • √ 房间列表
      • √ 添加房间
      • × 搜索房间

    优化

    • 基础

      • √ 代码压缩
    • 展示

      • √ 以前未设置头像的,显示默认头像
      • √ 加载速度优化
      • × 界面换肤
    • 开发

      • √ 组件化开发
      • √ 模块化开发
      • REST API
      • √ 使用 PM2 部署
      • √ 前后端分离
      • × 代码规范
      • × 测试用例
    • 安全

      • √ 密码使用 MD5+SALT 保存
      • √ 聊天内容过滤< >等特殊标签
    • 认证

      • √ Session
    • 部署

      • Linux & PM2

    踩坑

    图灵机器人不支持跨域,通过代理中间件把请求代理到本地。

    
    var proxy = require('http-proxy-middleware');
    
    app.use('/api/robot', proxy({
      target: 'http://www.tuling123.com',
      changeOrigin: true
    }));
    
    

    Gulp 使用通配符对多个文件处理,会压缩到一个文件中。以下是分别进行压缩的方式。

    
    const gulp = require('gulp'),
          minifyJS = require('gulp-uglifyjs'),
          babel = require('gulp-babel'),
          rename = require('gulp-rename');
    
    const compileDir = {
      css: {
        src: 'public/src/css/index.less',
        dest: 'public/dist/css'
      },
      js: {
        src: 'public/src/js/',
        dest: 'public/dist/js'
      }
    };
    
    gulp.task('compile-js', () => {
      const JSTaskList = ['index', 'login', 'mobile', 'room', 'roomAdd', 'userInfoMod', 'roomMember']
      return JSTaskList.map((e) => {
        gulp.src(`${compileDir.js.src}${e}.js`)
          .pipe(babel({
            presets: ['es2015']
          }))
          .pipe(minifyJS())
          .pipe(rename((path) => {
            path.basename += '.min'
          }))
          .pipe(gulp.dest(compileDir.js.dest))
      })
    });
    
    

    gulp-uglifyjs - No files given; aborting minification

    
    之前删除了一个 JS 文件,但是没有删除 JSTaskList 中的对应值。编译时会报上面的错误。删除对应的值就编译成功了。
    
    
    26 条回复    2017-07-25 22:46:50 +08:00
    bw2
        1
    bw2  
    OP
       2017-07-25 06:23:49 +08:00
    文章是十分钟自动放弃编辑权限?
    ------------------------------------------------
    补充
    ------------------------------------------------
    项目源码: https://github.com/bergwhite/nchat
    在线演示: http://47.93.252.247:8086/
    agostop
        2
    agostop  
       2017-07-25 08:41:58 +08:00
    现在一说全栈,就说的 nodejs ?
    aksoft
        3
    aksoft  
       2017-07-25 08:49:12 +08:00   ❤️ 1
    不是从 销售 设计 前端 后端 DBA 服务器 叫全栈吗?
    bw2
        4
    bw2  
    OP
       2017-07-25 08:49:51 +08:00
    @aksoft 就扶你
    bw2
        5
    bw2  
    OP
       2017-07-25 08:51:07 +08:00
    @agostop 在我这个初级前端的眼中,全栈只能是 nodejs 啊 ^#^
    aksoft
        6
    aksoft  
       2017-07-25 08:53:04 +08:00
    @bw2 厉害,我一个都不会
    lrh3321
        7
    lrh3321  
       2017-07-25 09:14:25 +08:00
    @aksoft 我做 后端 DBA 服务器 ,是不是可以叫做 半栈 ?
    DKYzz
        8
    DKYzz  
       2017-07-25 09:14:38 +08:00
    感觉对话字体很小,是我的错觉吗
    aksoft
        9
    aksoft  
       2017-07-25 09:18:21 +08:00
    @lrh3321 你只能叫 1/3 栈
    bw2
        10
    bw2  
    OP
       2017-07-25 09:26:14 +08:00
    @lrh3321 半栈大佬,全栈菜鸟来向你取经
    bw2
        11
    bw2  
    OP
       2017-07-25 09:26:40 +08:00
    @DKYzz 字体确实小了点,改改改
    seasstyle
        12
    seasstyle  
       2017-07-25 09:29:50 +08:00 via Android   ❤️ 1
    怎么手机上找不到 github 的 star ?😂
    JasperYanky
        13
    JasperYanky  
       2017-07-25 09:31:38 +08:00
    全栈不是 前端+后端+客户端么
    bw2
        14
    bw2  
    OP
       2017-07-25 09:36:47 +08:00
    @seasstyle 手机端,进入关于,右上角的图片可以点击的,进去了就是 github 的仓库地址
    bw2
        15
    bw2  
    OP
       2017-07-25 09:37:11 +08:00
    @JasperYanky 客户端还在筹备中,预计用 RN 开发
    bw2
        16
    bw2  
    OP
       2017-07-25 09:45:54 +08:00
    @seasstyle 点 star 好像只能用 PC 页面,或者设置手机视图为 PC,移动端的 github 好尴尬
    xqin
        17
    xqin  
       2017-07-25 10:55:46 +08:00   ❤️ 1
    bw2
        18
    bw2  
    OP
       2017-07-25 11:04:53 +08:00
    @xqin 一直在等你啊。求问你是如何注入 onerror 事件的,我只还原了修改图片为'',但是 onerror 事件无效。
    bw2
        19
    bw2  
    OP
       2017-07-25 11:06:19 +08:00
    @xqin 哎,能力太差,近半小时没有找到问题所在,求大佬指点
    xqin
        20
    xqin  
       2017-07-25 11:18:33 +08:00   ❤️ 1
    因为我并不是改的图片, 而是修改的用户名.

    bin/socket/event.js 第 90 行, 在接收消息的时候, 允许从消息中得到当前的 `user`.

    然后在接收之后, 广播给其他人的时候, 其他人接收时的处理逻辑是这样的,
    public/src/js/index.js 第 102 行, 把接收到的 `user` 传递给 renderBubbleMsg 方法, 这个方法 在使用 `user` 时直接拼入字符串内(未做转义处理, 第 156 行), 所以只要 emit 那个事件, 并将 user 设置为
    <img src="" onerror="alert(/Hello from v2ex/)">admin , 然后其他收到消息的人, 就会弹出提示框了.
    bw2
        21
    bw2  
    OP
       2017-07-25 11:23:02 +08:00
    @xqin 感谢大佬,这就去修复
    xqin
        22
    xqin  
       2017-07-25 12:57:47 +08:00   ❤️ 1
    @bw2 没修复好.
    hantsy
        23
    hantsy  
       2017-07-25 13:01:34 +08:00   ❤️ 1
    只能说用 Firebase 这种太容易实现了。
    bw2
        24
    bw2  
    OP
       2017-07-25 14:08:36 +08:00
    @xqin 临时过滤了下,后期再改进过滤机制。img.replace(/on[a-zA-z]+=/, '')
    bw2
        25
    bw2  
    OP
       2017-07-25 14:09:13 +08:00
    @hantsy 又学到一个新技能
    hantsy
        26
    hantsy  
       2017-07-25 22:46:50 +08:00
    @bw2 Firebase 官方有 AngularJS 和 Angular 2 支持。之前一个项目用的 AngularJS 1.5 + Firebase 实现了一个聊天功能(包括文字,图片聊天,消息提醒(在聊天窗口不提醒,离开聊天窗口有通知 Icon, 离线会发送邮件),离线 /在线标记),Firebase 的 AngularJS 本身全部基于 Websocket (当然源于底层的 Firebase SDK ), 所以实时支持是默认的。Firebase 官方也有个比较复杂的聊天程序例子。

    比较无奈的 Firebase 是纯 Key/value 的 NoSQL, 数据结构太简单,想做复杂查询就麻烦了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3309 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:18 · PVG 20:18 · LAX 04:18 · JFK 07:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.