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

bwitn5fc  于 2023-05-22  发布在  Nginx
关注(0)|答案(4)|浏览(185)

我的雇主有许多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时,可以对所有应用使用live reload?例如,我希望同时运行两个ng serve示例--一个用于https://localhost/my-app-1,另一个用于https://localhost/my-app-2--并为两个应用程序进行实时重新加载。
我尝试过基于HTTP Referer头(nginx中的$http_referer变量)有条件地路由流量,但并非所有的实时重载流量都包含此头。
我正在使用Angular版本6和Angular CLI。

omhiaaxx

omhiaaxx1#

你必须为你的第一个应用运行ng serve --publicHost https://localhost/my-app-1。以及其他应用程序的相应公共主机。这将确保来自/sockjs-node/的流量被发送到不同的URL。
来自--publicHost的Angular 文档“浏览器客户端(或live-reload客户端,如果启用)应该用来连接到开发服务器的URL。用于复杂的开发服务器设置,例如具有反向代理的设置。”

e4eetjau

e4eetjau2#

我已经设法设置类似的情况下与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);

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

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

请确保使用不带前导斜杠的资源,例如:<img src="assets/my-image.png">
在我的例子中,我需要一些更多的Angular 配置来处理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中两个应用程序的配置,在architect.serve.options部分:

"publicHost": "http://localhost:5000/my-app-1"

并按预期工作,包括热重新加载。

im9ewurl

im9ewurl3#

更新:现在通过Angular CLI v8.3.14修复了此问题
对于旧版本,可以使用@angular-builders/custom-webpack修复此问题:

  • npm install @angular-builders/custom-webpack --save-devyarn add @angular-builders/custom-webpack --dev
  • 按此处所述更新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`
    }
  };
};

我已经设置了一个应用修复的演示项目:https://github.com/micmro/angular-base-href-reload-socket-path-workaround

ibps3vxo

ibps3vxo4#

我通过使用localhost的子域成功地获得了类似的设置。

。。。等等
看起来基于chrome的浏览器会将localhost的任何子域解析为localhost地址。(我只在Windows上测试过Chrome和Edge)
或者,您可以始终在计算机上添加主机条目。
Nginx的配置看起来像这样:

server{ 
    listen 5080;
    server_name app1.localhost

    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;

    location / {
        proxy_pass http://127.0.0.1:4200
    }
}

....为每个应用程序重复整个服务器块,只需更改服务器名称和proxy_pass设置
我正在监听端口5080,但你当然可以使用任何端口。

相关问题