I recently configured a server with the following software organization (with dev.com
being aliased from localhost
during development):
------ if (dev.com) ----> localhost:3000
|
dev.com:443 / api.dev.com:443 --- [compute / nginx reverse proxy]
|
------ if(api.dev.com) ----> localhost:8000
My React app seems to work fine other than these messages in the developer console printing periodically:
I think this may have something to do with webpack. I am not familiar enough with webpack to know what it may be doing here. I found that if I set env WDS_SOCKET_PORT=443
then the connections continue to fail but look like so:
Connections to dev.com:443
should route to the same server through the proxy as connections to download the initial site bundle. So I’m not sure what’s going wrong here.
The callstack:
My deps:
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.4.0",
"bootstrap": "^5.3.0",
"jwt-decode": "^3.1.2",
"nodemon": "^2.0.22",
"react": "^18.2.0",
"react-bootstrap": "^2.8.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.0",
"react-scripts": "^5.0.1",
"web-vitals": "^2.1.4"
},
This was not happening until I proxied the server behind nginx. Any idea whats going on here? Bonus points if you know why webpack maintains this continuous connection to the server.
After exporting DEBUG='express:*'
in the env I am able to see debug log from the webpack development server. It appears to be routed the /ws
requests from the reverse proxy – it just doesn’t seem to care and returns a 404.
express:router dispatching GET /ws +6s
express:router query : /ws +0ms
express:router expressInit : /ws +1ms
express:router handleWebpackInternalMiddleware : /ws +0ms
express:router compression : /ws +0ms
express:router trim prefix (/ws) from url /ws +0ms
express:router bound setHeaders /ws : /ws +0ms
express:router middleware : /ws +1ms
express:router serveStatic : /ws +0ms
express:router <anonymous> : /ws +9ms
express:router middleware : /ws +1ms
express:router serveStatic : /ws +0ms
express:router middleware : /ws +7ms
express:router bound serveMagicHtml : /ws +6ms
express:router trim prefix (/ws) from url /ws +0ms
express:router middleware /ws : /ws +0ms
express:router redirectServedPathMiddleware : /ws +1ms
express:router noopServiceWorkerMiddleware : /ws +0ms
2
Answers
It looks like you are using a stack that includes react, webpack and webpack dev server.
Webpack dev server will build bundles at start, but it can also (re)build during runtime if source files are changed. That’s why the client wants a Websocket, to monitor for changes and update the website live (ie. without refreshing) …
Changing WDS_SOCKET_PORT to 443 is fine. (or 0 should translate to what the browser uses for the site).
You have a nginx reverse proxy server, but it fails with the websocket. Websocket does use http(s) to setup but then upgrades the connection to websocket. Nginx does not pass the Upgrade (and Connection) http header by default, so the upgrade fails.
Easiest solution is the add an additional location to nginx:
Webpack’s Dev Server uses a WebSocket to give you Hot Module Replacement (HMR) support. This way, it can push updates (or compilation errors) to the browser as you code, so that you can see changes immediately without having to refresh the whole page/tab.
It seems that the issue you are facing is that, because you are using a proxy, your client code can’t connect to Webpack Dev Server’s WebSocket server (listening at
wss://localhost:3000/ws
), because the proxy is blocking those requests.You could manually set
webSocketURL
so that your client knows the right URL for the WebSocket server (regardless of the proxy), as stated in the docs:Note this option will only affect your development builds / flow, it won’t have any effect in production.
Alternatively, you could update your proxy to also pass the WebSocket requests forward to
localhost:3000
(just like with the HTTP requests), as in@user7994388
‘s answer.