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.


Comments 8


@golosio верните старый редактор. Работать в "новом" совсем неудобно.

Определение открытой страницы происходит с использованием регулярных выражениях,

Страниц вообще быть не должно. Это глупости. Страничный режим "удобно" читать на планшете (и то тормозит...), а на ПК эта фигня лишняя. Лучше масштабировать текст по всему экрану. Ваш "страничный режим" на широкоэкранных мониторах смотрится особенно глупо.

12.09.2018 13:45
0

@arturio777, в посте под "страницами" подразумеваются пути, по которым отображаются различные компоненты сайта, например такие как "пост", "лента", "профиль" и т.д.
То о чем ты пишешь это верстка, насколько я понимаю, и тебе не нравится, что она не в полный экран?

13.09.2018 09:44
0

@golosio , здравствуйте! А куда писать о возникшей проблеме с кошельком? Не приходят никакие уведомления. Написала по кнопке "обратная связь", но пост ушёл в общую ленту, где его никто не увидит. Пришлось его редактировать, как обращение к аудитории.

15.09.2018 14:35
0

@lllll1ll, здравствуйте!
На основной версии сайта уведомления пока не приходят. Мы тестируем новый сервис нотификаций на песочнице.
Или вы имеете в виду Android приложение?

17.09.2018 08:25
0

@yulia.rodnikova , нет, не Android.
Спасибо.

17.09.2018 08:32
0

@golosio Режим отображения постов во "всплывающем окне" (на отдельном слое) на больших экранах реально бесит.
Имеется ввиду вот это
"@media screen and (min-width: 67rem)
.PostsListpost_container, .PostsListpost_top_bar {
width: 62rem;
}"
Из него пользователь не может сразу же перейти куда-то. Сначала закрывает это "всплывающее окно", а только тогда переходит. Это лишний клик. Да и после обновления страницы - она всеравно уже открывается не во "всплывающем окне".

28.09.2018 19:50
0

@golosio Привет! Подписался на ваш канал! Надеюсь на такой же ответ, взаимную подписку и дружбу. Спасибо! Желаю удачи вам!

12.10.2018 23:26
0

лайк

27.11.2018 13:06
0