webentwicklung-frage-antwort-db.com.de

"ReferenceError: WebSocket ist nicht definiert" bei Verwendung von RxJs WebSocketSubject und Angular Universal

Ich bin dabei, ein angle 6.x-Univeral-Projekt einzurichten, um seine SSR-Funktionen (serverseitiges Rendern) zu nutzen. In meiner App verwende ich die Websocket-Kommunikation mit RxJs.

Genauer gesagt, ich verwende WebSocketSubject und webSocket in meinem Projekt für das geneigte Universal 6.x, das auf der Browserplattform einwandfrei funktioniert. Beim Ausführen des Node-Webservers (der das SSR-Material (serverseitiges Rendering) enthält) wird jedoch ein Fehler ausgegeben:

ReferenceError: WebSocket ist nicht definiert

Beispielcode:

// 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));

Bitte beachten Sie, dass der Fehler nicht in der Browserversion auftritt der App (d. H. ng serve gibt den Fehler nicht aus), sondern erst nach dem Kompilieren der SSR-Dateien und dem Ausführen des Express-Webservers. Um den Fehler zu reproduzieren, müssen die Builds zuerst ausgeführt werden:

# 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'

Ich habe auch ein Reproduktions-Repo eingerichtet.

Umgebung verwende ich:

  • Laufzeit: Angular 6
  • RxJS-Version: 6.2.0, 6.2.1, 6.2.2 (alle getestet)

Bearbeiten Sie 2018-08-02

Ich konnte das Problem genauer angehen. Es scheint, dass dies auch ein Webpack-Problem ist. Angular Universal erstellt ein js-Bundle für die Ausführung der Winkel-App auf dem Knotenserver, auf Node ist jedoch keine Websocket-Implementierung vorhanden. Daher muss es manuell als Abhängigkeit hinzugefügt werden (npm-Paket). Ich habe versucht, es zum js-Server-Bundle hinzuzufügen (const WebSocket = require('ws'); manuell, was das Problem löst (dh ReferenceError verschwindet). Wenn ich es jedoch zu dem TypeScript-Code hinzufüge, der später in das js-Bundle transkompiliert wird, ist dies der Fall funktioniert nicht.

Weitere Details

  • Der Webpack-Loader ts-loader wird zum Kompilieren von TypeScript => JavaScript verwendet
  • Die Websocket-Abhängigkeit wurde zu package.json hinzugefügt: "ws": "^6.0.0"
  • Wenn Sie versuchen, auf die ws-Abhängigkeit zu verweisen, indem Sie const WebSocket = require('ws'); zum nicht kompilierten TypeScript-Code hinzufügen, wird das Problem nicht gelöst . Es würde in var WebSocket = __webpack_require__(333); in der js-Ausgabedatei kompiliert, die Abhängigkeit kann nicht aufgelöst werden.
  • Manuell Ändern von var WebSocket = __webpack_require__(333); => const WebSocket = require('ws'); in der kompilierten js-Datei würde das Problem lösen , aber natürlich ist es ein Hack.

Die Fragen lauten also:

  • Kann ich ein Webpack zwingen, die Abhängigkeit const WebSocket = require('ws'); => const WebSocket = require('ws'); zu kompilieren (keine Änderungen)?
  • Oder wäre es vielleicht eine bessere Lösung, diese Abhängigkeit im eunigen npm-Paket für Winkel zu registrieren und eine Pull-Anforderung zu erstellen?
10
Ronin

Alles was es braucht ist folgendes:

// set WebSocket on global object
(global as any).WebSocket = require('ws');

Und natürlich benötigen wir auch die ws-Abhängigkeit in package.json:

npm i ws -s

2
Ronin

Die RxJS-Funktion webSocket kann einen WebSocket-Konstruktor als Argument erhalten. Dies kann verwendet werden, um webSocket in einer Nicht-Browser/Universal-Umgebung wie dieser auszuführen.

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

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