Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
golosio
6 лет назад

Golos.io: Рефакторинг и редизайн

Друзья, мы с вами поговорили о проблемах существующей кодовой базы Golos.io и обозначили дальнейший путь развития; обсудили новую архитектуру клиента по части: скорости работы сайта и производительности, а также инфраструктурных сервисов.

И теперь можем поднять вопрос редизайна Golos.io, который неразрывно связан с рефакторингом, так как невозможен без переработки текущего кода.

Рефакторинг и редизайн

Относительно недавно мы приступили к редизайну сайта Golos.io. В первую очередь попытались изменить стили, без изменения основного кода компонентов. Однако, вскоре поняли, что такой подход не приносит удовлетворительных результатов. Дело в том, что в текущем клиенте используется Foundation Framework, и имеется достаточно большой массив css кода, разработанного командой steemit. Пойдя по пути каскадного переопределения стилей, без рефакторинга логики компонентов, стало очевидно, что такой подход нежизнеспособен, из-за огромного количества возникающих коллизий и сайд эффектов. В связи с этим мы приняли решение написать компоненты заново и реструктуризировать проект.

Роутинг страниц

В текущей реализации роутинга, пришедшей от steem, есть, как минимум, две проблемы:

  • Определение открытой страницы происходит с использованием регулярных выражений, и без использования возможностей пакета react-router. Вследствии чего сложно понять, какой компонент страницы сейчас просматривается пользователем.
  • Вопреки redux практикам, в приложении существует единое место сбора данных. Из-за этого трудно определить, как и где были сформированы данные

Отсюда вытекают сложности в реализации нового функционала и интуитивного понимания кода.

Требования

Мы делаем SPA-приложение, которое работает со сложными структурами данных, требующими дополнительной обработки на клиенте после получения ответа от api.
К тому же, основным требованием для нас является оптимизация страниц под работу поисковых ботов, поэтому мы должны реализовывать серверный рендеринг страниц (SSR).
Нам необходимо сохранить возможность обработки данных и SSR, но избавиться от текущих проблем за счет последовательного рефакторинга, без масштабной переделки проекта в течении долгого времени, а в рамках реализации новых страниц.

Стратегия улучшения

  • Работая над новой страницей, в app/RootRoute.js нужно описать новый роут (маршрут) с path и component (loadable контейнер) в самом нижнем условии (после else).
  • Каждый контейнер, которому требуются данные для SSR, должен реализовывать статичный async метод getInitialProps с вызовами экшенов (например, выполняющих запросы к api).
  • Сервер должен искать текущий роут и вызывать метод getInitialProps у относящегося к нему компонента.
    После того, как каждый контейнер будет вызывать экшены для загрузки необходимых ему данных, мы сможем отказаться от регулярных выражений для определения роута, пришедших от steem.

Данные

В существующем варианте приложения данные поступают через redux-saga, исходя из роута, определенного с помощью регулярных выражений. Следуя redux way, такая реализация некорректна, и требует рефакторинга.

Идеальным вариантом заполнения необходимыми данными redux хранилища, является вызов экшена в момент mount (монтирования) контейнера (на клиенте) и вызова специального метода контейнера (при серверном рендеринге).

Специально написанный redux middleware должен слушать экшен определенной структуры и выполнять необходимые манипуляции для выполнения запроса, обработки полученных данных и выполнять действие в случае ответа с ошибкой.

Обновленная структура проекта

Папка src является основной папкой, в которой мы храним:

  • app - SPA-приложение;
  • server - SSR приложение и api для него (перенесем в ближайшее время).

В свою очередь папка app имеет следующие вложенности:

├── components
│ ├── common
│ ├── golos-ui
│ └── папки с именами папок контейнеров
├── containers
├── helpers
├── redux
│ ├── actions
│ ├── constants
│ ├── reducers
│ ├── sagas
│ └── selectors
└── themes

Разделение логики проекта

Приложение имеет следующие слои распределения логики:

  • store - папка redux;
  • selectors - папка redux/selectors;
  • containers - папка containers;
  • presentational components - папка components/(имя контейнера или страницы);
  • dumb components - папка components/golos-ui, components/common и styled-components в presentational components.

Store

  • entities - хранит результат работы redux-entities-immutable, после нормализации;
  • status - хранит статусы запросов, ошибки, данные, которые нельзя вынести в entities из-за неподходящей реализации api;
  • ui - хранит изменение интерфейса, сгруппированные по страницам;
  • и остальная структура хранения данных, пришедшая от steemit.

Selectors

Селекторы - это функции, задача которых получить данные из стора (хранилища данных), трансформировать и агрегировать их для дальнейшей передачи по следующим слоям.

Containers

Контейнеры - это компоненты верхнего уровня, задачи которых получить данные и экшены через props, и описать основные методы, которые понадобятся в presentational components.
Пример: containers/userProfile/settings/SettingsContent

Presentational components

Это компоненты, которые лежат в папке components, сгруппированные по папкам на основе принадлежности к конкретным контейнерам. Их задача получить props и методы от контейнера, описать рендеринг dumb components и передать им конечные данные.
В рамках этого слоя, в идеальном варианте, должен быть компонент, который является основным presentational component для конкретного контейнера. Он должен описывать рендеринг других presentational components для разделения логики по выполняемым задачам и отображаемым сущностям.
Пример: components/userProfile/SettingsShow

Dumb components

Это компоненты, которые не реализуют логику, не описывают экшены, а вызывают переданные методы и рендерят конечные данные.
Примеры: components/golos-ui, components/common и styled-components в presentational components.

Переход на styled-components

Препроцессоры, такие как SASS и LESS, добавляют много полезных функций, но они не решают проблем, приводящих к анархии CSS. Поэтому работа по организации кода остается для таких методологий, как BEM, которые хотя и полезны, но не являются обязательными и не могут применяться на уровне языка или инструментов.

Основная идея styled-components заключается в том, чтобы применять лучшие практики, удаляя сопоставление между стилями и компонентами.

Так же, styled-components хорошо поддерживают темы, то есть, в будущем можно будет легко использовать библиотеки компонентов на базе styled-components без необходимости использовать что-то кроме документации, чтобы адаптировать их внешний вид, согласно общему стилю сайта.

Итак, после реализации описанных ранее сервисов, усовершения инфраструктуры клиента, улучшения его юзабилити, обновления внутренней структуры и внешнего вида, мы получим современное, производительное и дружелюбное по отношению к пользователям приложение.

Иллюстрация к посту - Yandex


Подписывайтесь на официальный аккаунт блог-платформы Golos.io @golosio, чтобы быть в курсе развития проекта! Телеграм для ваших вопросов — https://t.me/golos_support. Лучшее на Голосе — https://t.me/golos_best
Есть предложения, как сделать Golos.io лучше? Пишите в Issues на нашем Github, в наш Телеграм-канал или в чат разработчиков Golos.io в Телеграм!

С уважением, команда Golos.io @golosio: @alex-firsov, @bacher, @b1acksun, @chinpu, @dan-kinescop, @dekol, @devall, @format-x22, @insider, @jevgenika, @kucinskaya.alla, @muhazokotuha, @msm72, @nickshtefan, @yulia.rodnikova, @yuri-vlad.

1
35.304 GOLOS
На Golos с October 2016
Комментарии (8)
Сортировать по:
Сначала старые