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:
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
ts-loader
wird zum Kompilieren von TypeScript => JavaScript verwendet"ws": "^6.0.0"
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.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:
const WebSocket = require('ws');
=> const WebSocket = require('ws');
zu kompilieren (keine Änderungen)?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
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,
});