Я настраиваю универсальный проект angular 6.x, чтобы использовать его SSR (на стороне сервера Рендеринг) возможности. В своем приложении я использую связь через веб-сокеты с помощью RxJ.
В частности, я использую WebSocketSubject
и webSocket
в своем проекте angular universal 6.x, который отлично работает на платформе браузера. Однако при запуске веб-сервера узла (который содержит материал 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));
Обратите внимание, что ошибка не возникает в версии приложения для браузера (т.е. ng serve
не вызывает ошибку), а только после компиляции материала SSR и запуска экспресс-веб-сервера. Чтобы воспроизвести ошибку, сначала нужно запустить сборки:
# 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'
Я также создал репозиторий воспроизведения.
Я использую среду:
- Время выполнения: Angular 6
- Версия RxJS: 6.2.0, 6.2.1, 6.2.2 (проверено все)
Изменить 2018-08-02
Мне удалось более точно решить проблему. Похоже, это тоже проблема webpack. Angular Universal создает пакет js для запуска приложения angular на сервере узла, но изначально на Node нет реализации веб-сокета. Следовательно, его нужно добавлять вручную как зависимость (пакет npm). Я попытался добавить его в пакет js-сервера (const WebSocket = require('ws');
вручную, который решает проблему (т.е. ReferenceError исчезает). Однако, когда я добавляю его в код TypeScript, который позже трансформируется в пакет js, это не сработает.
Дополнительная информация
- Загрузчик веб-пакетов
ts-loader
используется для компиляции TypeScript => JavaScript - В package.json добавлена зависимость от веб-сокетов:
"ws": "^6.0.0"
- Попытка сослаться на зависимость ws путем добавления
const WebSocket = require('ws');
в некомпилированный код TypeScript не решит проблему. Он будет скомпилирован вvar WebSocket = __webpack_require__(333);
в выходном файле js, зависимость не может быть разрешена. - Ручное изменение
var WebSocket = __webpack_require__(333);
=>const WebSocket = require('ws');
в скомпилированном js-файле решит проблему, но, конечно же, это взлом.
Итак, вопросы:
- Могу ли я "заставить" webpack компилировать зависимость
const WebSocket = require('ws');
=>const WebSocket = require('ws');
(без изменений)? - Или, может быть, было бы лучшим решением зарегистрировать эту зависимость в универсальном пакете npm angular и создать запрос на перенос?