起因
有时候前端开发需要使用域名访问到本地的项目,一般我们的操作是修改 Host ,然后通过 nginx 反向代理到本地运行的项目。然而使用最新 vue cli 创建的项目内置的是webpack 5,webpack 5实现热更新是使用了 websocket。当我们通过 https 协议的域名访问项目时,websocket 就会连接不上,导致热更新失败。
比如:我们的项目通过 dev.danny.com 访问本地运行在 8088 端口的项目
复现
使用 https 访问,就会报错
使用域名访问项目,websocket的请求连接也会变成域名,像是这样:
一般前端使用nginx只是简单代理项目,如下配置
location / {
charset utf-8;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass https://127.0.0.1:8088;
}
解决
- 经过一通折腾,发现websocket地址是带有端口号的,我们是同事443访问页面不需要带端口号,所以在nginx 层需要修改
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 转发socket协议需要指定到端口号
proxy_set_header Host $host:$server_port;
# Additional headers for WebSocket
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
- 项目本地的
vue.config.js中也需要开启https,并使用和nginx相同的证书
devServer: {
port: 8088,
headers: {
'Access-Control-Allow-Origin': '*'
},
allowedHosts: [
'dev.danny.com'
],
https:{
key: fs.readFileSync(resolvePath('cert/*.danny.com-key.pem')),
cert: fs.readFileSync(resolvePath('cert/*.danny.com.pem')),
},
client: {
logging: 'info',
overlay: true,
webSocketURL: {
hostname: 'dev.danny.com',
pathname: '/ws',
protocol: 'https'
}
}
}
结果
websocket 可以正常收到热更新推送。
本文目的是记录一下问题。 对于nginx部分的原理还不是很清楚。欢迎交流👏🏻