Когда пришла эпоха коротких видео в TikTok и YouTube, я, как и многие, стал проводить там слишком много времени, порой обнаруживая себя засыпающим в 5 утра под листание бесконечной ленты. Тогда я решил отучить себя от этой привычки. Пробовал разные ограничения, но, в конечном итоге, просто забивал на них.
Примерно в это же время я увлёкся поэзией. Мне было около 30, когда я научился получать удовольствие от чтения стихов. И я подумал — а почему бы не заменить короткие видео на стихи. Тогда каждый раз, когда я хотел позалипать в тикток, я вместо этого открывал случайное стихотворение какого-нибудь автора, читал несколько стишков, закрывал, и возвращался к делам.
Если подумать, то стихи — это тиктоки 20 (19, 18 ...) века. Но красивое стихотворение вызывает более сильные чувства, чем любое короткое видео, и, что самое важное, к нему хочется возвращаться, перечитывать, и вновь получать удовольствие от красоты написанного. А особенно понравившиеся стихи, учить наизусть.
Так у меня появилась идея полушутя-полусерьезно сделать приложение с тикток механикой, но вместо видео — стихи.
Nocode VS Code
Я ничего не знал о фронтенд разработке и решил попробовать nocode-инструменты.
Механика моего приложения элементарна — бесконечный скроллинг текста, поэтому я думал, что быстро накидаю готовые компоненты и в продакшен. На деле оказалось, что даже такую простую механику готовыми компонентами не реализовать.
Получается, что пропадает смысл этих инструментов. Ведь они изначально создавались чтобы создавать прототипы без дополнительных знаний, а сейчас усложнились настолько, что сами требуют изучения.
Зачем тогда вообще этот уровень абстракции?
Если уж и изучать, то полноценный инструмент, который дает свободу творчества.
Всё-таки code
Так я начал смотреть в сторону React Native, но нашел еще более простое решение — PWA (progressive web app). Это технология, которая позволяет сделать приложение из обычного сайта. Сейчас многие банки, приложения которых недоступны в AppStore, используют эту технологию. PWA — это когда можно на смартфон «установить» сайт. На домашнем экране появится иконка приложения, если его запустить, то откроется сайт, но без интерфейса браузера. Как будто нативное приложение.
Конечно, многие функции в PWA-приложениях ограничены, ведь это просто сайт, но у меня простое веб-приложение, и PWA для него подходит идеально.
Backend
Бэкенд я сделал на DjangoRestFramework, потому что это быстро и удобно. Мне нужен простой API, в который я буду обращаться из JS-фронтенда. В качестве базы данных использую PostgreSQL.
Frontend
Для фронтенда я выбрал ReactJS, т.к. это самый распространённый фреймворк. Я никогда не писал на JS, поэтому учился этому с нуля, и то, что у ReactJS большое комьюнити, мне очень помогло в изучении. Если тоже начинаете изучение React, могу посоветовать вот этот бесплатный курс.
Чтобы из сайта сделать PWA-приложение, он должен соответствовать нескольким требованиям:
-
обязательный HTTPS
-
manifest с описанием
-
наличие service worker-а
Service worker — это js-код, который выступает посредником между приложением и интернетом, т.е. все запросы в API, которые будет отправлять приложение, будут отправляться через этот воркер.
Он может кэшировать их, обрабатывать ситуации плохой связи или её отсутствия, чтобы пользователь не увидел ошибку браузера, а увидел вашу собственную “заглушку”. Вообще, тема service worker-ов очень обширна, на Хабре можно найти подробные статьи об этом. Я же сгенерировал свой воркер в сервисе pwabuilder.com
После добавления воркера, выяснилось, что самая популярная JS-библиотека для HTTP-запросов axios, не умеет работать через него. Пришлось заменить axios на ky.
Проблема превью в мессенджерах
Мое приложение — это SPA на ReactJS, поэтому по GET запросу любой страницы веб-сервер возвращает пустой HTML, а дальше отображением занимается JS-код внутри браузера, изменяя DOM-дерево "на лету". И если, например, делиться ссылкой в Телеграме на какую-либо страницу сайта, то на превью будет якобы пустая страница, хотя внутри браузера у пользователя есть контент, но превью-генераторы не умеют рендерить JS, они просто посылают GET запрос, и на основе полученного пустого HTML рисуют превьюшку в чате. Та же ситуация и с поисковыми ботами Google и Яндекс.
Для решения этой проблемы, я нашел вот такой контейнер. Внутри headless chrome, который любезно срендерит JS за поискового бота или генератора превьюшек в мессенджерах. На входящем nginx-е я строю маршрутизацию запроса на основе заголовка User-Agent, и, если это поисковой бот или превью-генетатор, то проксирую этот запрос в пререндер-контейнер, который вернет HTML-страницу с отрисованным контентом.
Вот только я еще не решил — это изящное решение архитектурной проблемы, или ужасный костыль?
Перед публикацией статьи, увидел, что у поискового бота Яндекса появилась бета-версия "Рендеринга страниц JavaScript"
Deploy
Когда пришла пора деплоить приложение в прод, я купил домен stihtok.ru, и подыскал VPS-хостинг. Мне понравился TimeWeb Сloud, я взял самую дешевую виртуалку и сделал ansible-плейбуки для установки необходимого окружения на сервере.
Разумеется, все работает в докере. Для автоматизации сборки контейнеров я использую GitHub Actions с собственным раннером на сервере. По коммиту в ветку происходит сборка и деплой на тестовый стенд, а отведение тэга деплоит его на прод.
Вот такое получилось приложение:
Автор: Роман Орлов