如何在通过nginx反向代理托管的多个应用程序中使用“ng serve”?

时间:2018-05-14 17:17:32

标签: angular nginx webpack-dev-server

我的雇主有许多正在积极开发的Angular 2+应用程序。这些应用程序托管在nginx反向代理之后。例如,在开发期间,可以通过以下方式访问一个应用程序:

https://localhost/my-app-1

而另一个可能在:

https://localhost/my-app-2

要完成此代理行为,我将每个Angular应用配置为在使用ng serve托管时使用其他端口:

// in angular.json
{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "projects": {
        "my-project": {
            "architect": {
                "serve": {
                    "options": {

                        // each app gets its own port
                        "port": 4201

                    }
                }
            }
        }
    }
}

然后,我使用nginx将流量代理到使用此nginx配置的相应端口:

# proxy my-app-1 requests
location ^~ /my-app-1/ {

    proxy_pass http://127.0.0.1:4201/;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;

    proxy_http_version 1.1;
    proxy_cache_bypass $http_upgrade;
}

# proxy my-app-2 requests
location ^~ /my-app-1/ {

    proxy_pass http://127.0.0.1:4202/;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;

    proxy_http_version 1.1;
    proxy_cache_bypass $http_upgrade;
}

# proxy ng serve live reload traffic
location ^~ /sockjs-node/ {

    # Notice that the port is hardcoded
    # in this proxy configuration
    proxy_pass http://127.0.0.1:4201;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;

    proxy_http_version 1.1;
    proxy_cache_bypass $http_upgrade;
}

这样做有一点需要注意 - /sockjs-node/流量只会路由到两个应用中的一个(在此示例中,是在端口4201上托管的那个)。因此,实时重新加载功能一次只能用于一个应用程序。

这是我的问题:有没有办法配置nginx或Angular开发服务器,以便在通过nginx代理使用ng serve时,允许我使用所有我的应用的实时重新加载?例如,我希望同时运行两个ng serve个实例 - 一个用于https://localhost/my-app-1,一个用于https://localhost/my-app-2 - 并且可以为这两个应用进行实时重新加载。

我已尝试根据HTTP Referer标头(nginx中的$http_referer变量)有条件地路由流量,但并非所有实时重新加载流量都包含此标头。

我正在使用Angular的第6版和Angular CLI。

3 个答案:

答案 0 :(得分:1)

您必须为第一个应用程序运行ng serve --publicHost https://localhost/my-app-1。以及其他应用程序的相应公共主机。这样可以确保将来自/sockjs-node/的流量发送到其他网址。

来自--publicHost的角度文档“浏览器客户端(或实时重载客户端,如果启用)用于连接到开发服务器的URL。用于复杂的开发服务器设置,例如一个带有反向代理。”

答案 1 :(得分:0)

我设法用expresshttp-proxy-middleware设置了类似的大小写。

最相关的快递代码如下:

const http = require('http');
const express = require('express');
const proxy = require('http-proxy-middleware');
const url = require('url');

const app = express(); 
// ... some express setup

app.use('/my-app-1', proxy({
  target: 'http://127.0.0.1:4202',
  changeOrigin: true,
  pathRewrite: { '^/my-app-1': '' },
  xfwd: true,
  ws: true
}));

// analogically the same for 'my-app-2'

// redirect to default app
app.get('/', (req, res) => res.redirect(
  url.format({ pathname: '/my-app-1', query: req.query }))
);

const httpServer = http.createServer(app);
httpServer.listen(5000);

我还在<base href=...>的两个应用中都更改了index.html

<base href="/my-app-1/"> 

确保您使用的资产不带斜杠,例如:<img src="assets/my-image.png">

在我的情况下,我需要更多角度配置以使用ngx-translate处理资产:

import { APP_BASE_HREF } from '@angular/common';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

@NgModule({
  imports: [
    // ...
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: httpLoaderFactory,
        deps: [HttpClient, APP_BASE_HREF]
      }
    })
  ],
  declarations: // ...
  exports: // ...
  providers: [
    // ...
    { provide: APP_BASE_HREF, useValue: '/my-app-1/' }
  ]
})
export class AppModule {
}

export function httpLoaderFactory(http: HttpClient, baseHref) {
  return new TranslateHttpLoader(http, baseHref + 'assets/i18n/', '.json');
}

最后,我必须按照@Dennis的建议设置publicHost-我已经在angular.json的{​​{1}}部分中更新了两个应用的配置:

architect.serve.options

并且可以按预期工作,包括热重装。

答案 2 :(得分:0)

更新:此问题现已通过this

修复。

对于较旧的版本,可以使用@angular-builders/custom-webpack来解决此问题:

  • npm install @angular-builders/custom-webpack --save-devyarn add @angular-builders/custom-webpack --dev
  • 按照Angular CLI v8.3.14的说明更新angular.json
  • 添加一个./extra-webpack.config.js文件
module.exports = (config, options) => {
  if(!config.devServer) {
    // do nothing for `ng build`
    return config;
  }
  return {
    ...config,
    devServer: {
      ...config.devServer,
      sockPath: `${config.devServer.publicPath}/sockjs-node`
    }
  };
};

我已经设置了一个应用此修复程序的演示项目: here