全栈式的开发多人在线聊天室 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
bw2
V2EX    程序员

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

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

技术栈

觉得好的欢迎点个 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 好尴尬
O3YwA1ENkb7i35XJ
    17
O3YwA1ENkb7i35XJ  
   2017-07-25 10:55:46 +08:00   1
bw2
    18
bw  
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 哎,能力太差,近半小时没有找到问题所在,求大佬指点
O3YwA1ENkb7i35XJ
    20
O3YwA1ENkb7i35XJ  
   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 感谢大佬,这就去修复
O3YwA1ENkb7i35XJ
    22
O3YwA1ENkb7i35XJ  
   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     Solana     2676 人在线   最高记录 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 25ms UTC 02:18 PVG 10:18 LAX 19:18 JFK 22:18
Do have faith in what you're doing.
ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86