如何使 BrowserSync 与 nginx 代理服务器一起工作?
Posted
技术标签:
【中文标题】如何使 BrowserSync 与 nginx 代理服务器一起工作?【英文标题】:How to make BrowserSync work with an nginx proxy server? 【发布时间】:2015-02-27 01:33:09 【问题描述】:(如果需要,请参阅my last question 了解更多背景信息。)
我正在开发一个使用分离的前端和后端的应用程序:
后端是一个主要提供 REST API 的 Rails 应用(在localhost:3000
上提供服务)。
前端是一个 AngularJS 应用程序,我正在使用 Gulp 构建它并在 localhost:3001
上本地提供服务(使用 BrowserSync)。
为了让两端相互通信,同时尊重same-origin policy,我配置了 nginx 作为两者之间的代理,在localhost:3002
上可用。这是我的 nginx.conf:
worker_processes 1;
events
worker_connections 1024;
http
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server
listen 3002;
root /;
# Rails
location ~ \.(json)$
proxy_pass http://localhost:3000;
# AngularJS
location /
proxy_pass http://localhost:3001;
基本上,任何对 .json
文件的请求,我都会发送到 Rails 服务器,而任何其他请求(例如,静态资产),我都会发送到 BrowserSync 服务器。
来自我gulpfile.coffee
的 BrowserSync 任务:
gulp.task 'browser-sync', ->
browserSync
server:
baseDir: './dist'
directory: true
port: 3001
browser: 'google chrome'
startPath: './index.html#/foo'
这一切基本上都有效,但有几个我正在尝试解决的警告:
当我运行 gulp 任务时,基于上述配置,BrowserSync 会在http://localhost:3001/index.html#/foo
加载一个 Chrome 选项卡。但是,由于我使用的是 nginx 代理,因此我需要端口为 3002。有没有办法告诉 BrowserSync,“在端口 3001 上运行,但在端口 3002 上启动”?我尝试为startPath
使用绝对路径,但它只需要相对路径。
每次 BrowserSync 启动时,我都会在控制台中收到一个(看似良性的)javascript 错误:WebSocket connection to 'ws://localhost:3002/browser-sync/socket.io/?EIO=3&transport=websocket&sid=m-JFr6algNjpVre3AACY' failed: Error during WebSocket handshake: Unexpected response code: 400
。不确定这到底是什么意思,但我的假设是 BrowserSync 被 nginx 代理弄糊涂了。
如何解决这些问题以使其无缝运行?
感谢您的任何意见!
【问题讨论】:
【参考方案1】:设置浏览器同步以使用通过 websocket 在 uwsgi 上运行的 python (django) 应用程序。 Django 应用程序以 /app 为前缀,以生成类似于 http://example.com/app/admin/ 的 url
server
listen 80;
server_name example.com;
charset utf-8;
root /var/www/example/htdocs/static;
index index.html index.htm;
try_files $uri $uri/ /index.html?$args;
location /app
## uWSGI setup
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:///var/run/example/uwsgi.sock;
uwsgi_param SCRIPT_NAME /app;
uwsgi_modifier1 30;
location /media
alias /var/www/example/htdocs/storage;
location /static
alias /var/www/example/htdocs/static;
【讨论】:
【参考方案2】:您也可以从 gulp/browsersync 端非常简单地使用它的proxy option:
gulp.task('browser-sync', function()
browserSync(
...
proxy: 'localhost:3002'
);
);
这意味着你的浏览器像往常一样通过 gulp 直接连接到 browsersync,除了现在它代理 nginx。只要您的前端没有在 URL 中硬编码主机/端口,对 Rails 的请求将通过代理并具有相同的来源,因此您仍然可以 POST 等。这对于某些人来说可能是可取的,因为开发设置的这种更改是在代码的开发部分(gulp+browsersync)而不是条件化/更改也在生产中运行的 nginx 配置。
【讨论】:
确实如此。这就够了!【参考方案3】:我只有将/browser-sync/socket.io
附加到proxy_pass url 才能成功。
map $http_upgrade $connection_upgrade
default upgrade;
'' close;
server
# ...
# BrowserSync websocket
location /browser-sync/socket.io/
proxy_pass http://localhost:3001/browser-sync/socket.io/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
【讨论】:
刚发现proxy_pass http://localhost:3001/
和proxy_pass http://localhost:3001
不一样。使用proxy_pass http://localhost:3001
,会自动附加位置部分。【参考方案4】:
要更好地控制页面的打开方式,请使用opn 而不是浏览器同步机制。像这样的东西(在 JS 中 - 抱歉,我的 Coffee Script 有点生疏了):
browserSync(
server:
// ...
,
open: false,
port: 3001
, function (err, bs)
// bs.options.url contains the original url, so
// replace the port with the correct one:
var url = bs.options.urls.local.replace(':3001', ':3002');
require('opn')(url);
console.log('Started browserSync on ' + url);
);
我对 Nginx 不熟悉,但是根据this page 的说法,第二个问题的解决方案可能是这样的:
map $http_upgrade $connection_upgrade
default upgrade;
'' close;
server
# ...
# BrowserSync websocket
location /browser-sync/socket.io/
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
【讨论】:
非常感谢!这很好用。我不得不做一些小的调整 - (a) 在 gulpfile 中,通过属性bs.options.urls.local
而不是 bs.options.url
访问 url(看起来 API 可能略有变化?),以及 (b) 在 nginx 中。 conf,将 BrowserSync proxy_pass 设置为 http://localhost:3001
而不是 http://localhost:3002
(我假设这是为了指定 BrowserSync 服务器,而不是 nginx 代理)。再次感谢您的时间和帮助 - 他们非常感谢!以上是关于如何使 BrowserSync 与 nginx 代理服务器一起工作?的主要内容,如果未能解决你的问题,请参考以下文章
将 browsersync 与 gulp/nodemon 一起使用
代理URL不能与BrowserSync Gulp任务一起使用