Vue+Vite WebSocket 连接失败与 502 错误排查
2025-01-14 13:06:58
Vue+Vite 项目 WebSocket 连接失败及 502 Bad Gateway 错误排查
使用 Vue 和 Vite 构建的项目部署时,可能会遇到 WebSocket connection to wss failed
错误和 502 Bad Gateway
问题。这种情形通常发生在配置了 HTTPS 并通过 Docker 容器化部署时。 以下探讨问题的根源和一些解决办法。
问题剖析
根本原因在于 HTTPS 环境下 WebSocket 连接的安全要求。开发环境使用 HTTPS 时,Vite 会默认尝试通过 wss://
建立 WebSocket 连接。如果客户端尝试建立 wss 连接失败,就会返回502 Bad Gateway
。由于浏览器的安全限制, wss
连接通常需要与页面地址的域名保持一致,并进行适当配置才能生效。如果使用了如 localhost:8080
这类本地地址, 或使用了错误的证书, 连接就可能中断。此外,反向代理(如 Nginx)在处理 WebSocket
请求时,可能需要特殊配置。 错误信息往往指向配置问题或反向代理设置的不匹配。
解决方案一:调整 vite.config.js
HTTPS 设置
vite.config.js
文件中的 HTTPS 配置不正确或不完整,可能会引发该错误。具体地讲,当Vite 启动 https server 时, 客户端通过 wss://
连接。这时服务端必须是公网地址才能让客户端访问成功。 一种方式是通过 Nginx 将 wss://websitename.xyz/
反向代理到 Vite 服务的 wss://localhost:8080/
。如果前端代码访问的域名与vite配置不符, 或者 Nginx配置不正确,连接便可能失效。 简单粗暴的方式是通过注释掉 vite.config.js
文件中的 https
配置来禁用HTTPS,虽然可以临时解决问题,但是不推荐。 为了解决问题,首先应当保证Vite 使用 wss
连接时的地址可以正常访问。 其次应该使用Nginx进行反向代理。
步骤:
- 检查
vite.config.js
的 HTTPS 配置。确保key
和cert
配置指向的证书路径正确,且证书本身有效。同时检查server.host
是否是0.0.0.0
,以便可以在docker外部被访问到。 - 修改 Nginx 配置。确保 Nginx 反向代理正确配置了 WebSocket 连接所需的
upgrade
和connection
请求头,正确地转发请求到localhost:8080
,如下列nginx配置实例:
server {
listen 443 ssl http2;
server_name websitename.xyz;
ssl_certificate /etc/letsencrypt/live/websitename.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/websitename.xyz/privkey.pem;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
-
使用以下代码检查当前机器
8080
端口是否开放:sudo lsof -i :8080
如果显示正常端口已占用, 说明vue 项目正常运行。
-
如果使用
docker compose up
, 需要确保nginx配置是在 docker-compose.yml中进行,并且websitename.xyz
是指向了 docker 服务机器的公网 IP 的。 -
完成以上配置后,务必重启 docker 以及 nginx 服务
代码示例 (vite.config.js
):
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import fs from 'node:fs'
export default defineConfig({
plugins: [vue()],
server: {
port: 8080,
host: '0.0.0.0',
// 取消以下注释则取消 https
/* https: {
key: fs.readFileSync('./privkey.pem'),
cert: fs.readFileSync('./fullchain.pem'),
} */
}
})
额外提示:
- Nginx需要与docker使用同一个证书。
- 在某些云服务器环境中,防火墙可能会阻碍对特定端口的访问。需要检查服务器的防火墙规则,确保8080端口对外开放,或者是使用更常见的如
80
,443
等端口。
解决方案二: 使用 build 命令 规避 开发环境 Websocket 连接问题
如果你的项目并不需要 热重载(hot reload)
功能,一种简单且有效的方式是,使用 build
命令 构建生产版本代码,并在 serve
的时候指定主机名 host
和 端口 port
。build
命令生成静态文件,省去了 Web Socket 的复杂性,并直接部署。通过 Dockerfile 在容器启动时执行 build 操作。 如果一定要使用热重载功能, 应按照 “解决方案一” 中的方法进行调整。
步骤:
-
修改 Dockerfile。使用
npm run build
命令构建项目,并将serve
指令修改为npm run serve -- --host 0.0.0.0 --port 8080
,让程序运行在特定的host和port 上, 确保生产环境没有热重载等调试需求, -
构建 Docker 镜像并运行容器,检查是否依然有
502 Bad Gateway
和WebSocket connection
的错误。
代码示例 (Dockerfile):
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN ["npm", "run", "build"]
CMD ["npm", "run", "serve", "--", "--host", "0.0.0.0", "--port", "8080"]
补充说明:
- 使用
build
命令时,生产版本代码会编译压缩,访问速度会明显提升。 - 这种方式禁用了
Vite
热重载功能。修改源代码需要重新构建容器才能生效。
通过对 vite.config.js
配置,以及Dockerfile设置的优化调整,基本上能够应对部署时常见的 WebSocket 和 502 问题。解决过程中注意理解错误的本质和系统配置的运作原理, 可以有效避免重复性错误。 务必认真排查 Nginx
配置文件与证书相关的问题。