Nodejs express+socket.io 跟js文件的小坑

Nodejs express+socket.io 跟js文件的小坑

如果express和socket.io同监听在一个端口,如果 express的静态目录是public 这里public/socket.io.js 这个文件 页面代码 用 <scr src=“http://host:port/socket.io.js” /> 访问不到,会提示 welcome to socket.io. 把socket.io.js改名或者放在其他目录下就能避免这个坑, 估计express中判断ws请求是用 startwith(“socket.io” 来判断的


3 回复

Nodejs express+socket.io 跟js文件的小坑

在使用Node.js结合Express和Socket.io时,可能会遇到一些小坑。其中一个常见的问题是当Express和Socket.io都监听同一个端口时,socket.io.js 文件可能无法正确加载。这会导致页面上出现“Welcome to socket.io”的提示,而不是正常的JavaScript文件。

示例代码

首先,我们来看一个简单的示例代码,展示如何配置Express和Socket.io

const express = require('express');
const http = require('http');
const socketIo = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

app.use(express.static('public'));

io.on('connection', (socket) => {
    console.log('A user connected');
    socket.emit('message', 'Welcome to socket.io');
});

server.listen(3000, () => {
    console.log('Server is running on port 3000');
});

在这个例子中,我们将静态文件夹设置为public,并且假设有一个名为socket.io.js的文件位于public/socket.io.js路径下。

遇到的问题

当你尝试通过以下方式引用socket.io.js文件时:

<script src="http://localhost:3000/socket.io/socket.io.js"></script>

你可能会发现页面上显示“Welcome to socket.io”,而不是正常的JavaScript文件。这是因为Socket.io会拦截所有以/socket.io/开头的请求,并将其处理为WebSocket连接。

解决方法

解决这个问题的一种方法是将socket.io.js文件重命名或移动到其他目录。例如,你可以将文件移动到public/js/socket.io.js目录下,并修改HTML中的引用路径:

<script src="http://localhost:3000/js/socket.io.js"></script>

或者,你也可以将socket.io.js文件直接放在public目录下,并修改引用路径:

<script src="http://localhost:3000/socket.io.js"></script>

总结

总结一下,当Express和Socket.io监听同一个端口时,Socket.io会拦截所有以/socket.io/开头的请求。因此,如果你将socket.io.js文件放在默认的静态目录中,它可能会被错误地处理为WebSocket请求。为了解决这个问题,可以将socket.io.js文件重命名或移动到其他目录,并相应地更新引用路径。

希望这个解决方案能帮助你避免这个小坑!


有个express-io项目貌似是解决这个问题的

当你使用Express与Socket.IO时,如果两者都监听同一个端口,并且你的静态文件目录设置为public,你可能会遇到一个问题:页面无法正确加载/socket.io/socket.io.js。这是因为Socket.IO内部处理WebSocket连接时会拦截对/socket.io路径的请求。

示例代码

假设你的项目结构如下:

- app.js
- public/
  - index.html

app.js

const express = require('express');
const http = require('http');
const socketIo = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

app.use(express.static('public'));

io.on('connection', (socket) => {
    console.log('A user connected');
    socket.emit('news', { hello: 'world' });
    socket.on('my other event', (data) => {
        console.log(data);
    });
});

server.listen(3000, () => {
    console.log('Server is running on port 3000');
});

public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Socket.IO Test</title>
</head>
<body>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        const socket = io();
        socket.on('news', (data) => {
            console.log(data);
        });
    </script>
</body>
</html>

解决方案

为了避免这个问题,你可以将Socket.IO的JS文件放到一个不同的目录下,或者使用Express的路由机制来区分不同类型的请求。

示例:更改静态文件目录

将Socket.IO的JS文件移到一个单独的目录,例如/assets

app.use('/assets', express.static('public'));

然后在HTML中引用它:

<script src="/assets/socket.io/socket.io.js"></script>

示例:重命名文件

你可以重命名socket.io.js文件为custom-socket.io.js,并将其移动到public目录下:

app.use(express.static('public'));

在HTML中引用:

<script src="/custom-socket.io.js"></script>

通过这些方法,你可以避免Express拦截Socket.IO的JS文件请求,从而确保静态资源能够正确加载。

回到顶部