前端使用 Nginx 反向代理引起的热加载失败

3,444 阅读2分钟

前言

最近遇到一个因为对 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