问题 如何使BrowserSync与nginx代理服务器一起使用?


(如果需要,请参阅 我的上一个问题 获取更多背景信息。)

我正在开发一个使用分离的前端和后端的应用程序:

  • 后端是一个Rails应用程序(服务于 localhost:3000)主要提供REST API。
  • 前端是一个AngularJS应用程序,我正在与Gulp建立并在本地服务(使用 BrowserSync) 上 localhost:3001

让两个人互相交谈,同时尊重 同源政策,我配置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服务器。

来自我的BrowserSync任务 gulpfile.coffee

gulp.task 'browser-sync', ->
  browserSync
    server:
      baseDir: './dist'
      directory: true
    port: 3001
    browser: 'google chrome'
    startPath: './index.html#/foo'

这一切基本上都有效,但我想解决一些警告:

  • 当我运行gulp任务时,基于上面的配置,BrowserSync会在其中加载Chrome选项卡 http://localhost:3001/index.html#/foo。既然我正在使用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代理混淆了。

如何解决这些问题以使其无缝运行?

谢谢你的任何输入!


10891
2017-12-30 21:45


起源



答案:


要更好地控制打开页面的方式,请使用 OPN 而不是浏览器同步的机制。这样的事情(在JS中 - 对不起,我的咖啡脚本有点生锈):

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不熟悉,但根据 这一页,第二个问题的解决方案可能如下所示:

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";
    }
}

6
2017-12-31 15:13



非常感谢!这很有效。我不得不做一些小调整 - (a)在gulpfile中,通过属性访问url bs.options.urls.local代替 bs.options.url (看起来API可能略有改变?),以及(b)在nginx.conf中,将BrowserSync proxy_pass设置为 http://localhost:3001代替 http://localhost:3002 (我假设这是为了指定BrowserSync服务器,而不是nginx代理)。再次感谢您的时间和帮助 - 非常感谢! - Bungle


答案:


要更好地控制打开页面的方式,请使用 OPN 而不是浏览器同步的机制。这样的事情(在JS中 - 对不起,我的咖啡脚本有点生锈):

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不熟悉,但根据 这一页,第二个问题的解决方案可能如下所示:

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";
    }
}

6
2017-12-31 15:13



非常感谢!这很有效。我不得不做一些小调整 - (a)在gulpfile中,通过属性访问url bs.options.urls.local代替 bs.options.url (看起来API可能略有改变?),以及(b)在nginx.conf中,将BrowserSync proxy_pass设置为 http://localhost:3001代替 http://localhost:3002 (我假设这是为了指定BrowserSync服务器,而不是nginx代理)。再次感谢您的时间和帮助 - 非常感谢! - Bungle


我只能通过追加成功 /browser-sync/socket.io 到proxy_pass网址。

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";
    }
}

3
2018-05-19 16:01



刚刚发现了 proxy_pass http://localhost:3001/ 不同于 proxy_pass http://localhost:3001。同 proxy_pass http://localhost:3001,位置部分自动附加。 - rnons


您也可以通过使用它来非常简单地从gulp / browsersync端执行此操作 代理选项

gulp.task('browser-sync', function() {
    browserSync({
        ...
        proxy: 'localhost:3002'
    });
});

这意味着您的浏览器会像通常gulp一样直接连接到browsersync,除非它代理nginx。只要您的前端不是URL中的主机/端口的硬编码,对Rails的请求将通过代理并具有相同的来源,因此您仍然可以POST等。对于某些人来说这可能是合乎需要的,因为开发设置的这种更改会在代码的开发部分(gulp + browsersync)中进行,而不是条件化/更改也在生产中运行的nginx配置。


1
2018-04-22 00:16



确实。这就足够了! - Dani


设置浏览器同步以使用通过websocket在uwsgi上运行的python(django)应用程序。 Django应用程序以/ app为前缀生成看起来像的URL http://example.com/app/admin/

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;
  }

}

0
2017-07-14 13:39