Создание realtime чата в NestJS
Websockets - это протокол связи, который обеспечивает полнодуплексные каналы связи по одному TCP-соединению, установленному между веб-браузером и веб-сервером. Это позволяет серверу отправлять данные в браузер без запроса с клиента.
Сегодня мы рассмотрим, как мы можем использовать Websockets для обеспечения связи в реальном времени между различными браузерами, создав приложение чата в NestJS .
Итак, без лишних слов, давайте начнем.
Введение в веб-сокеты
Веб-сокеты являются альтернативой HTTP-коммуникации в веб-приложениях. Они обеспечивают постоянную связь между клиентом и сервером, которую обе стороны могут использовать для начала отправки данных в любое время.
Это может принести следующие преимущества:
- Сервер может отправлять сообщения клиенту без явного запроса клиента
- Низкая задержка связи
- Клиент и сервер могут одновременно общаться друг с другом
Вот почему Websockets превосходит HTTP, когда речь идет о долгосрочном общении в реальном времени.
Настройка проекта
Прежде чем мы сможем начать разработку проекта, давайте сначала настроим наш его и установим необходимые зависимости. Для этого вам нужно открыть свой терминал и выполнить следующие команды.
Сначала создайте проект и перейдите в его каталог.
nest new nestchat cd nestchat
После этого нам просто нужно установить зависимости с помощью менеджера пакетов npm.
npm i --save @nestjs/websockets @nestjs/platform-socket.io
Теперь, когда у нас все установлено и произведена базовая настройка проекта, давайте создадим файлы, в которых мы будем работать.
Начнем с создания модуля, службы и контроллера с помощью интерфейса командной строки NestJS.
nest g gateway app
После этого вам просто нужно создать папку с именем static в вашем каталоге src, которая содержит три файла:
- index.html - Дизайн для нашего чата
- main.js - клиентская логика websockets
- styles.css - стиль для нашего HTML-файла
Теперь структура вашего проекта должна выглядеть примерно так.
Теперь, когда мы завершили первоначальную настройку, мы можем запустить наш сервер, выполнив следующую команду.
npm run start:dev
Вуаля, первоначальная настройка завершена, теперь давайте приступим к реализации конфигурации Websockets.
Сервер веб-сокетов
Во-первых, давайте начнем с создания нашего сервера Websockets, реализовав инструменты Websocket, которые мы установили ранее. Это очень простой процесс, который требует только AppGateway, который мы создали выше.
import { SubscribeMessage, WebSocketGateway, OnGatewayInit, WebSocketServer, OnGatewayConnection, OnGatewayDisconnect, } from '@nestjs/websockets'; import { Logger } from '@nestjs/common'; import { Socket, Server } from 'socket.io'; @WebSocketGateway() export class AppGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect { @WebSocketServer() server: Server; private logger: Logger = new Logger('AppGateway'); @SubscribeMessage('msgToServer') handleMessage(client: Socket, payload: string): void { this.server.emit('msgToClient', payload); } afterInit(server: Server) { this.logger.log('Init'); } handleDisconnect(client: Socket) { this.logger.log(`Client disconnected: ${client.id}`); } handleConnection(client: Socket, ...args: any[]) { this.logger.log(`Client connected: ${client.id}`); } }
Это в основном все, что нам нужно для взаимодействия с приложением, поэтому давайте разберем его.
Сначала вы заметите, что мы украсили наш класс декоратором @WebsocketGateway()
, который дает нам доступ к функциональности socket.io.
Мы также реализовать три интерфейса OnGatewayInit
, OnGatewayConnection
и OnGatewayDisconnect
которые мы используем , чтобы добавить некоторые ключевые состояния нашего приложения. Например, мы регистрируем, когда новый клиент подключается к серверу или когда текущий клиент отключается.
Затем мы создали переменную-член с именем server, которая украшена декоратором @WebsocketServer()
, что дает нам доступ к экземпляру сервера Websockets.
Мы используем экземпляр в нашей handleMessage()
функции, где мы отправляем данные всем клиентам, подключенным к серверу, используя функцию emit()
. Функция handleMessage()
также украшена, декоратором @SubscribeMessage()
что дает возможность слушать событие с именем msgToServer
.
Прежде чем мы перейдем к клиентской части проекта, нам нужно только добавить наш шлюз в модуль.
import { Module } from '@nestjs/common'; import { AppGateway } from './app.gateway'; @Module({ imports: [], controllers: [], providers: [AppGateway], }) export class AppModule {}
Websocket клиент
Закончив сервер, давайте теперь перейдем к клиентской части этого проекта. Для этого мы будем использовать статические файлы непосредственно в нашем проекте NestJS. Для простоты работы с клиенсткой частью мы также будем использовать Vue.js .
Сначала нам нужно сообщить нашему приложению NestJS, что мы хотим использовать статические ресурсы, добавив несколько строк кода в наш файл main.js
.
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { NestExpressApplication } from '@nestjs/platform-express'; import { join } from 'path'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useStaticAssets(join(__dirname, '..', 'static')); await app.listen(3000); } bootstrap();
Здесь мы говорим express, что каталог static
будет использоваться для хранения наших статических ресурсов, что мы можем сделать только путем импорта и использования NestExpressApplication.
Затем мы создадим код JavaScript на стороне клиента в нашем файле main.js
, который мы позже будем использовать в макете.
const app = new Vue({ el: '#app', data: { title: 'Nestjs Websockets Chat', name: '', text: '', messages: [], socket: null }, methods: { sendMessage() { if(this.validateInput()) { const message = { name: this.name, text: this.text } this.socket.emit('msgToServer', message) this.text = '' } }, receivedMessage(message) { this.messages.push(message) }, validateInput() { return this.name.length > 0 && this.text.length > 0 } }, created() { this.socket = io('http://localhost:3000') this.socket.on('msgToClient', (message) => { this.receivedMessage(message) }) } })
Здесь мы создаем новый экземпляр Vue.js и создаем некоторые базовые переменные, которые позже будем использовать в нашем макете.
Далее вы можете увидеть функцию created()
, которая будет выполняться при создании внешнего интерфейса. В этом методе мы создаем экземпляр нашей переменной socket с помощью библиотеки socket.io, которую мы позже импортируем в наш интерфейс. Мы также добавляем слушатель событий в наш сокет, который прослушивает событие msgToClient
, которое мы создали ранее на нашем сервере.
Затем у нас есть функция sendMessage()
, которая получает входные данные из нашего макета и отправляет их на наш сервер, используя то же событие, если входные данные верны.
Вот и все для нашей клиентской части - теперь нам нужно только создать макет для нашего приложения.
Макет приложения
Чтобы создать макет, нам просто нужно добавить несколько простых HTML и CSS в наше приложение.
Здесь мы импортируем зависимости socket.io и vue.js с помощью тегов script, а затем создаем простой макет с двумя полями ввода, областью отображения сообщений и кнопкой для отправки сообщений.
Вы также можете заметить, что мы импортируем наш файл main.js, который мы использовали выше, и пользовательскую таблицу стилей, которую мы создадим сейчас.
#messages{ height:300px; overflow-y: scroll; } #app { margin-top: 2rem; }
Тестирование приложения
Теперь, когда мы закончили наше приложение чата, пришло время проверить его, открыв его в двух или более вкладках браузера и пообщаясь друг с другом. Для этого давайте запустим наше приложение и откроем его в нашем браузере.
npm run start
После запуска мы должны увидеть наш макет на http://localhost: 3000.
Затем вам просто нужно ввести имя и сообщение и нажать кнопку отправить. После отправки сообщение должно появиться во втором окне и должно выглядеть примерно так.
Это оно! Мы завершили наше чат-приложение на NestJS, используя Websockets. Полный код проекта также можно найти в Github.
Заключение
Вы сделали это! Я надеюсь, что эта статья помогла вам понять основы Websockets и как их использовать в NestJS.