Подавляющее большинство вещей, которые должны делать фронтенд разработчики, можно сделать не зная ничего о бэкенде кроме API.
Однако если вы достаточно долго работаете с разного рода задачами, вероятней всего вы столкнетесь с чем-то, что требует некоторых знаний в области бэкенда.
Ниже представлен краткий список того, о чем должен знать разработчик интерфейсов.
Частота запросов
Бэкенд имеет ограниченные ресурсы, он может обрабатывать запросы лишь с определенной частотой. В общем случае вы не должны об этом думать — фронтенд должен делать все что необходимо для предоставления качественного пользовательского опыта, бэкенд же в свою очередь можно оптимизировать и масштабировать. Тем не менее сетевые запросы к бэкенду не бесплатны и имеют разную цену (в терминологии используемых ресурсов)
Как мы можем измерить насколько запрос затратный?
Одно из практических правил говорит нам о том запись всегда дороже чтения, поэтому чем больше данных записывается — тем дороже становятся запросы.
Давайте рассмотрим пример того когда это становится критичным: предположим мы разрабатываем google docs.
Мы хотим чтобы пользователь не потерял написанное если он вдруг покинет приложение, поэтому мы чаще сохраняем данные. Можем ли мы сохранять каждый новый символ или его удаление?
Ваш бэкенд вероятнее всего будет не в состоянии обработать все эти запросы, или же стоимость инфраструктуры будет непозволительно высокой. Сделав задержку и сохраняя данные только после того как пользователь перестал печатать, можно достигнуть 99% от необходимого результата без огромных затрат на оставшийся 1%.
Следующий пример, давайте предположим что вы хотите опрашивать бэкенд об изменениях, чтобы всегда иметь самую свежую версию .doc файла. Как часто необходимо делать запросы? Чтение намного дешевле записи, поэтому вы можете делать сравнительно больше таких запросов, но они все еще имеют лимит.
Данный лимит зависит от множества факторов, таких как: максимальное количество активных клиентов в промежуток времени, инфраструктура и бюджет. Если вы думаете что ваш функционал может приблизиться к такому лимиту, стоит поговорить с командой бэкендеров, иначе есть риск задодосить сайт вашей компании.
Время простоя (downtime)
Вы должны ожидать и быть готовыми к тому что каждый запрос может в какой-то момент упасть для некоторых пользователей. Это неизбежно, бэкенд может в какой-то момент падать целиком либо же на каком то конкретном эндпоинте пока все остальные продолжают работать.
Вы должны различать какие запросы в вашем приложении являются критичными, когда нужно показать полноэкранную ошибку с сообщением "Попробуйте позже", а когда ошибку можно обработать с помощью постепенной деградации (например серая кнопка для какой либо функции, с сообщением при наведении о том, что функция на текущий момент недоступна)
Если ваш бэкэнд разделен на несколько микросервисов, вероятность сбоя подмножества эндпойнтов выше. В другом случае, eсли ваш бэкэнд представляет собой только один сервер, один сбой может разрушить все эндпойнты.
В любом случае, хороший фронтэнд должен всегда отлавливать ошибки в запросах с помощью try catch и иметь заготовленные ошибки для пользователя. В javascript нет встроенной функции(recovery panic), которая позволяет продолжить выполнение кода после ошибки, поэтому при её возникновении ваше приложение упадет.
HTTP
Бэкэнд и фронтенд должны использовать соответствующие HTTP статусы (в определенной степени). Надеюсь, ваш бэкэнд не воспринимает каждую ошибку как 400.
Интерфейс должен знать каждый статус, который бэкэнд планирует вернуть.
Не парсите сообщения об ошибках, чтобы определить, то что авторизация не удалась, код ошибки 401 подходит для этого больше.
Не повторяйте тот же самый запрос, если вы получили 400-ый код потому что он, вероятно, не будет работать снова. А к примеру 500-ый код может означать, что сервер просто перезагружается и повторная попытка будет успешной.
Другие свойства HTTP запросов которые желательно знать:
- HTTP запросы могут быть закрыты сервером если они занимаются слишком много времени прежде чем завершатся. Если вы думаете что некоторая задача займет больше времени чем лимит на запрос (как правило около 20 секунд), вам следует выбрать вместо единичного запрос-ответа, запрос с последующим опросом результата. Или воспользоваться другими механизмами, например веб-сокетами.
- Если вы отправляете большое количество данных на сервер(например видео), вы должны использовать составной HTTP запрос(multipart/form-data), который делит данные на части перед отправкой.
- Иногда неожиданно возникает то, что существует ограничение размера URL. Некоторые веб-интерфейсы передают данные обратно на сервер с query параметрами, но если они длиннее 2048 символов, вам придется изменить такой способ на передачу параметров в теле HTTP запроса.
Делегирование бизнес логики
Если какая-то бизнес логика вашего функционала может быть реализована и на бэкенде и на фронтенде, где лучше её реализовать?
В основном лучше делать это на бекенде. Причины:
- Бэкенд может быть изменен намного быстрее — один деплой на все сервера и обновленная логика будет доступна. Фронтенд же, на руках у пользователей и деплой не будет означать что старая логика в которой возможно присутствуют ошибки, не будет запущена на продакшене.
- Если бизнес логика требует вычислительной мощности, её тяжело протестировать на различном спектре устройств с которых пользователи могут заходить на ваше приложение. Если вы заходите на него с топового macbook, то не сможете представить насколько медленными будут вычисления на chromebook за 100 долларов.
- Более безопасно блокировать бизнес логику на бэкенде. Предположим у вас есть функционал только для pro пользователей. Если ограничение будет сделано на фронтенде, то кто-либо потенциально может провести реверс-инжиниринг и получить доступ к функционалу.
Кросс-доменные запросы
В качестве протокола безопасности, если запрос к бэкэнду поступает из другого домена, он будет отклонен из-за того что он является кросс-доменным запросом. Такое поведение обусловлено политикой одного источника(Same-Origin Policy). Данная политика запутывает людей в процессе разработки, поскольку порты тоже считаются частью домена.
Зачастую используется сервер npm/yarn для фронтенда и бэкенда на другом порту, что делает каждый запрос кросс-доменным.
Решения:
- Указание одного домена в
hosts
файле и разграничивание фронтенда и бекенда с помощью nginx*. - Включить кроcс-доменные запросы на сервере в зависимости от переменной среды, если production то false, если development то true.
- Включить домен с которого ведется разработка в белый список исключений.
Межсайтовая подделка запросов(CSRF) — так называется атака, которая делает несанкционированный запрос от пользователя инициированный с другого сайта.
Например: вы нажимаете кнопку на каком-либо сайте и он выполняет javascript код, который попытается выполнить запрос на сайт вашего банка.(подробнее)
Чтобы это предотвратить, сервер выдает одноразовый CSRF токен для каждой сессии, так что попытка будет неудачной из-за отсутствия токена. Добавляйте его к заголовкам авторизованных запросов.
Очистка кэша
Каждый запрос проходит через несколько кэшей на пути к бэкэнду. Если вы посещаете сайт в первый раз, подождите, пока он загрузится, а затем перезагрузите страницу.
Веб-приложение загружается быстрее чем в первый раз, поскольку браузер кэширует ресурсы, такие как favouritewebsite.com/static/script.js
.
Что если вы хотите внести изменения в script.js
? Вы меняете имя файла. Допустим, вы меняете script.js
на script.js?v=2
, на который ссылается index.html
.
Закэшированный script.js
становится неактуальным, поскольку к нему никогда не будет другого запроса (если сам index.html не будет закэширован! Запрос к index.html
должен быть инвалидирован на бэкэнде).
Современные конвейерные сборки включают в себя очистку кэша для каждой сборки, поэтому большинство javascript файлов выглядят как script.4e885f13.js
. Обычно это применяется только к css стилям и скриптам, но вы также можете применить их к изображениям и другим ресурсам.
Однако подобные ресурсы меняются очень редко, и по соображениям производительности стоит их исключить из автоматического кэширования и просто обновлять вручную при необходимости.
*Примечание переводчика:
В оригинале было так:
Map your server domains to some hostname in your dev environment's host config.
Я мог неправильно понять то что хотел сказать автор, поэтому добавляю сноску.
Автор: Илья Бельский