Single store
Похоже один из самых распространённых типов архитектуры на front-end для enterprise проектов характерный и подходящий для многих enterprise проектов. Схематично эту архитектуру можно изобразить следующим образом (Рис. 1):

Рис.1 Single store front-end архитектура
Стрелки обозначают возможность общения разных слоёв, иногда через дополнительные механизмы. Например, стрелка соединяющая хранилище из data layer и back-end может обозначать общение через дополнительный сервис или хук. Идея очень проста. В простейшем случае вы поставляете на клиент одним большим куском все что нужно (кроме самих данных) для отрисовки не только текущей страницы, но и все что нужно для загрузки всех страниц на которые можно перейти с текущей страницы. В самом простом случае — вообще для всех страниц в приложении. Это делает приложение максимально интерактивным и отзывчивым для пользователя. Пользователю теперь не нужно при переходе между страницами получать новые файлы по сети, достаточно запросить данные с API и отрисовать их.
Первый вопрос который может возникнуть с ходу — если мы хотим добиться максимальной интерактивности, то почему бы не подгружать заодно и сразу все данные и таким образом добиться по-настоящему максимально высокой интерактивности. Резонно. Все данные что мы можем подгрузить заранее стоит подгрузить заранее, но есть две причины по которым мы редко сможем это сделать:
- Объём всех данных на сервере для пользователя слишком велик — мы просто не можем загрузить все, так как ограничены размером как минимум конечного бандла!
- Нам нужна некая стратегия обновления этих данных. Один из классических понятных и простых подходов — это обновление данных при попытке их отображения (при переходе на соответствующую страницу). А если мы каждый раз обновляем данные при переходе на страницу, то зачем хранить данные и запрашивать их заранее?
Примечание: на самом деле второй пункт в целом и не является причиной, особенно в последнее время, когда набирает популярность подход offline-first, что является часто и особенностью проектирования Progressive Web Application (PWA). Это связано с отказом от приоритета в актуальности данных и отдаче предпочтений скорости интерактивности. Пример: банковское приложение — к примеру данные о счетах среднего пользователя не обновляются очень часто, поэтому вместо того чтобы отрисовывать ошибку получения данных о счетах мы можем отобразить уже полученные и закешированные данные заранее. В эру мобильных устройств и периодических проблем со связью в городах (тоннели, лифты, подвальные этажи) это делает приложение более дружелюбным для пользователя не смотря на то, что могут быть отображены нерелевантные данные. Помните - архитектура — это всегда вопрос о правильном выборе компромиссов. Итого вопрос о том нужно ли подгружать и кешировать данные заранее сводится к тому что важнее — актуальность данных или скорость интерактивности и стабильность.
Второй вопрос — зачем нам нужен так называемый store (хранилище данных)? Фундаментально store не обязателен, но на практике почти всегда оказывается, что разные страницы приложения могут взаимодействовать между собой и влиять на поведение друг друга. Это взаимодействие выражается в следующих процессах:
- Кеширование данных для увеличения скорости интерактивности.
- Передача данных между страницами для некоторых так называемых пользовательских сценариев, когда пользователь для совершения операции не вводит все необходимые данные в форму и не отправляет данные на сервер с разных форм кусками. А когда при прохождении какого-то сценария (например длинная анкеты) вопросы появляются на странице по одному, данные кешируются на клиенте а потом сразу все одной пачкой отправляются на сервер
- Когда состояние одних страниц влияет на состояние других (настройка тем, вида расположения элементов, статусы (например авторизован пользователь или нет), отображение пользовательских данных (имя пользователя, кабинета), всевозможные настройки работы приложения (включение\отключения функциона льности, модов работы) и пр.)
Если ни один из этих пунктов вам не подошёл, то стоит задуматься о правильности выбора архитектуры в сторону stateless, возможно вам и не нужно создавать приложение и лучшим решением будет создание сайта.
Какие же преимущества нам даёт single store и почему он так популярен? Вот они:
- Очень легко организовать с точки зрения программиста на начальных стадиях, существуют коробочные решения (знаменитый redux), что делает обслуживание такой архитектуры довольно дешёвой.
- Такая архитектура является базовой на сегодня, практически все front-end инженеры осведомлены о ней и поиск сотрудников, способных работать с ней, таким образом упрощается.
- На начальных этапах, пока данных относительно не много (порядок нескольких сотен полей) и их хранение легко обслуживать, осуществлять синхронизацию компонент очень просто (оформив подписку на изменение этих данных), что снижает количество багов в приложении на начальных этапах.
Но есть и значительные минусы, которые в основном начинают проявляться при развитии приложения:
- Это единственное хранилище и поэтому его сл ожно по-настоящему разбить для работы нескольких команд (на мой вкус — для больше чем 10 человек это начнёт становится проблемой). Если количество программистов будет расти, то они начнут мешать друг другу в модификациях этого хранилища, будут оставаться устаревшие не используемые поля и методы доступа к ним, что захломляет проект и со временем может сильно замедлить разработку из-за менее организованного кода.
- Разные компоненты могут использовать похожие по смыслу данные, но все таки разные. Иногда эта «похожесть» приводит к багам. Решение — правильная инкапсуляция данных. Но правильная организация такого глобального хранилища — сложная штука. Проблема в том, что подход с глобальным хранилищем прост в начале, но очень плохо масштабируется после определённого уровня сложности. Интересно, что это часто не очевидно для начинающих front-end инженеров, хотя это является базовой идеей для любого back-end разработчика. Глобальные хранилища — это зло для любого боьлшого проекта!
Так в каких случаях уместно данная архитектура? За счёт быстро изменяющихся условий в бизнесе и рынке, когда скорость разработки (или другими словами стоимость) особо важна, пожалуй, это достаточно удачное решение для разного рода прототипов, стартапов для которых скорость разработки на начальных этапах жизненно необходима, даже в ущерб скорости развития в будущем. Так же это достаточно удачное решение и для приложений которые не собираются развиваться с точки зрения функциональности слишком широко (узко направлены). А вот для огромных enterprise приложений над которыми трудится несколько (иногда десятки) команд и приложение может развиваться достаточно не предсказуемо (например банковское ПО, где может существовать потенциально сотни подразделов) от single store архитектуры придётся отказаться.