Angular Universal (ssr-dev-server) 在 dev:ssr 中设置或获取 Express 应用程序的随机端口

问题描述 投票:0回答:1

我正在尝试在 Angular Universal 的 Express 应用程序中调用 Websocket 服务器。


在生产中使用时效果很好

npm run serve:ssr

> [email protected] serve:ssr
> node dist/evaluator/server/main.js

Node Express app listening on http://localhost:4000

我可以通过

ws://localhost:4000

调用 websocket

但是在本地开发模式下

npm run dev:ssr

构建器中的以下代码行

https://github.com/angular/universal/blob/main/modules/builders/src/ssr-dev-server/utils.ts#L22

export function getAvailablePort(): Promise<number> {
  return new Promise((resolve, reject) => {
    const server = createServer();
    server
      .unref()
      .on('error', reject)
      .listen(0, () => {
        const { port } = server.address() as AddressInfo;
        server.close(() => resolve(port)); // This port is random
      });
  });
}

为 Express 服务器 (SSR) 设置动态影响的随机端口

process.env['PORT']

server.ts 中的代码(快速服务器端)


export function app(): express.Express {
  const express_app = express();
  // ....
  return express_app;
}

function run(): void {
  const port = process.env['PORT'] || 4000; // that process port comes from the above builder utils

  // Start up the Node app
  const express_app = app();
  const server = http.createServer(express_app);
  const wss = new WebSocketServer({ server });

  wss.on('connection', (ws) => {
    ws.on('message', (message) => {
      ws.send(JSON.stringify('mess ' + message));
    });
  });
  server.listen(port, () => {
    console.log(`Node Express app listening on http://localhost:${port}`);
  });
}

此注释指出您可以通过config设置端口

https://github.com/angular/universal/issues/1628#issuecomment-616322722

但在我看来,角度默认 4200 端口存在混淆(您可以在 angular.json 中设置,如文档所述)https://github.com/angular/universal/blob/main/modules/ builders/README.md#ssr-dev-server),但它不会影响始终是随机的 Express 服务器端口。

如果我将 /node_modules/@nguniversal/builders/src/ssr-dev-server/utils.jsL27 中的端口强制为 4000,那么 Express 应用程序将在端口 4000 上启动,然后我可以使用 for 代理 proxy.conf.json 中的请求实例

{
  "/ws": {
    "target": "ws://localhost:4000",
    "secure": false,
    "ws": true
  }
}

否则我不知道如何获取该动态端口来请求 Websocket。看来 Angular Universal 的代理魔法只能代理

http://localhost:4200/
到 Express 路由器,而不是
ws://localhost:4200/
。所以我请求 websocket 的唯一方法是将
ws://localhost:4200/ws
代理到
ws://localhost:4000/

我在 app.component.ts 中的代码(角度前端)

  constructor(
    @Inject(PLATFORM_ID) private platformId: InjectionToken<Record<string, unknown>>,
    @Inject(DOCUMENT) private document: Document
  ) {
    this.window = this.document.defaultView as Window;
    if (this.isBrowser) {
      const myWebSocket = webSocket(this.window.location.href.replace('http', 'ws')); 
    
    // open a socket to ws://localhost:4200/

    // so here the PORT is not correct ws://localhost:4200/ does not reply 
    // because the port is dynamicaly set unless I hard fix it to 4000 in utils 
    // and set it here too instead of Angular 4200 port

      myWebSocket.asObservable().subscribe(dataFromServer => {
        console.log(dataFromServer);
      });
      myWebSocket.next(JSON.stringify({}));
    }

我的问题是如何设置此端口或如何在角度侧获取此动态 process.env['PORT'] ?

Compiled successfully.
Node Express app listening on http://localhost:43481 // How can I set this port ? or how can I get it in app component

** Angular Universal Live Development Server is listening on http://localhost:4200, open your browser on http://localhost:4200 **

相关:

具有角度通用的WebSocket

https://github.com/angular/universal/issues/1848

https://github.com/angular/universal/issues/1722

感谢您的阅读

angular express websocket port universal
1个回答
0
投票

我今天才遇到这个问题,确实很令人沮丧。我解决这个问题的方法是在

development
上创建另一个服务器(wss),但在
production
上使用与express服务器相同的服务器:

  const port = process.env['PORT'] || 4000;

  // Start up the Node server
  const app = await init();
  const server = createServer(app);

  // Initialize WebSocket server
  initWSS(server);

  server.listen(port, () => {
    console.log('Server listening on port ' + port);
    // console.log('Node Express server listening on http://localhost:', port);
  });

这是

initWSS
:

export const initWSS = (server: Server) => {
  const env = process.env['NODE_ENV'];

  if(env === 'production') wss = new WebSocketServer({ server });
  else wss = new WebSocketServer({ port: 4202 });
  ...

因此,如果环境是

development
,则创建另一个wss服务器并将其分配到固定端口(在我的情况下为wss为4202,为主服务器为4201)。否则,只需在生产时将express和wss服务器加入到
process.env['PORT']
中即可。

© www.soinside.com 2019 - 2024. All rights reserved.