ПОСТЫ
Клон Duolingo в два вечера с Firebase
By slnt_opp
Как-то давно(около четырех лет назад) у меня появилась идея, сделать базу данных и аутентификационный шлюз тире сервис работающий только как API, дабы делать динамические веб приложения без бэкэнда. Два года перед эту идею купил Google не у меня. Об этом как-нибудь в другой раз, а сейчас разбираемся что такое Firebase, как им пользоваться и нужен ли он.
Немного об архитектуре веб-приложений
Давай попробуем взглянуть на веб немного сверху. Если сделать так, то мы имеем три основные стороны:
- Интерфейс a.k.a. front-end
- Логика a.k.a. back-end
- База данных a.k.a.
Mong
Это исходит из того, что нам нужно решить довольно определенный круг проблем.
- Понять проблему пользователя
- Решить проблему пользователя
- Объяснить пользователю, что проблема решена
(Порядок дан обратно порядку сторон выше)
И так или иначе эти составные части будут в любом веб(и не только) приложении.
Однако по мере развития браузеров и JS itself, интерфейсы ушли довольно далеко, а большинство публичных приложений не имеют какой-то уникальной логики, которую непременно нужно скрыть. Однако бэкэнд всегда был связующим с БДю
Тааак…
Как же так - без сервера?
Ну сервер все же есть, просто либо серверов меньше, либо сервер меньше, либо, что чаще, это вообще не твоя головная боль. Все началось не знаю когда, но начало быть популярным вместе с распространением графовых баз данных, таких как DGraph(на котором Firebase вероятно и работает). Что ж такое эти графовые БД? Можно очень много рассказывать про их математику и тд, но что важно для нас здесь, это безопасность и принципиальная невозможность утечек данных к тем, кому не положено.
Achtung! Это мое понимание и наблюдения, я не бдолог и на метематик Такая база данных это многомерный граф, где при движении по вертикали мы переходим от пользователя к пользователю, а при ортогональном движении мы читаем данные. И так уж вышло, что некоторые связи - направленные, это значит что если мы имеем следующий граф(Буквы - пользователи, цифры - данные):
R # root
/ \
0 - D A - 0 - 1 - 2
| |
0 - E - B - 0
| |
F C - 0 - 1
|
.................
Так вот если ты используешь данные доступа для пользователя B, ты сможешь получить доступ к C и данным C, потому что С ниже, к E потому что там добавлена связь и к F потому что F ниже E и так далее, и к данным E и F разумеется. Но к А - никак. Таким образом схема для B будет:
0 - E - B - 0
| |
F C - 0 - 1
|
.................
Так же, такие БД имеют системы правил определяемых пользователем. Что важного в них? Два момента:
- По умолчанию все запрещено, правила разрешают все классы и объекты по отдельности
- Правила имеют понятие об анонимности и авторизованности.
- Можно сравнивать данные из запроса и документа
Таким образом можно опубликовать какую-то часть данных, и что еще важнее - отправить запрос в БД без авторизации, и он завершиться успешно с ответом Permission denied
. Потому что большинство правил начинаются с if request.auth
, кроме одного - создания пользователя.
Да, создание аккаунта в БД в нашем и похожих случаях будет доступно абсолютно всем с единственным ограничением - нужно использовать один их доступных драйверов авторизации. Таким образом БД живет сама по себе, и живет прекрасно и безопасно.
Что из этого следует? Можно описать всю логику на фронтенде и используя GraphQL сделать полноценное приложение.
Firebase
Firebase это логичное следствие такого подхода. Firebase состоит из 7 сервисов, погнали по порядку.
Authentication
Этот сервис собственно и решает проблему создания пользователей, после настройки пользователь не сможет ни зарегистрироваться, ни получить ни записать никаких данных не предоставив токен от одного из провайдеров авторизации. Также, Firebase предоставляет Firebase UI, который может умеет что-то еще, однако главное это контейнер с кнопками разных провайдеров. А их тут много, это: Google, Apple, Facebook, Twitter, GitHub, Microsoft, Yahoo, через Телефон и классические мыло/пароль.
Cloud Firestore и Realtime Database
Это два сервиса хранения данных. Оба NoSQL, оба работают как DGraph. Доступ через апи и/или библиотеки. Разница между ними в цене и функциональности. Однако в чем конкретно разобраться довольно тяжело. Спасибо Google за опросник-помощник который объясняет и подсказывает какую лучше использовать для твоего проекта. Я остановился на Cloud Firestore. Потмоу что мне нужен был чистый NoSQL. Realtime умеет в хуки на обновления и хранит чистый JSON, поэтому часто используется в мессенджерах и играх.
Storage
Тут нечего рассказывать - это CDN. Клади, забирай, быстро во всем мире.
Hosting
Хостинг работает по принципу Github Pages - “статически” сгенерированные приложения кладуться в CDN и раздаются из-под какого-нибудь Nginx в 3-5 точках мира и вуа-ля. Соответственно туда можно положить приложение разработанное на любом современном фреймворке, i.e. Vue, Angular, React и т.д.
Functions
Если тебе все-таки нужно спрятать какую-то логику, то можно использовать функции. По сути пишешь кусочек кода на JS, и он и другие кусочки собираются в сервер и крутятся в контейнерах. Функции вызываются обычными хттп запросами.
Machine Learning
Тут все очевидно, Google просто предоствляет всю мощь их ML Kit в твои приложения, а тебе не нужно нагружать клиента Tensorflow.js. Также ML дает некоторые готовые модели, типа сканирования штрихкодов, переводчика и умных ответов. К тому же ты можешь использовать все накопленные в базе данных знания о пользователях для построения и обучения моделей напрямую. Ну разве это не прекрасно. Двойная продажа данных по цене одной.
Перейдем к практике.
Пример на копии Duolingo
Если кто не знает
Duolingo это один из множества, но вероятно самый популярный/распиареный, сервисов самообучения языкам. Пользователь выбирает свой язык, язык который хочет учить и в игровом формате проходит уроки возрастающей сложности.
Насколько это эфективно не очень легко сказать, но мне помогало осваивать базу и фразы путешевственика. Пиком был мой разговор из суммарно пяти реплик и шуткой на испанском, что как я считаю абсолютный максимум, который можно требовать от бесплатного приложения. Самый главный минус - приложение не дает абсолютно никакой грамматики, из-за чего очень сложно, а то и невозможно, брать это за базу и расширяться.
Задания делятся примерно на 5 типов:
- Выбрать слово по картинкам
- Перевести предложение - написав его
- Перевести предложение - составив его из данных слов
- Заполнить пропуск одним из предложенных вариантов
- Прочитать вслух(опционально)
- Может быть еще что-то
Задания 2 и 3 работают в обе стороны(то есть с родного на иностранный и с иностранного на родной языки).
Что было нужно
Супруга попросила утилиту, чтобы подготовиться к письму(часть экзамена) на немецком. Когда-то я уже делал ей такое для подготовки к химии - для запоминания кислотных остатков и составления соединений с ними.
Что я хотел
Сделать что-то похожее на Duolingo по UX не увеличивая нагрузки на мой не самый большой сервер bzw. попробовать и сделать это на Firebase.
Что я сделал
В целом то, что я хотел, но так как сроки были сжатыми(по трекеру я потратил 7 часов, т.е. как и на самом деле - два вечера). Я сразу выбрал и сделал только один возможный вариант заданий - 2 (и хотел имплементировать подобие 3 в виде подсказки, однако не успел).
Никакого разделения на уроки у меня конечно нет, потому что я не педагог и не могу так далеко подумать, но в логике это предусмотрено :)
Таким образом жизненный цикл сессии такой:
Для пользователя:
- Залогиниться ->
- Выбрать настройки урока ->
- Ответить на вопросы ->
- Получить результаты
Технически:
- Залогинить пользователя через Google, т.е. получить его UID ->
- Получить задания по выбранным настройкам: количество, тип, уровень сложности ->
- Сравнить данный ответ с правильным ответом сложнее чем просто
===
-> - Записать результаты в коллекцию статистики ( -> ) экстра-пункт показать среднюю оценку и прогресс в главное менюхе
Потыкать
В общем это работает, и даже понемногу развивается, я потратил в сумме еще 4 часа на фикс тех багов которые были и вместе с этим добавить что-то еще.
Так что можешь даже сам попробовать, но берегись, пока не ответишь на всё - урок не закончится.
Прилага тут по сыыыыыылке
Achtung! Приложение не оптимизировано для маленьких экранов, так что только на фуллскрин
Скрины(некоторые уже устаревшие, сорь):
Что я еще не сказал
Мне кажется, что я сказал достаточно, чтобы было понятно, что за зверь такой Firebase и ответил на главные поставленные вопросы. Но эту секцию я уже написал, так что я назову еще два минуса.
У Firebase нет удобного интерфейса для работы с данными в БД.
А с чего он должен быть? А с того что у всех есть и это бывает очень нужно. Например, в стандартном интерфейсе документы загружаются по одному и нельзя прочитать два одновременно. Почему? Потому что это все равно запросы, так можно очень быстро превысить все свои лимиты просто загрузив страницу. Но все же можно было бы что-нибудь и придумать, потому что в таких кейсах как мой, периодически нужно банально исправлять ошибки в заданиях. Да, я, не будь дураком, написал свой интерфейс, но хотелось бы иметь что-то вроде MongoDB Compass.
Firebase.js и Firebase UI
Как я уже писал это такая библиотечка, который даешь блок на странице и она вставляет туда кнопки для например авторизации, а под firebase.js я подразумеваю библиотеку для взаимодействия с Firebase. С ними много проблем. Но самая главная это - они жутко устаревшие относительно фреймворков и в целов современного JS. Callbackhell это наименьше что тебя ждет.
Процедуры
Их отсутствие скорее. Очень актуальный для моего кейса вопрос, это процедуры в БД. Мое приложение начинается с получения определенного количества случайных заданий, но мне приходится сначала получить все, что может быть очень больно для моего бесплатного плана.
Кстати тут и плюс
Как это часто бывает, это дикая халява. Есть бесплатный план - Spark, по которому есть бесплатные квоты в каждом сервисе Firebase. Для Firestore это например 50к чтений и 20к записываний. Ровно за 0$.
Резюме
Это годный сервис, как показала практика можно быстро и бесплатно поднять и захостить прототип, а дальше легко его заскейлить. Предлагаемых возможностей достаточно, чтобы продать свое приложение под всеми трендовыми ярлыками типа DataScience и ML(не хватает разве что Blockchain, хотя это уже не модно, но если хочется - Azure).
Спасибо за прочтение и Пользусес!