Heroku部署在线剪刀石头布游戏出现404错误求助
Heroku部署后出现404错误(Cannot GET /)问题分析与解决
问题背景
本地开发的在线剪刀石头布游戏运行正常,但部署到Heroku后,控制台提示Cannot GET /及资源加载失败:服务器返回404状态码。Heroku日志显示访问根路径/时返回404。
服务器代码(index.js)
const express = require("express"); const app = express(); const http = require("http"); const { Server } = require("socket.io"); const socketio = require("socket.io"); const cors = require("cors"); app.use(cors()); const server = http.createServer(app); let players = []; let otherPlayerChoice = null; let playerChoice = null; // const io = new Server(server, { // cors: { // origin: "https://rock-paper-scissors-online.herokuapp.com", // methods: ["GET", "POST"], // }, // }); const io = socketio(server); io.on("connection", (socket) => { console.log(`User Connected: ${socket.id}`); players.push(socket.id); socket.on("join-room", (number) => { socket.join(number); }); const playerNumber = players.indexOf(socket.id); socket.emit("playerNumber", playerNumber); socket.on("disconnect", () => { console.log(`User Disconnected: ${socket.id}`); const index = players.indexOf(socket.id); players.splice(index, 1); }); socket.on("choice", (data) => { console.log(`Player ${data.playerNumber} chose ${data.choice}`); // Find the other player const otherPlayer = players.find((player) => player !== socket.id); // Get the other player's choice socket.to(otherPlayer).emit("opposing-player-move", data.choice); socket.on("test", (move) => { otherPlayerChoice = move.choice; playerChoice = data.choice; // Determine the winner let result; if (playerChoice === otherPlayerChoice) { result = "It's a tie!"; } else if ( (playerChoice === 0 && otherPlayerChoice === 2) || (playerChoice === 1 && otherPlayerChoice === 0) || (playerChoice === 2 && otherPlayerChoice === 1) ) { result = `Player ${data.playerNumber === 0 ? 1 : 0} wins!`; } else { result = `Player 2 wins!`; } // Emit the result to both players io.to(move.room).emit("game-result", result); // io.to(otherPlayer).emit("game-result", result); io.emit("disable-buttons"); }); }); }); server.listen(process.env.PORT || 5000, () => { console.log("SERVER IS RUNNING"); });
Heroku日志
2023-04-12T17:05:08.265241+00:00 app[web.1]: SERVER IS RUNNING 2023-04-12T17:05:08.543766+00:00 heroku[web.1]: State changed from starting to up 2023-04-12T17:05:10.135071+00:00 heroku[router]: at=info method=GET path="/" host=rock-paper-scissors-online.herokuapp.com request_id=1ee5c19c-7db9-48bf-a0da-dc83b386c9b2 fwd="109.96.9.152" dyno=web.1 connect=0ms service=5ms status=404 bytes=415 protocol=https
问题原因
- 根路径未处理:你的Express服务器没有配置根路径(
/)的响应逻辑,也没开启静态文件托管。本地运行时你可能直接打开前端HTML文件(file://协议),绕开了Express;但Heroku上所有请求都经过服务器,找不到对应路由就返回404。 - Socket.IO CORS配置缺失:注释掉的CORS配置会导致线上环境可能出现跨域问题,影响Socket连接。
- 全局玩家存储隐患:
players数组是全局变量,Heroku多实例部署时会导致数据不共享,但这是后续优化问题,当前首要解决404。
解决步骤
1. 开启静态文件托管
假设前端文件(HTML/CSS/JS)放在项目根目录的public文件夹下,在app.use(cors());之后添加:
app.use(express.static("public"));
这样访问根路径时,Express会自动返回public/index.html(如果存在)。
2. 兜底根路由(可选)
如果需要自定义根路径响应,添加路由处理:
app.get("/", (req, res) => { res.sendFile(__dirname + "/public/index.html"); });
3. 恢复Socket.IO CORS配置
取消注释Socket.IO的CORS配置,确保线上跨域正常:
const io = new Server(server, { cors: { origin: "https://rock-paper-scissors-online.herokuapp.com", methods: ["GET", "POST"], }, });
测试阶段可以用origin: "*"放宽限制,生产环境建议指定具体域名。
4. 确认项目配置
- 确保
public文件夹存在且包含前端文件 package.json的scripts里有正确启动命令:"scripts": { "start": "node index.js" }
内容的提问来源于stack exchange,提问作者Stefan-Yves
相关产品推荐
相关产品推荐

