我目前正在本地开发多个Vue.js单页应用程序,并在尝试将这些应用程序服务放在NGINX反向代理后遇到了各种问题。具体来说,我遇到了许多与Websockets或sockjs-node相关的错误,这会破坏vue应用程序的热重载功能(404 Not Found)。
这些SPA中的每一个都在自己的基本Node.js服务器上运行,该服务器在其服务器根目录下提供静态文件。他们应该通过NGINX反向代理访问:
http://localhost:6200/ -> http://localhost/my-app1/
http://localhost:6205/ -> http://localhost/my-app2/
http://localhost:6210/ -> http://localhost/my-app3/
对于开发,我使用npm run serve
运行所有vue.js应用程序,然后通过NGINX代理访问这些站点:http://localhost/my-appX/
。这些站点没有任何功能问题,但热重载不起作用。
在浏览器的开发者控制台中查看后,有众多GET请求的EG:
http://localhost/sockjs-node/info?t=1605955915882
。显然,这个URL是错误的,因为我们当前是通过代理访问网站 - 我原本希望看到http://localhost/my-appX/sockjs-node/info?t=1605955915882
。以下是在尝试使其工作之前我的当前配置:
我的NGINX配置:
upstream nodefrontend_myapp1 {
server localhost:6200;
}
upstream nodefrontend_myapp2 {
server localhost:6205;
}
upstream nodefrontend_myapp3 {
server localhost:6210;
}
# Redirect HTTP to HTTPS
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# 307 temporary redirect
return 307 https://$host$request_uri;
}
# HTTPS Proxy
server {
listen 443 ssl http2;
server_name localhost;
# Proxy "my-app" URI traffic to correct server
location /my-app1/ {
proxy_buffering off;
proxy_set_header Host $host;
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;
# For websockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
# Proxy to my-app's root
proxy_pass http://nodefrontend_myapp1/;
}
# Note: several other sites are running via the below routes
location /my-app2/ {
proxy_pass http://nodefrontend_myapp2/;
# ...
}
location /my-app3/ {
proxy_pass http://nodefrontend_myapp3/;
# ...
}
}
vue.config.js配置:
module.exports = {
// options...
// I want the site to be accessible *RELATIVE* to the current URL.
// This will make vue.js resources have no leading slash, eg: <link> href="css/file123.css" </link>
// And should allow me to fetch resources on the current VHOST: eg: http://localhost/my-app/css/file123.css
publicPath: "",
devServer: {
//disableHostCheck: true,
https: false,
public: "0.0.0.0",
host: "localhost" ,
port: 6200,
sockPath: "", /////////// This has been causing me issues
},
}
查看了webpack文档后,我发现应该在每个应用的vue.config.js中更新sockPath
,于是我这样做了:
sockPath: "/my-appX/sockjs-node",
这样停止了 sockjs-node 的 404 GET 错误,但是现在出现了不同的错误,关于 websockets 找不到资源:
ws://localhost/my-appX/sockjs-node/147/0dj5ee1p/websocket
。为了检查问题是 webserver 还是 NGINX,我运行了
wscat -c ws://localhost:6200/my-appX/sockjs-node/147/0dj5ee1p/websocket
,它确实工作了。这表明 NGINX 在某种程度上杀死了 websocket。为了再次确认,我通过 NGINX 测试了 websocket:wscat -c ws://localhost/my-appX/sockjs-node/147/0dj5ee1p/websocket
,这次测试却没有成功。经过几个小时的配置和 NGINX 玩耍,我在网上找到一篇文章,说我应该更改我的 NGINX proxy_pass URL,以删除结尾的斜杠。我将它从以下内容更改为:
proxy_pass http://nodefrontend_myappX/;
转化为:
proxy_pass http://nodefrontend_myappX;
通过wscat -c ws://localhost/my-appX/sockjs-node/147/0dj5ee1p/websocket
重新测试了websocket,它正常工作了!但是…在去掉前导斜杠后,网站无法加载。我的怀疑是vue.config.js的publicPath,但我束手无策。
有没有人能够在NGINX反向代理(作为虚拟主机)后运行多个Vue.js站点,并使热重载功能正常工作?
====== 我找到了一个解决方案,但我不喜欢它:
- 在服务器上以子路由的形式静态托管SPA:
http://localhost:6200/my-app
- 将NGINX反向代理_pass转到:
proxy_pass http://localhost:6200/my-app/
- 将vue.config.js文件的publicPath设置为:
publicPath: "/my-app"
- 不要设置vue.config.js的sockPath属性(删除它)。
这种配置的关键在于vue.js前端浏览器知道它位于/my-app,在/my-app上托管服务器发送请求,而NGINX实际上并不修改任何URI。
尽管此配置可行,但我不喜欢Web服务器必须在子路由上托管静态文件,且浏览器必须知道其vhost(publicPath) - 除非这是标准做法?对于浏览器了解它的publicPath (/my-appX/),我有点满意,因为它需要使用历史记录模式。
PS. 在生产中,我的原始配置使用相对publicPath正常工作。只是HRM在开发中出错了。
有人能够解决这个问题吗? 谢谢
========= 更新1)找到解决方法,不确定这是否是唯一的解决方法。
我发现我的vue.config.js devserver "public"属性设置不正确。根据webpack devserver文档,运行在浏览器中的devserver客户端(/sockjs-node)代码将通过查看其window.location变量来“猜测”服务器的位置。但是,由于我通过代理访问服务器,似乎默认情况下无法处理它。所以他们的解决方案是设置"public"属性,使客户端直接与服务器通信(跨域请求)...如果你问我的话,这有点儿hack。
因此,客户端sockjs-node现在直接从http://localhost/my-appX/到http://lcoalhost:62xx/进行通信。
这就是(例如)my-app1的vue.config.js现在的样子:
module.exports = {
// options...
publicPath: "",
devServer: {
//disableHostCheck: true,
https: false,
public: "localhost:6200", //// This line makes the client browser talk DIRECTLY to this address / server for hot reloading.
host: "0.0.0.0" ,
port: 6200,
},
}
话虽如此,现在通过http一切都按预期工作。但是,将NGINX更新为https会导致webpack-devserver sockjs-node出现CORS错误。这是因为客户端/浏览器已升级到HTTPS,但webpack-devserver仅支持http。然而,为了解决这个问题,我只需将vue.config.js devserver设置为https,CORS错误就消失了。
这似乎更像是与webpack-devserver sockjs-node的问题/限制,而不是stackoverflow问题。将问题留在此处。