如何在CodeSandbox中同时运行Socket.io服务器与React应用?
CodeSandbox脚本处理机制说明
CodeSandbox对React项目有默认启动逻辑——只要检测到是Create React App结构,就算你删掉start脚本,它也会自动调用react-scripts start启动前端,这就是你删了脚本还能正常跑React的原因。
它的脚本执行优先级是:优先读取package.json里的start脚本,但有两个前提:
- 项目类型得是Node.js或Full Stack,如果选的是纯React模板,它只会处理前端,直接忽略服务器相关脚本。
- 脚本里用到的依赖(比如
concurrently、nodemon、ts-node)必须已经装在项目里,不然脚本执行会报错,服务器根本起不来。
React + Socket.io 服务器同沙箱运行配置示例
1. 调整项目类型
在CodeSandbox里,要么新建项目时选Node.js模板,要么在现有项目的设置里把类型改成Node.js/Full Stack,这样才会完整执行你写的start脚本。
2. 修正package.json配置
你的原脚本有两个小问题:nodemon的exec参数用单引号在部分环境会出问题,还有localhost 8080作为参数传给服务器文件,得确保代码能正确接收,或者直接在服务器代码里指定端口。修正后的配置如下:
{ "main": "src/index.tsx", "scripts": { "start": "concurrently \"npm run server\" \"react-scripts start\"", "server": "nodemon --exec ts-node server/index.ts", "build": "react-scripts build" }, "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "socket.io": "^4.7.2" }, "devDependencies": { "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", "@types/node": "^20.6.0", "concurrently": "^8.2.0", "nodemon": "^3.0.1", "ts-node": "^10.9.1", "typescript": "^5.2.2", "react-scripts": "5.0.1" } }
3. 服务器代码(server/index.ts)
要处理跨域(React默认跑3000端口,服务器在8080,得允许跨域请求),代码示例:
import { createServer } from "http"; import { Server } from "socket.io"; const httpServer = createServer(); const io = new Server(httpServer, { cors: { origin: "*", // 测试阶段可以用*,正式环境换成React应用的地址 methods: ["GET", "POST"] } }); io.on("connection", (socket) => { console.log("用户连接:", socket.id); socket.on("message", (msg) => { console.log("收到消息:", msg); io.emit("message", msg); // 广播消息给所有在线用户 }); socket.on("disconnect", () => { console.log("用户断开连接:", socket.id); }); }); const PORT = process.env.PORT || 8080; httpServer.listen(PORT, () => { console.log(`服务器运行在端口 ${PORT}`); });
4. React客户端代码(src/App.tsx)
连接Socket.io服务器,注意CodeSandbox里要替换成服务器的公共域名(终端里会输出类似https://xxxx.sse.codesandbox.io的地址):
import { useEffect, useState } from "react"; import { io, Socket } from "socket.io-client"; function App() { const [socket, setSocket] = useState<Socket | null>(null); const [message, setMessage] = useState(""); const [messages, setMessages] = useState<string[]>([]); useEffect(() => { // 替换成你CodeSandbox服务器的实际地址 const newSocket = io("http://localhost:8080"); newSocket.on("message", (msg) => { setMessages(prev => [...prev, msg]); }); setSocket(newSocket); return () => { newSocket.close(); }; }, []); const sendMessage = () => { if (socket && message) { socket.emit("message", message); setMessage(""); } }; return ( <div style={{ padding: "20px" }}> <h1>Socket.io 聊天室</h1> <div> {messages.map((msg, idx) => ( <p key={idx}>{msg}</p> ))} </div> <input type="text" value={message} onChange={(e) => setMessage(e.target.value)} placeholder="输入消息..." style={{ marginRight: "10px" }} /> <button onClick={sendMessage}>发送</button> </div> ); } export default App;
关键注意点
- CodeSandbox里服务器和前端都会分配公共域名,客户端连接时别用
localhost:8080,换成服务器终端输出的实际地址,不然容易跨域失败。 - 所有依赖要确保在
package.json里,CodeSandbox会自动安装,但如果是手动加的脚本,得检查依赖有没有漏加。 - 脚本执行失败的话,直接看CodeSandbox的终端信息,比如nodemon找不到、ts-node语法错误之类的,针对性解决就行。
内容的提问来源于stack exchange,提问作者V.Rashkov
相关产品推荐
相关产品推荐

