使用RxJs WebSocketSubject和Angular Universal时,"ReferenceError:未定义WebSocket"

Ron*_*nin 10 node.js webpack angular-universal angular

我正在设置一个角度6.x通用项目,以利用其SSR(服务器端呈现)功能.在我的应用程序中,我正在使用RxJs进行websocket通信.

更具体地讲,我是,使用WebSocketSubjectwebSocket在我的角度普遍6.x的项目,该项目在浏览器平台上正常工作.但是,在运行节点Web服务器(包含SSR内容(服务器端呈现))时,会引发错误:

ReferenceError:未定义WebSocket

示例代码:

// not actually code from the reproduction repo
import { WebSocketSubject, webSocket } from 'rxjs/webSocket';

const socket: WebSocketSubject<any> = webSocket('wss://echo.websocket.org');
socket.subscribe(msg => doSomething(msg));
Run Code Online (Sandbox Code Playgroud)

请注意,应用程序的浏览器版本不会出现错误(即ng serve不会抛出错误),但只有在编译SSR内容并运行快速Web服务器之后.要重现错误,必须首先运行构建:

# install dependencies
npm install

# build angular bundles for browser and server platforms
npm run build:client-and-server-bundles

# build the webserver
npm run webpack:server

# start the webserver
npm run serve:ssr

# the app is now being served at http://localhost:8081/
# open it in the browser and the error will occur: 'ReferenceError: WebSocket is not defined'
Run Code Online (Sandbox Code Playgroud)

我还建立了一个复制回购.

我正在使用的环境:

  • 运行时:Angular 6
  • RxJS版本:6.2.0,6.2.1,6.2.2(全部测试)

编辑2018-08-02

我能够更准确地解决问题.看来,这也是一个webpack问题.Angular Universal创建了一个js包,用于在节点服务器上运行angular app,但Node上本身没有websocket实现.因此,必须手动添加它作为依赖项(npm包).我尝试将它添加到js服务器包(const WebSocket = require('ws');手动,它解决了问题(即ReferenceError消失).但是,当我将它添加到稍后被转换为js包的TypeScript代码时,它将无法工作.

更多详情

  • webpack加载器ts-loader用于编译TypeScript => JavaScript
  • websocket依赖已添加到package.json: "ws": "^6.0.0"
  • 尝试通过添加const WebSocket = require('ws');未编译的TypeScript代码来引用ws依赖项将无法解决此问题.它将被编译到var WebSocket = __webpack_require__(333);js输出文件中,依赖关系将无法解析.
  • 在编译的js文件中手动更改var WebSocket = __webpack_require__(333);=> 将解决问题,但当然这是一个黑客攻击.const WebSocket = require('ws');

所以,问题是:

  • 我可以"强制"webpack编译依赖const WebSocket = require('ws');=> const WebSocket = require('ws');(没有变化)?
  • 或者,它可能是一个更好的解决方案,在angular universal npm包中注册这个依赖项并创建一个pull请求?

Bas*_*Bas 7

RxJS webSocket 函数可以接收 WebSocket 构造函数作为参数。这可以用来在像这样的非浏览器/通用环境中运行 webSocket。

const WebSocketConstructor = WebSocket || require('ws')

const socket: WebSocketSubject<any> = webSocket({
    url: 'wss://echo.websocket.org', 
    WebSocketCtor: WebSocketConstructor,
});


// OR...

import { WebSocket, ...otherStuff... } from 'ws';
import { webSocket, ...otherStuff... } from 'rxjs/webSocket';

const socket$ = webSocket({
  url: 'wss://someplace.com',
  WebSocketCtor: WebSocket,
});
Run Code Online (Sandbox Code Playgroud)


Ron*_*nin 6

只需要这样:

// set WebSocket on global object
(global as any).WebSocket = require('ws');
Run Code Online (Sandbox Code Playgroud)

当然,我们还需要wspackage.json 中的依赖项:

npm i ws -s