<srcipt src="/socket.io/socket.io.js"></script>加载的资源是从哪儿冒出来的?

    这个标题可能起的不太高级,或者表述不清楚。这里解释一下,其实就是弄清楚<srcipt type="text/javascript" src="/socket.io/socket.io.js"></script>这句代码加载的资源是哪里来的。如果觉得过程太繁琐,就直接看总结把。

    首先我们来看一下使用socket.io前端代码的实现:

<!DOCTYPE html>
<html>
<head>
    <title>socket.io</title>
    <script type="text/javascript" src="/socket.io/socket.io.js"></script>
</head>
<body>
<div></div>
<script type="text/javascript">
    var socket = io("ws://10.10.10.96:8080"); //通过ip和端口建立一个socket client
        socket.on('connect', function(){
            console.log('connect a socket client');
        });
</script>
</body>
</html>

    使用非常简单,就是去服务器加载socket.io.js这个js,然后浏览器解析这个文件,获取io这个实例对象,这个实例里面封装了关于wbsocket的相关方法,没什么难理解的。但是我要说的是socket.io.js这个外部脚本是如何获取到的。写nodejs的朋友都知道外部脚本,样式,图片等这些文件是属于静态资源,在服务端我们通常会有一个静态资源文件夹public在express中我们通过:

app.use(express.static(__dirname+'/public'))

来实现资源静态化,其实实现原理很简单,请求过来的时候根据请求url判断是不是请求静态资源,如果是就将public中对应url的文件读出来然后返回就行。但是我们会发现

<script type="text/javascript" src="/socket.io/socket.io.js"></script>

请求的资源是不在我们的静态资源文件夹里面的。那这个文件是哪里来的呢?这个时候我们第一反应应该想到我们引入的socket.io包了。打开这个模块我们可以看见

这里写图片描述

    这里我们可以看见一个socket.js,但是他不是我们前面提到那个socket.io.js,至于问什么不是,你打开看一下,里面的编写规范完全是按照commonJS那一套来的,而commonJS在不编译的情况下,浏览器只能说“臣妾无能为力啊”。那他在是从哪儿来的呢?大家可能会注意到socket.iomo模块下还有几个命名为socket***的模块,不要怀疑自己的第一感觉,他们肯定是‘亲戚’关系,他就在socket.io-clientmo模块里面

这里写图片描述

    这里我们就不买关子了,居然找到资源文件了,哪我们就看作者是如何将这个资源文件静态化的。这里我们还是要回到前面的socket.io模块中去,因为他是我们直接引入的模块,打开入口文件index.js,从代码中收索我们要找的socket.io相关字样很快我们可以发现这一段代码:

var clientSource = undefined;//定义静态资源内容变量

/**
 * Server 构造函数.
 *
 * @param {http.Server|Number|Object} srv http server, port or options
 * @param {Object} [opts]
 * @api public
 */
function Server(srv, opts){
  if (!(this instanceof Server)) return new Server(srv, opts);
  if ('object' == typeof srv && srv instanceof Object && !srv.listen) {
    opts = srv;
    srv = null;
  }
  opts = opts || {};
  this.nsps = {};
  this.path(opts.path || '/socket.io');
  this.serveClient(false !== opts.serveClient);
  this.parser = opts.parser || parser;
  this.encoder = new this.parser.Encoder();
  this.adapter(opts.adapter || Adapter);
  this.origins(opts.origins || '*:*');
  this.sockets = this.of('/');
  //这一句实现了静态资源socket.io.js
  if (srv) this.attach(srv, opts);
}

我们看看我们在服务端express是如何搭建socket服务的:

var app = require("express")();
var socket = require("socket.io");
var port = 8080
app.set('port', port);
var server = http.createServer(app);
var io = socket(server);
server.listen(port);

顺便说一句express4.x和koa2在使用socket.io上都大同小异。socket(server)其实在启动websocket服务的时候,同时还相当于给这个http服务增加了一条处理/socket.io/socket.io.js的路由,(这里说明一点,不一定是websocket服务,socket.io做了降价处理,当浏览器不支持websocket时,他会自动切换到comet4j模式上去,这里我们不考虑comet4j),我们也可以不将websocket服务挂载到当前端口,也可以另外起端口,这里不多说,主要还是弄清楚socket.io.js时哪里来的。

总结:

    前面将来这么多,其实‘src=”/socket.io/socket.io.js”‘在nodejs 服务的实现方式有两种:

var io = socket(server);

    一种就是当传入server是一个http对象的时候,上面这句代码会在出传入的server对象上添加两条处理/socket.io/socket.io.js和/socket.io/socket.io.js.map的路由,然后将对应的文件响应给http请求,
    另外一种就是当传入的server是一个数字(端口)的时候,socket(server)会重新启动一个监听在该端口的http服务,然后将上面提到的哪两条路由挂在新端口的http服务下。这样当我们在使用

<script type="text/javascript" src="/socket.io/socket.io.js"></script>

加载外部脚本的时候就能保证socket.io.js的资源的正确加载了。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值