React+MongoDB+Express部署后WebSocket连接失败问题求助
用户认证功能部署后登录失败问题
问题详情
本地开发时用户认证(注册、登录)功能正常,但部署到Heroku域名环境后出现错误:
WebSocketClient.js:16 WebSocket connection to 'my_domain' failed:
环境信息
- 前端:React.js
- 部署平台:Heroku
- 服务器端口:4000(本地)
- 登录成功跳转目标:/Cards页面
相关代码
服务器index.js
const express = require("express"); const cors = require("cors"); const mongoose = require("mongoose"); const authRoutes = require("./Routes/AuthRoutes"); const app = express(); const cookieParser = require("cookie-parser"); require("dotenv").config(); app.listen(4000, () => { console.log("Sever started on 4000"); }); mongoose.set("strictQuery", false); mongoose .connect(process.env.DB_URL, { useNewUrlParser: true, useUnifiedTopology: true, }) .then(() => { console.log("Successfully connected to MongoDB Atlas!"); }) .catch((err) => { console.log(err.message); }); app.use( cors({ origin: [ "http://localhost:3000", ], method: ["GET", "POST"], credentials: true, }) ); app.use(cookieParser()); app.use(express.json()); app.use("/", authRoutes);
登录页Login.js
import React, { useState, useEffect } from "react"; import axios from "axios"; import { Link, useNavigate } from "react-router-dom"; import { useCookies } from "react-cookie"; import { ToastContainer, toast } from "react-toastify"; import "../Login.css"; function Login() { const [cookies] = useCookies([]); const navigate = useNavigate(); useEffect(() => { if (cookies.jwt) { navigate("/Cards"); } }, [cookies, navigate]); const [values, setValues] = useState({ email: "", password: "" }); const generateError = (error) => toast.error(error, { position: "bottom-right", }); const handleSubmit = async (event) => { event.preventDefault(); try { const { data } = await axios.post( "http://localhost:4000/login", { ...values, }, { withCredentials: true } ); if (data) { if (data.errors) { const { email, password } = data.errors; if (email) generateError(email); else if (password) generateError(password); } else { navigate("/Cards"); } } } catch (ex) { console.log(ex); } };
问题原因及解决步骤
1. 硬编码API地址导致请求错误
Login.js中登录请求地址写死为http://localhost:4000/login,部署到线上后,前端会尝试访问用户本地的4000端口,而非Heroku服务器地址。
- 解决:用环境变量存储API地址。在React项目根目录创建
.env文件:
然后修改Login.js中的请求地址:REACT_APP_API_URL=https://你的Heroku应用域名.herokuapp.comawait axios.post( `${process.env.REACT_APP_API_URL}/login`, { ...values }, { withCredentials: true } )
2. CORS配置未包含生产域名
服务器CORS仅允许http://localhost:3000的请求,线上前端域名不在白名单中,跨域请求被拦截,进而触发WebSocket相关错误(若有实时通信依赖)。
- 解决:将Heroku前端域名添加到CORS的
origin列表,注意原代码中method应为复数methods:
更灵活的方式是用环境变量配置:在Heroku后台设置app.use( cors({ origin: [ "http://localhost:3000", "https://你的Heroku应用域名.herokuapp.com" ], methods: ["GET", "POST"], credentials: true, }) );ALLOWED_ORIGINS为http://localhost:3000,https://你的Heroku应用域名.herokuapp.com,然后修改服务器代码:const allowedOrigins = process.env.ALLOWED_ORIGINS.split(","); app.use(cors({ origin: allowedOrigins, methods: ["GET", "POST"], credentials: true }));
3. Heroku端口固定配置错误
Heroku会动态分配端口,代码中app.listen(4000)会导致服务器无法正常启动。
- 解决:使用Heroku提供的
PORT环境变量:const PORT = process.env.PORT || 4000; app.listen(PORT, () => { console.log(`Server started on ${PORT}`); });
4. WebSocket连接排查
错误提示为WebSocket连接失败,需确认:
- 是否项目中确实使用了WebSocket(如Socket.io),若是则需确保服务器和客户端均使用正确域名,且CORS配置允许WebSocket跨域;
- 若未使用WebSocket,检查是否有依赖库意外触发了WebSocket连接,可通过浏览器开发者工具的Network面板定位请求来源。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

