Мелочь в навигации — архитектура на бэке

Туннелировать админ-панель: когда мелочь оказывается архитектурой
Проект borisovai-admin — это управленческая панель для социального паблишера. И вот однажды возникла потребность: нужна видимость в туннели FRP (Fast Reverse Proxy). Казалось — простая фича. Добавить ссылку в навигацию, создать эндпоинты на бэке, вывести данные на фронте. Четыре-пять дней работы, максимум.
Началось всё с мелочи: требовалось добавить пункт “Туннели” в навигацию. Но навигация была одна, а HTML-файлов четыре — index.html, tokens.html, projects.html, dns.html. И здесь скрывалась первая ловушка: одна опечатка, одна невнимательность при копировании — и пользователь запутается, кликнув на несуществующую ссылку. Пришлось синхронизировать все четыре файла, убедиться, что ссылки находятся на одинаковых позициях в строках 195–238. Мелочь, которую легко упустить при спешке.
Но мелочь эта потащила за собой целую архитектуру. На бэке понадобилось добавить две вспомогательные функции в server.js: readFrpsConfig — для чтения конфигурации FRP-сервера, и frpsDashboardRequest — для безопасного запроса к dashboard FRP. Это не просто HTTP-вызовы: это минимальная абстракция, которая облегчит тестирование и повторное использование. Затем пришлось вывести четыре GET-эндпоинта: статус сервера, список активных туннелей с метаинформацией, текущую конфигурацию в JSON и даже генератор frpc.toml для скачивания клиентского конфига в один клик.
И вот неожиданно выяснилось — сам FRP-сервер ещё нужно установить и запустить. Обновил install-all.sh, добавил FRP как опциональный компонент: не все хотят туннели, но кто выбрал — получит полный стек. На фронте создал новую страницу tunnels.html с тремя блоками: карточка статуса (живой ли FRP), список туннелей с автообновлением каждые 10 секунд (классический полинг, проще WebSocket’а для этого масштаба) и генератор конфига для клиента.
Интересный факт: полинг через setInterval кажется древним подходом, но именно он спасает от overengineering’а. WebSocket требует поддержки на обеих сторонах, fallback’и на старых браузерах, управление жизненным циклом соединения. Для обновления статуса раз в 10 секунд это overkill. Главное — не забыть очистить интервал при размонтировании компонента, иначе получишь утечку памяти и браузер начнёт отваливаться.
Главный урок: даже в мелких фичах скрывается целая архитектура. Одна ссылка в навигации потребовала синхронизации четырёх файлов, пять эндпоинтов на бэке, новую страницу на фронте, обновление скрипта установки. Это не scope creep — это discovery. Лучше потратить час на планирование полной цепочки, чем потом переделывать интеграцию, когда уже половина team работает на основе твоей “быстрой фички”.
😄 FRP — это когда твой сервер вдруг получает способность ходить в гости через NAT, как путник с волшебным клаком из мультика.
Метаданные
- Session ID:
- grouped_C--projects-bot-social-publisher_20260208_1523
- Branch:
- main
- Dev Joke
- Почему Vite считает себя лучше всех? Потому что Stack Overflow так сказал
Часть потока:
Разработка: bot-social-publisher