浏览器如何知道在哪里可以找到 socket.io?
How does the browser know where to find socket.io?
<script src="/socket.io/socket.io.js"></script>
浏览器如何知道如何从该引用中获取 socket.io?我上次检查时,我的 public 文件夹中没有 socket.io.js 文件。
更新: Socket.io 工作正常,我只是好奇它是如何使用这个神秘的路由来获取客户端 socket.io 代码的。
感谢您的详尽回答:)
实际上,这里有一些魔法。当您安装服务器端 socket.io
库并通过将其传递给您的 Web 服务器来对其进行初始化时,它会自动将路由处理程序安装到您的 Web 服务器中,以处理对 /socket.io/socket.io.js
的任何请求,并将提供 socket.io.js
文件,该文件是为客户端设计的,每当请求特定的 /socket.io/socket.io.js
路由时,都会从服务器端 socket.io 安装目录的深处为客户端设计。
因此,该文件实际上并非来自所请求的确切路径(这只是为其安装了处理程序的路径)。该文件实际上来自服务器端安装目录(node_modules/socket.io
内)。这样做的好处是,由于 socket.io 的服务器端实现和客户端实现都来自完全相同的 NPM 安装,它们总是保证是相同的版本,所以你永远不会有客户端和服务器版本不同步的问题。
作为参考,这里是 socket.io server code 的相关部分,服务于 /socket.io/socket.io.js
:
var clientSource = read(require.resolve('socket.io-client/socket.io.js'), 'utf-8');
Server.prototype.serve = function(req, res){
var etag = req.headers['if-none-match'];
if (etag) {
if (clientVersion == etag) {
debug('serve client 304');
res.writeHead(304);
res.end();
return;
}
}
debug('serve client source');
res.setHeader('Content-Type', 'application/javascript');
res.setHeader('ETag', clientVersion);
res.writeHead(200);
res.end(clientSource);
};
/**
* Attaches the static file serving.
*
* @param {Function|http.Server} http server
* @api private
*/
Server.prototype.attachServe = function(srv){
debug('attaching client serving req handler');
var url = this._path + '/socket.io.js';
var evs = srv.listeners('request').slice(0);
var self = this;
srv.removeAllListeners('request');
srv.on('request', function(req, res) {
if (0 === req.url.indexOf(url)) {
self.serve(req, res);
} else {
for (var i = 0; i < evs.length; i++) {
evs[i].call(srv, req, res);
}
}
});
};
<script src="/socket.io/socket.io.js"></script>
浏览器如何知道如何从该引用中获取 socket.io?我上次检查时,我的 public 文件夹中没有 socket.io.js 文件。
更新: Socket.io 工作正常,我只是好奇它是如何使用这个神秘的路由来获取客户端 socket.io 代码的。
感谢您的详尽回答:)
实际上,这里有一些魔法。当您安装服务器端 socket.io
库并通过将其传递给您的 Web 服务器来对其进行初始化时,它会自动将路由处理程序安装到您的 Web 服务器中,以处理对 /socket.io/socket.io.js
的任何请求,并将提供 socket.io.js
文件,该文件是为客户端设计的,每当请求特定的 /socket.io/socket.io.js
路由时,都会从服务器端 socket.io 安装目录的深处为客户端设计。
因此,该文件实际上并非来自所请求的确切路径(这只是为其安装了处理程序的路径)。该文件实际上来自服务器端安装目录(node_modules/socket.io
内)。这样做的好处是,由于 socket.io 的服务器端实现和客户端实现都来自完全相同的 NPM 安装,它们总是保证是相同的版本,所以你永远不会有客户端和服务器版本不同步的问题。
作为参考,这里是 socket.io server code 的相关部分,服务于 /socket.io/socket.io.js
:
var clientSource = read(require.resolve('socket.io-client/socket.io.js'), 'utf-8');
Server.prototype.serve = function(req, res){
var etag = req.headers['if-none-match'];
if (etag) {
if (clientVersion == etag) {
debug('serve client 304');
res.writeHead(304);
res.end();
return;
}
}
debug('serve client source');
res.setHeader('Content-Type', 'application/javascript');
res.setHeader('ETag', clientVersion);
res.writeHead(200);
res.end(clientSource);
};
/**
* Attaches the static file serving.
*
* @param {Function|http.Server} http server
* @api private
*/
Server.prototype.attachServe = function(srv){
debug('attaching client serving req handler');
var url = this._path + '/socket.io.js';
var evs = srv.listeners('request').slice(0);
var self = this;
srv.removeAllListeners('request');
srv.on('request', function(req, res) {
if (0 === req.url.indexOf(url)) {
self.serve(req, res);
} else {
for (var i = 0; i < evs.length; i++) {
evs[i].call(srv, req, res);
}
}
});
};