javascript

Проектируем профессиональный фронт для мессенджера

  • вторник, 3 марта 2026 г. в 00:00:04
https://habr.com/ru/articles/1005348/

Ранее я писал статью Пишем высокопроизводительный вьюпорт для мессенджера / Хабр В которой демонстрировалось создание простого вьюпорта для мессенджера и он не был основан на кроссплатформенном решении.

Пример будущей реализации фронта для мессенджера
Пример будущей реализации фронта для мессенджера

Выбор технологий

Перед тем как писать наш будущий мессенджер нужно определиться с технологией на которой будем его разрабатывать. Явными фаворитами среди инструментов web разработки для SPA являются Angular и React. Я не буду акцентировать преимущества каждого из этих инструментов, а остановлюсь сразу на Angular, т.к. ранее проводил ресёрч по неклассическим виртуализированным спискам и выявил, что для данной задачи он справится эффективнее, чем React.

Решение для построения неклассических виртуализированных списков на Angular ng-virtual-list и на React rcx-virtual-list (не реализовано до кроссплатформенного состояния, т.к. Angular лучше справляется с подобной задачей).

Технические требования

  1. Сделаем вьюпорт групп открывающийся из дока.

  2. Вьюпорт сообщений с разделением по дате создания.

  3. Флоу редактирования и удаления сообщений.

  4. Блок создания сообщений.

  5. Поиск сообщений по подстроке.

  6. Уникальный дизайн с темизацией.

  7. Кроссбраузерное и кроссплатформенное решение.

Разработка решения

Создаем новый проект Angular, в данном примере будем использовать 20.x версию. Добавляем пакет ng-virtual-list и настраиваем по описанию.

Сразу предоставлю исходный код проекта ng-virtual-list-chat-demo. Далее я буду останавливаться на ключевых моментах в коде репозитория, чтобы объяснить подробнее.

Проект функционирует полностью на моках, транспорт имплементируется с помощью mock-служб.

Службы

  • Служба для работы с группами сообщений groups-mock.service.ts. Реализует методы getGroups, createGroup, updateGroup и deleteGroup.

  • Служба для переключения чатов message.service.ts

  • Mock-служба для работы с сообщениями messages-mock.service.ts. Служба предоставляет функционал getMessages, createMessage, updateMessage, patchMessages и deleteMessage по указанному chatId.

  • Служба для работы с уведомлениями о создании новых сообщений (имитирует работу ws) messages-notification-mock.service.ts Реализует 2 Observable $typing (сигнализирует о наборе сообщения пользователем с заданным userId) и $messages (Сигнализирует о добавлении сообщения, в качестве значения передаёт версию изменений).

  • Служба темизации theme.service.ts

  • Служба локализации localization.service.ts. Важно отметить, что интерфейс "умеет" адаптироваться под языки с написанием right-to-left, например такие как иврит. За это отвечает директива locale-sensitive.directive.ts.

Основные компоненты

  • Основная страница мессенджера chat.component.ts

  • Компонент групп чатов groups.component.ts

  • Компонент вьюпорта сообщений messages.component.ts. Реализация коллекций основана на ProxyCollection. При получении "сырых" данных они переводятся в ProxyCollection<IMessageItemData>, которая при изменении формирует новый список элементов для <ng-virtual-list>

    Важно отметить, что ng-virtual-list умеет кэшировать сообщения по типу, для чего введены такие типы элементов как typing-indicator, unmailed-separator, group, quote и message, которые рендерятся, как элементы определенного типа.

     <ng-template #itemRenderer let-index="index" let-data="data" let-prevData="prevData" let-nextData="nextData" let-measures="measures" let-config="config" let-reseted="reseted">
            <div staticClick [maxStaticClickDistance]="maxStaticClickDistance" class="message-template" (onStaticClick)="config.select(data.edited ? true : undefined)">
                @if (data?.data) {
                    @switch (data.data.type) {
                        @case ("typing-indicator") {
                            <x-messages-typing-indicator ... />
                        }
                        @case ("unmailed-separator") {
                            <x-message-unmailed-separator ... />
                        }
                        @case ("group") {
                            <x-message-group ... />
                        }
                        @case ("quote") {
                            <x-message-box [messageType]="'quote'"... />
                        }
                        @default {
                            <x-message-box ... />
                        }
                    }
                }
            </div>
        </ng-template>
  • Компонент сообщения message-box.component.ts реализует функционал просмотра, выбора, редактирования и удаления. Компонент использует SVG визуализацию message-substrate.component.ts с различными визуальными эффектами и анимациями.

  • В проекте реализован ряд контролов @shared/components также основанных на SVG рендеринге. Такие как button, button-group, check-box, context-menu, dialog, drawer и базовый substrate.

  • Поиск сообщений по подстроке реализован средствами библиотеки ng-virtual-list, а подсветка подстроки с помощью директивы search-highlight.directive.ts.

  • В проекте реализован свой ResourceManager с политиками загрузки и кэширования изображений.

Дизайн элементов устроен с учетом анимации градиентных заливок.

Решение работает на любом браузере и любой платформе.

Demo: https://chat-demo.eugene-grebennikov.pro/

demo
demo

Demo ng-virtual-list: ng-virtual-list-examples

P.S.: Если понравился проект, ставьте звездочку ⭐ инструменту для работы с виртуализированными списками ng-virtual-list