在跟着IBM的课程学习全栈开发的时候,期间想到了我于两年前写的一个小项目,当时学习了Python的Flask框架,就异想天开地编写了一个基于频道的聊天室。当时并不知道实时通信的原理,只是简单地用Flask和SQLite——连Socket.io都没用上——实现了一个简单的类Slack聊天室。

现在见识到了更多的技术,年轻莽撞的我自然是想要重写这个项目。不过具体能不能完成,就是另外一回事了。

阅读本文需知道:

  • 我使用Jetbrains WebStorm作为IDE,新建项目也是使用了WebStorm提供的模板
  • 写这个文章时我安装的Node.js版本是v20.11.0、npm版本是10.2.4

项目结构

首先,我们需要新建两个文件夹(废话):一个是用于存放前端代码的client文件夹,另一个是用于存放后端代码的server文件夹。

在WebStorm中,先在client文件夹中新建一个React项目,然后在server文件夹中新建一个Express项目。

总体的项目结构差不多是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
总项目(其实不放在一起也OK)/
├─ client/
│ ├─ node_modules/
│ ├─ public/
│ ├─ src/
│ │ ├─ App.js
│ │ ├─ index.js
│ ├─ package.json
├─ server/
│ ├─ bin/
│ │ ├─ www
│ ├─ node_modules/
│ ├─ public/
│ ├─ routes/
│ ├─ views/
│ ├─ app.js
│ ├─ package.json
  • client文件夹中,最重要的便是src文件夹,其中的App.jsindex.js是React项目的入口文件
  • server文件夹中,最重要的便是app.js文件。不过由于bin/www文件是服务器的启动关键,所以需要修改它而不是app.js文件

后端

我们率先开始装包:

1
npm install socket.io cors nodemon

不装Express包自然是因为WebStorm已经帮我们装好了,哈哈。

Socket.io包是我们这次项目的核心。它能够轻松地实现实时通信,也就是多人聊天的基础。Cors包用于解决跨域问题,比方说我们的前端项目是运行在localhost:3000,而后端项目是运行在localhost:4000,这样就会出现跨域问题。而Nodemon包是用于自动重启服务器的,这样我们就不用每次修改代码后都手动重启服务器了,懒人福音。

我们直接来看bin/www文件。它的一行代码便告诉了我们它的作用:

1
2
3
4
5
/**
* Create HTTP server.
*/

const server = http.createServer(app);

bin/www创建了一个HTTP服务器,而app则是我们的Express应用。

在导入依赖的地方,我们先导入Socket.io和Cors包:

1
2
const cors = require('cors');
const { Server } = require("socket.io");

要想使用Cors包,我们就需要激活它:

1
app.use(cors());

在HTTP服务器被创建之后,我们就需要创建Socket.io服务器了:

1
2
3
4
5
const socketIO = new Server(server, {
cors: {
origin: "http://localhost:3000"
}
});

此处的cors选项指定了React项目的默认端口,为我们之后的前后端通信提供了便利。

接下来,我们需要监听Socket.io服务器的连接事件:

1
2
3
4
5
6
7
socketIO.on("connection", (socket) => {
console.log(`A user connected: ${socket.id}`);

socket.on("disconnect", () => {
console.log(`A user disconnected: ${socket.id}`);
});
});

这个连接事件会在客户端连接到服务器时触发,打印出客户端的ID。

最后我们要用上最先装的Nodemon包。进入package.json文件,找到scripts选项,将start选项改为:

1
2
3
{
"start": "nodemon ./bin/www"
}

至此,我们的server目录就可以先不管了。

前端

和后端一样,先来装包:

1
npm install socket.io-client

为啥不装React包呢?额……不皮了。

Socket.io-client包是用于在前端连接到Socket.io服务器的。

其实前端的代码很简单,我们只需要在App.js中写入以下代码:

1
2
import socketIO from "socket.io-client";
const socket = socketIO.connect("http://localhost:4000");

好了,大功告成,就这么简单。

后话

最后只需要在两个项目中分别运行npm start,然后打开浏览器窗口,访问localhost:3000就可以看到服务端的终端输出了。

为什么我要水这么一篇文章呢?因为我觉得这个项目的基础部分还是挺有意思的,而且我也想把我学到的东西记录下来,以便日后查阅。

好吧其实根本就是今天早上睡过头、压根没时间花在代码上,所以一整天就干了这么点实质性的东西。

水文章还是挺好玩的,以后有机会再水一篇。