前言
最近遇到一个因为对 nginx 配置以及 websocket 协议不熟悉导致 webpack 热重载失败的问题,每次编辑保存后都要主动刷新网页,难以接受。。。
正常在使用 create-react-app 创建前端项目后,运行项目,如果不对默认端口配置做任何改变,项目将运行在
http://127.0.0.1:3000。但在项目调试中我们往往希望访问某个指定的域名, 比如 http://www.test.com 时能直接访问到项目,emmm...
因为项目没有使用 eject 暴露出 webpack 的相关配置,于是按官方指引在 config-overrides.js 中一顿操作,但 dev-server 部分覆盖一直未生效,于是简单粗暴,遂采用 nginx 反向代理
host 配置
配置要访问的域名到本机 ip
127.0.0.1 www.test.com
nginx 配置
相关概念解释:
server 块
- 配置虚拟主机的相关参数,一个
Http中可以有多个server
location 块
- 配置请求的路由,以及各种页面的处理情况。
nginx 配置信息:
server {
listen 80;
server_name www.test.com;
gzip on;
gzip_buffers 4 16k;
gzip_comp_level 5;
gzip_http_version 1.0;
gzip_min_length 1k;
gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon image/bmp;
gzip_vary on;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
配置 reload 后访问域名,发现热重载失效
原因
控制台提示 WebSocket connection ws://www.test.com/sockjs-nodeto failed...,WebSocket 握手失败,无法获取文件变更进行加载替换
查找资料后发现是 nginx 配置的问题,未正确配置升级为 WebSocket 协议,WebSocket 协议相比较于 HTTP 协议成功握手后可以多次进行通讯,直到连接被关闭。但是 WebSocket 中的握手和 HTTP 中的握手兼容, 它使用HTTP中的 Upgrade 协议头将连接从 HTTP 升级到 WebSocket
我们将 location 改为
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
在浏览器访问项目,热重载生效
涨知识
最重要的就是在反向代理的配置中增加了如下两行,其它的部分和普通的HTTP反向代理没有任何差别
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
这里面的关键部分在于 http 请求中添加了以下头部
Connection: Upgrade
Upgrade: websocket
这两个字段表示请求服务器升级协议为 WebSocket,服务端响应如下报文:
Status Code: 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
告诉客户端已成功切换协议,升级为Websocket协议
写在最后
需要继续巩固 http 相关知识,另外用 nginx 时间也不短了,但是对里面的具体配置,从没有去了解过为什么要这样配置。之前 proxy_set_header Host $host; 这个配置导致 proxy_pass 到网关地址请求失败,弄了一天才发现是 nginx 配置的原因,惭愧。痛定思痛,立下 flag 🐶,决心深入 nginx