Files
min-chat/README.md
T
Комаров Данил Анатольевич 6 83ef0d5ab3 init
2026-05-29 04:59:58 +03:00

6.2 KiB

Чат с общей комнатой

Веб-приложение чата с одной общей комнатой на WebSocket. Поддерживает текстовые сообщения, отправку файлов и отображение изображений.

Сервер: Node.js + ws
Клиент: React + Vite
Прокси: nginx (production-сборка)


Быстрый запуск (разработка)

Сервер

cd server
npm install
npm start

Запускает WebSocket сервер на ws://localhost:8080.

Клиент

cd client
npm install
npx vite

Запускает dev-сервер на http://localhost:3000.
В режиме разработки клиент подключается напрямую к ws://localhost:8080.

Пользователи по умолчанию

Логин Пароль
alice 123
bob 456

Production (Docker)

Сборка образа

docker build -t chat-app .

Запуск контейнера

docker run -d -p 80:80 chat-app

Открой http://localhost.

Как это работает

  • nginx на порту 80 раздаёт статику React и проксирует WebSocket
  • Путь / → статические файлы клиента (index.html, JS, CSS)
  • Путь /ws → прокси на Node.js WebSocket сервер (порт 8080 внутри контейнера)
  • nginx поддерживает Upgrade до WebSocket, таймаут соединения — 24 часа
  • Максимальный размер загружаемых файлов через nginx — 50 МБ
  • После остановки Node.js контейнер завершается (через wait)

Переменные окружения

Сервер

Переменная По умолчанию Описание
PORT 8080 Порт WebSocket сервера
MAX_FILE_SIZE 10485760 (10 МБ) Максимальный размер файла в байтах
USERS_FILE users.json Путь к файлу с пользователями

Пример:

$env:PORT=9090; $env:MAX_FILE_SIZE=2097152; node server.js

Клиент

Переменная По умолчанию (dev) По умолчанию (production) Описание
VITE_WS_URL ws://localhost:8080 /ws URL WebSocket сервера

Настройки хранятся в файлах:

  • client/.env.development — для npx vite (dev-режим)
  • client/.env — для vite build (production-сборка)

Протокол обмена

Аутентификация

Клиент → Сервер:

{ "type": "auth", "login": "alice", "password": "123" }

Сервер → Клиент:

{ "type": "auth_result", "success": true }
{ "type": "auth_result", "success": false, "reason": "Invalid login or password" }

Текстовое сообщение

Клиент → Сервер:

{ "type": "text", "text": "Привет!" }

Сервер → Все:

{ "type": "text", "from": "alice", "timestamp": 1717000000000, "text": "Привет!" }

Файл / изображение

Клиент → Сервер:

{
  "type": "file",
  "filename": "cat.png",
  "mime": "image/png",
  "data": "<base64>"
}

Сервер → Все (такая же структура, добавлены from и timestamp):

{
  "type": "file",
  "from": "alice",
  "timestamp": 1717000000000,
  "filename": "cat.png",
  "mime": "image/png",
  "data": "<base64>"
}

Системные сообщения

Сервер → Все:

{ "type": "system", "text": "alice joined the chat" }

Функциональность

  • Текстовые сообщения — отображаются с логином отправителя и временем
  • Файлы — любые типы, до 10 МБ (настраивается). Файлы передаются через base64 в JSON
  • Изображения — автоматически определяются по MIME-типу (image/*), рендерятся как <img>, клик открывает в новой вкладке
  • Не-изображения — отображаются как ссылка для скачивания с именем файла
  • Уведомления на неактивной вкладке — звуковой сигнал (Web Audio API) и красная точка на favicon
  • Системные сообщения — подключение / отключение участников
  • Скролл — автоматический, кастомный тонкий скроллбар в теме приложения

Структура проекта

chat/
├── server/
│   ├── server.js          # WebSocket сервер
│   ├── users.json         # Хардкоженые логины/пароли
│   └── package.json
├── client/
│   ├── src/
│   │   ├── App.jsx        # Корневой компонент
│   │   ├── App.css
│   │   ├── main.jsx       # Точка входа
│   │   └── components/
│   │       ├── Login.jsx / .css
│   │       ├── Chat.jsx / .css
│   │       ├── MessageList.jsx
│   │       ├── Message.jsx / .css
│   │       └── MessageInput.jsx / .css
│   ├── .env               # Production настройки
│   ├── .env.development   # Dev настройки
│   ├── index.html
│   ├── vite.config.js
│   └── package.json
├── Dockerfile             # Многостадийная сборка
├── docker-entrypoint.sh   # Точка входа контейнера
├── nginx.conf             # Конфигурация nginx
└── README.md