Создание 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.