vue使用websocket问题记录

最近笔者新参与的一个web项目,拟定采用vue2.0来编写,期间遇到有关使用websocket的问题,记录一下,个中遇到的一些问题和解决方法,分享给有需要的人。
  首先说一下vue2.0的初学体验,目前感觉上手还是很快的,对比其他框架比如angularjs,react等,的确是轻量级很多,并且确实如作者尤大大所诉,真实体会到了其渐进式前端解决方案的思想 ,你完全可以根据项目的实际情况,选择性的采用最适合的模块和组件组合来更快速实现自己的功能,然后随着业务功能的扩展,渐进式的调整系统的架构,或采用更适合当前情况的架构。
  结合项目的实际情况,项目本身不大,初期版本定位是一个小型的单页面应用,目前团队前端开发人员都有一定的angularjs的开发基础,此时切换到vue上面来,也挺顺利的,既然是复杂度不是特别高的单页面应用,初期定位就是用vue-cli来构建项目的基本结构,然后配上vue-route路由,vue-resource请求API数据,很快页面雏形出来了。
吧啦吧啦说了这么多,貌似还没切入主题,websocket,嗯,现在开始切入(咳咳,容我缓缓,刚刚还沉浸在尤大大的vue里面)。
  笔者不是专业的前端,对websocket还不是很了解,项目里面有一个应用场景是要在页面上实时显示服务端推送过来的数据,很显而易见的的服务端给客户端推送消息的场景,大家自然想到了websocket,而我但是对这个还是不是很清楚的,迅速查资料,知乎上这篇文章 貌似是讲的不错,小白表示看的很过瘾。
  这个功能,服务端也采用了websocket,这需要客户端也相应的采用websocket来与客户端建立ws连接,这样客户端和服务端就可以双向的发送数据。笔者的定式思维是,一拿到这个就会觉得是不是又需要npm安装什么包似的,因为这个功能是从另一个项目(暂且称其为项目B)的功能迁移过来的,而项目B前端是用的angularjs开发的,前端直接用的angularjs的一个websocket的包(angular-websocke),然后几行代码就敲定了,创建连接,发送数据,接收数据,很是方便。然后切换到vue里面,很自然的就去搜有木有vue的websocket包,很快找到了vue-websocket,安装好后,调试,直接报错:

XMLHttpRequest cannot load http://192.168.0.239:9000/socket.io/?EIO=3&transport=polling&t=LbjddEK. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 404.

笔者对比了项目B,同样在客户端启动本地server,能正常创建到服务端的ws连接,不会像http请求一样有跨域的问题,同时另一问题就是,明明是要创建ws连接,为何浏览器的控制台里会提示是http的连接?
vue-websocket没有调试成功,马上去找找有没有通用的包,于是在github找了js相关的websocket的相关包,比如ws,笔者对照了angularjs-websocket包,它也是依赖的ws。于是按照ws的说明文档,安装,然后webpack直接报错了:

ERROR in ./~/ws/lib/WebSocketServer.js Module not found: Error: Cannot resolve module 'tls' in xx\node_modules\ws\lib @ ./~/ws/lib/WebSocketServer.js 15:10-24 ERROR in ./~/options/lib/options.js Module not found: Error: Cannot resolve module 'fs' in xx\node_modules\options\lib @ ./~/options/lib/options.js 6:9-22

查找资料,说是这两个包是服务端node用的,客户端没有所以导致报错,需要修改webpack的配置文件,使其不加载客户端不需要的包
https://github.com/webpack/react-starter/issues/3#issuecomment-53395089
然后,webpack不报错了,但是前端调用ws生成实例的时候,依然会报错,因为ws链接创建的时候,先发起了http的链接请求,按照ws文档

var WebSocket = require('ws')
var ws = new WebSocket('ws://xxx/ws', 'ws')

在在代码里,生成ws实例的时候,还是会产生http的链接,跟前面用vue-websocket的情况类似,因为是在本地启动的前端服务,所以这样发起到服务器的请求,会导致跨越报错。
奇怪的是项目B里的angular使用的angular-websocket包,同样是基于ws包做的,在本地启动,是直接创建的ws链接,没有跨越的问题。
  然后在vue论坛上查找相关资料,类似的问题比如:
[https://forum-archive.vuejs.org/topic/1293/webpack-bundling-issue-with-websockets/3](https://forum-archive.vuejs.org/topic/1293/webpack-bundling-issue-with-websockets/3)
有人提到:Can't you just use window.WebSocket instead of ws?
提醒到了我,我摒弃了ws,直接用window.WebSocket,来创建ws连接,果然成功了。那为啥angular-websocket基于ws,能正常在浏览器执行,vue这边直接用ws不行,于是去查看angular-websocket的源码,才发现angular-websocket基于ws做了封装,它提供的$websocket对象,在当前浏览器环境下,本质上也是window.WebSocket的对象。

import angular from 'angular';
var Socket;
if (typeof window === 'undefined') {
try {
var ws = require('ws');
Socket = (ws.Client||ws.client||ws);
} catch(e) {}
}
// Browser
Socket = (Socket || window.WebSocket || window.MozWebSocket);
////////////////////////////////////////////////////////////
function $WebSocketBackendProvider($log) {
this.create = function create(url, protocols) {
var match = /wss?:\/\//.exec(url);
if (!match) {
throw new Error('Invalid url provided');
}
if (protocols) {
return new Socket(url, protocols);
}
return new Socket(url);
};

看源码里面,angular-websocket也是用window.WebSocket创建的,只有在没有window对象的时候,才会基于ws包来创建websocket对象。然后瞬间感觉找准了方向,目前我们的场景主要是PC端的浏览器使用,可以直接用window.WebSocket对象来,于是查阅了window.WebSocket的文档
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
很快问题就解决了,原来自带的window对象就已经可以解决问题了,自己绕了一大圈,还是回到原点,细看了它文档里写的相关方法,确实和前面讲到的angular-websocket很像,确实angular-websocket是对这些方法,比如onopen,send,onmessange等方法进行了封装,让开发可以更方便的调用。
  另外,还有一个websocket相关的库Socket.IO,Socket.IO是一个跨平台,支持多种连接方式,如websocket,flashsocket,ajax等,如果客户端不支持websocket时,可以切换使用其他链接方式,比如ajax轮询等,Socket.IO完全由JavaScript实现、基于Node.js、支持WebSocket的协议用于实时通信、跨平台的开源框架,它包括了客户端的JavaScript服务器端的Node.js,在客户端环境不支持websocket的情况下,用Socket.IO可以通过其他方式,模拟出websocket的效果。
  但是,笔者目前的情况是,服务端不是nodeJs环境,笔者在客户端安装了Socket.IO,并且按照文档说明,去建立ws链接,发现以下问题:

  1. 安装socket.io-client,安装完之后,webpack报错
    ERROR in ./~/socket.io-client/~/component-emitter/index.js Module build failed: Error: ENOENT: no such file or directory, open 'xx\node_modules\socket.io-client\node_modules\component-emitter\index.js' at Error (native) @ ./~/socket.io-client/lib/manager.js 8:14-42 ERROR in ./~/engine.io-client/~/component-emitter/index.js Module build failed: Error: ENOENT: no such file or directory, open 'xx\node_modules\engine.io-client\node_modules\component-emitter\index.js' at Error (native) @ ./~/engine.io-client/lib/socket.js 6:14-42
    参考https://github.com/socketio/socket.io-client/issues/933这个需要修改一下webpack的配置文件,添加以下两行:
module: {
    noParse: ['ws']
  },
  externals: ['ws']

这样webpack可以打包通过

  1. 然后测试,创建连接var socket = io(url);,这样创建的链接,Socket.IO默认是按轮询方式发起的http请求(很奇怪,当前浏览器明明是支持websocket的),这样首先就出现了前面的http跨域请求报错。
    XMLHttpRequest cannot load http://192.168.0.239:9000/socket.io/?EIO=3&transport=polling&t=LbjddEK. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 404.
    查阅资料,创建连接的时候,可以指定参数io(WS_URL, {transports: ['websocket', 'polling', 'flashsocket']}),设置其发起websocket链接,这样在console里看到的确实是发起的ws请求,然而依然报404错:
    WebSocket connection to 'ws://192.168.0.239:9000/socket.io/?EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 404
    提示是404找不到,确实是服务端没有'ws://192.168.0.239:9000/socket.io/?EIO=3&transport=websocket'这样的url,这种url是默认的ws服务端的url,可以设置 path,path默认是/socket.io,设置path后,io(WS_URL, {path: '/ws', transports: ['websocket', 'polling', 'flashsocket']}),依然报301错:
    WebSocket connection to 'ws://192.168.0.239:9000/ws/?EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 301
    笔者对比了成功建立ws链接时的url,ws://192.168.0.239:9000/ws,然后用工具测试了下,只有path是/ws,即ws://192.168.0.239:9000/ws?EIO=3&transport=websocket这样的url才能成功建立ws链接,这里报301的错误,是因为socketio会在path后面添加/?EIO=3&transport=websocket`这样一串参数,这样导致了服务端路由匹配不上,导致出现了404或301的情况,所以这里需要服务端配合调整一下路由规则,即可。

最终,结合当前的实际情况还是采用了原生的websocket,Socket.IO对url的格式有一定的规范要求,比较适合客户端和服务端都同时可控的情况,目前查了socketio的api文档,也没找到合适的方法,可以自定义url,大家有什么好的解决方法,请不吝赐教!
  今天码字就码到这里,就酱紫了,欢迎大家来拍砖!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • 转载 :OpenDiggawesome-github-vue 是由OpenDigg整理并维护的Vue相关开源项目库...
    果汁密码阅读 23,092评论 8 124
  • 别闹了,我知道我自己配不上你,可我也在努力改变自己。
    回首的背叛阅读 174评论 0 0
  • 2017年 6月14日(农历五月二十)星期三天气:晴 读经人:璐萱锦雯妈 读经第八周第3天,累积50天 写读经感恩...
    璐萱锦雯妈阅读 98评论 0 0
  • 【三个目标】身体健健康康活到90岁;财务自由可以帮到更多的人;拥有一个相爱到白头的爱人。 1、今天给爸爸发红包,他...
    惠心阳阳阅读 170评论 0 1
  • 夜幕降临,华灯初上,或许你正在匆匆忙忙的赶上最后一班公交,或许你正看着窗外的车水马龙而沉思,又或许。。。 一杯...
    wzj107阅读 254评论 0 1