Меня зовут Ксюша Луговая. В СберКорусе я занимаюсь поддержкой библиотеки React-компонентов Korus-UI.  С проблемой выбора библиотеки рано или поздно сталкивается почти каждый разработчик, и порой решение может быть нетривиальным. Возникают вопросы: чем руководствоваться при выборе библиотеки, какие популярные решения предлагает рынок, какие у них плюсы и минусы? Обзоры и отзывы не всегда помогают найти решение. В мире разработки не существует идеального варианта на все случаи. Поэтому в статье я расскажу, как мы решаем эту задачу, и разберу на примерах анализа нескольких популярных решений, как выбрать библиотеку React-компонентов для своего проекта.  Сценарии использования библиотеки. Это звучит очевидно, но четкое понимание задач — первоочередный критерий выбора. Типы компонентов приложения. От типа приложения зависит, какие компоненты вам потребуются. Часто достаточно набора кнопок/чекбоксов, базовых полей ввода, списков/меню с готовыми стилями. Значит, можно воспользоваться простыми компонентами с минимальным количеством настроек и готовыми стилями. Настройки, форматирование и интерактивность в дизайне. Если вам нужно значительно отформатировать и стилизовать свои компоненты, это тоже важно решить заранее. Когда требования четко сформулированы, ответьте на вопросы: Хорошо ли составлена документация проекта, есть ли интерактивные примеры? Насколько активно поддерживается проект? Сколько в проекте issues и как быстро они решаются? Проект бесплатный или коммерчески лицензированный? Насколько легко настраиваются компоненты? Покрыт ли код библиотеки тестами? Какие браузеры и платформы поддерживает библиотека? Это универсальные вопросы, которые помогут выбрать библиотеку. Даже если функционально решение идеально подходит под нужды вашего проекта, отсутствие поддержки или большое количество нерешенных багов — веская причина выбрать другую библиотеку.  Я отобрала следующие библиотеки, чтобы наглядно показать процесс анализа по критериям: Material-UI, Semantic-UI-React, yandex-ui, arui-feather, Korus-UI. С одной стороны, в этом списке  представлены наиболее популярные проекты – Material-UI и Semantic-UI-React, которые были созданы одним разработчиком и со временем обросли большим сообществом. С другой стороны – библиотеки, созданные внутри крупных компаний (Яндекс, Альфа Банк) для своих проектов, которые постепенно обрели популярность в качестве opensource решений. Далее рассмотрим сравнение библиотек в разрезе определенных выше критериев. Главная цель подключения библиотеки — набор компонентов для приложений, которые можно использовать повторно и легко комбинировать при создании более сложных модулей. Компоненты библиотек можно разделить на несколько групп. Layout-компоненты  Контейнеры, карточки, таблицы, гриды и прочие. Основные характеристики: Отвечают только за отображение; Часто принимают на вход только props.children; Не имеют своего состояния и методов жизненного цикла; Примеры:  h1, section, div, span, Icon, Avatar. Готовые дизайн-системы библиотек сильно упрощают верстку, если проекту не нужна своя тема стилей. Например, Material-UI и  Semantic-UI могут вполне справиться с этой задачей. Однако в крупных коммерческих проектах своя дизайн-система и кастомизация стилей библиотек будет избыточной. Компоненты-контролы (controls) Кнопки, чекбоксы, радиокнопки, поля ввода, слайдеры — небольшие базовые компоненты, которые помогают «оживить» контент и обеспечивать взаимодействие с пользователем.  Основные характеристики: Отвечают за отображение и не имеют внутреннего состояния; Принимают данные и функции обратного вызова в качестве props; Состояние компонентов связано в основном только с UI (disabled, required, isLoading). Сложные модульные компоненты Это группа компонентов с более сложной логикой, они расширяют функции базовых компонентов и могут их комбинировать.  Основные характеристики: Имеют состояние; Предоставляют данные и логику layout-компонентам (валидация, форматирование вывода, автодополнение); Комбинируют другие компоненты.   Layout Controls Modules Количество компонентов Material-UI App Bar, Avatars, Badges, Bottom Navigation, Divider, Grid List, Lists, Paper, Progress, Snackbar, Tables,  Button, Chip, Selection Controls, Text Fields, Pickers* Dialog, Cards, Drawers, ExpansionPanel, Menu, Stepper, Tabs, Tooltip 26** Semantic-UI-React Container, Divider, Flag, Header, Icon, Image, Label, List, Loader, Placeholder, Rail, Reveal, Segment, Step, Breadcrumb, Form, Grid, Menu, Message, Table, Advertisement, Card, Comment, Feed, Item, Statistic Button, Input, Checkbox, Radio, Select, Text Area Accordion, Dimmer, Dropdown, Embed, Modal, Popup, Progress, Rating, Search, Sidebar, Sticky, Tab, Transition, Visibility, Confirm, Pagination, Portal, Ref, Transitionable Portal 52 yandex-ui Badge, Divider, Icon, Image, Text, UserPic, ListTile, Spacer, Link, Spin Attach, Button, Checkbox, Menu, Radiobox, RadioButton, Select, Slider, Textarea, Textinput, Tumbler TabsMenu, Drawer, Dropdown, Messagebox, Modal, Popup, TabsPanes, Tooltip, Progress  30 arui-feather Amount, CardImage, FlagIcon, Form, GridRow, GridCol, Heading, Icon, InputGroup, Label, Link, List, Paragraph, Spin Attach, Button, CardInput, CheckBoxGroup, CheckBox, FormField, IconButton, Input, RadioGroup, Radio, Select, TagButton, Textarea, Toggle CalendatInput, Calendar, Collapse, EmailInput, InputAutocomplete, IntlPhoneInput, Menu, MoneyInput, Notification, PhoneInput, Plate, Popup, ProgressBar, Sidebar, SlideDown, Tabs 44 Korus-UI HTML tags factory***, Currency, Tags Button, Checkbox, Input,  Radio, Rating, Slider, Switcher, Textarea Autocomplete, ButtonGroup, Collapse, Collapsible,  DatePicker, DateRange, DateTimePicker, DateTimeRange, Dropdown, DropdownLink, DropdownSelect, Dropzone, FileDrop, FileUpload, Loader, MaskedInput, Modal, MultiSelect, Notifications, NumericRange, NumericTextBox, Pagination, Password, ProgressBar, StatusBar, StickyPanel, Tabs, TimePicker, TimeRange, Tooltip, Tour,  Validation, VStepper, Wizard, form 45 + Компоненты-обертки для всех основных HTML-тегов *Material-UI использует нативный календарь браузера в компонентах с выбором даты **Основные компоненты библиотеки, для которых есть примеры в документации ***Korus-UI создает обертку для всех основных HTML-тегов c единым API Почти 50% компонентного состава Material-UI и Semantic-UI-React и около 30% в библиотеках yandex-ui и arui-feather — малофункциональные layout-компоненты. В Korus-UI более 70% — сложные модульные компоненты. Возможность подстраивать компоненты под собственный дизайн экономит много времени и сил в будущем. Сравним подходы к кастомизации визуального отображения компонентов на примерах. Material-UI С помощью MuiThemeProvider. Компонент использует контекст библиотеки React для передачи объекта с темой всем дочерним компонентам. Через добавление классов. Все компоненты поддерживают атрибут className. Для кастомизации дочерних компонентов необходимо воспользоваться атрибутом classes. Библиотека заточена на применение CSS-in-Js, что может вызвать определенные трудности, если стили для приложения содержатся в CSS-файлах. Для внедрения кастомных стилей CSS-in-Js предоставляется HOC withStyles() либо хук makeStyles() для функциональных компонентов. Semantic-UI-React У Semantic-UI-React нет своей темы, можно использовать стили  Semantic-UI. Библиотека предоставляет несколько конфигурационных файлов, в которых можно указать кастомные настройки для всей темы или отдельных компонентов.  Это: Изменение размеров контейнера страницы, шрифтов и цветов по умолчанию с помощью site.variables; Переопределение css-переменных ; Объединение нескольких отдельных тем компонентов в один файл theme.config; Изменение пути к assets и использование кастомного иконочного шрифта. yandex-ui У библиотеки Яндекса несколько пресетов с темами. Их можно подключить сразу для всего проекта или применить стили для определенных компонентов. Возможности: Создание кастомной темы с помощью инструмента themekit;  Переопределение значения (токены) в теме; Дизайн-токены в формате yaml или json. Их можно собрать в итоговый файл (css, json, js, ios, android) и подключить к проекту. arui-feather (Альфа Банк) У библиотеки Альфа Банка нет руководства по кастомизации стилей в общедоступной документации.  Компоненты поддерживают атрибут className, возможно задать кастомные классы только их оберткам. Korus-UI (СберКорус) Кастомизация темы с помощью компонента LedaProvider. Он использует контекст библиотеки React для передачи объекта с темой всем дочерним компонентам. Можно написать кастомные стили под имеющуюся вёрстку. Полный список классов  в компонентах находится в разделе API-документации (см. атрибут theme). Их можно переопределять глобально для всех компонентов одного типа или для каждого индивидуально.  В работе с библиотекой может возникнуть потребность изменить внутренний элемент компонента. Например, добавить картинку или иконку в поле ввода, заменить элемент на новый (в компонент Loader передать кастомный элемент спиннера). Рассмотрим решения. Material-UI Позволяет изменять корневые элементы с помощью атрибута component. Например, компонент List по дефолту рендерит <ul> элемент. Его можно заменить другим элементом или React компонентом:  Semantic-UI Semantic-UI-React компоненты поддерживают схожий по функциональности атрибут as: Переданный элемент или React-компонент заменяют корневой элемент. Все неподдерживаемые пропсы передаются корневому элементу в качестве атрибутов. yandex-ui Предлагает использовать библиотеку render-override.  В ней есть набор хуков и компонентов для реализации переопределения элементов внутри составного компонента.  Пример:  В библиотеке yandex-ui расширяемость для существующих компонентов не реализована. arui-feather (Альфа Банк) Расширяемость компонентов не реализована. Korus-UI Расширяемость внутренних элементов библиотеки с помощью специального API. На вход компоненту можно передать атрибут из названия элемента и суффикса Render. Атрибуту присваивается функция, возвращающая элемент, которым заменяют существующий. Простейший пример: Структура метода позволяет вносить изменения максимально гибко: Element - сам элемент elementProps - props элемента componentState, componentProps - для удобства дополнительно приходят объекты с props и state всего компонента   Если мы хотим, чтобы новый элемент принимал на вход те же пропсы, можно отредактировать пример: Для типизации React-проектов применяются 2 основных инструмента: Typescript PropTypes В документации React для большой кодовой базы отдается предпочтение Typescript. Это инструмент статической типизации, который позволяет отлавливать большинство ошибок еще до исполнения кода. У PropTypes проверка типизации осуществляется только после запуска кода — это существенный недостаток по сравнению с другими инструментами. В основном рассматриваемые библиотеки для типизации используют Typescript. У Semantic-UI основная библиотека написана на ванильном JS, а Typescript используется только в Semantic-UI-React, созданной для интеграции с библиотекой React. Хороший процент покрытия тестами — важный показатель качества кодовой базы. Потому что покрытие тестами дает некоторые гарантии, что изменение или добавление новых функций ничего не сломает. Это особенно важно для библиотеки компонентов с точки зрения обратной совместимости и для разработчиков, которые используют библиотеку в своих проектах. Очередное обновление версии не должно приводить к появлению трудно распознаваемых ошибок. Ради справедливости стоит отметить, что автоматические тесты — не панацея. Высокий процент покрытия не гарантирует качество теста и охват основных пользовательских сценариев. Но без покрытия тестами невозможно проверить совместную работу компонентов (интеграционное тестирование) и их работу вообще (модульное тестирование). Сравним библиотеки на покрытие тестами.  Инструменты  Типы тестов % покрытия Material-UI Chai, Mocha, Sinon Unit 95.28% Statements 87.22% Branches 97.51% Functions 95.26% Lines Semantic-UI Jasmine, Karma Unit Отчет о покрытии отсутствует Semantic-UI-React Chai, Enzyme Unit Отчет о покрытии отсутствует yandex-ui Jest, Enzyme Unit Запуск тестов приводит к ошибке arui-feather Jest, Enzyme Unit 88.1% Statements 73.84% Branches 66.61% Functions 87.19% Lines Korus-UI Cypress, Jest Unit, end-to-end 69.28% Statements 56.14% Branches 66.29% Functions 71.78% Lines Качественная библиотека компонентов должна предоставлять хорошо структурированный сайт с документацией, которая включает большое количество интерактивных примеров. Storybook с демонстрацией функций компонентов может существенно сэкономить время при использовании библиотеки.  Документация Наличие интерактивных примеров Storybook Material-UI https://material-ui.com/ru/ - - Semantic-UI-React https://react.semantic-ui.com/ + - yandex-ui https://yastatic.net/s3/frontend/lego/storybook/index.html - + arui-feather https://digital.alfabank.ru/ + - Korus-UI https://opensource.esphere.ru/korus-ui/ + + Иногда возникает проблема, которая требует сторонней помощи. Нужно заранее определить, как ее получить. Ситуация с технической поддержкой решений с открытым исходным кодом неоднозначна. Если библиотека, которую вы планируете использовать, имеет большое сообщество, можно получить помощь от других разработчиков, вносящих свой вклад в развитие библиотеки. Но результат непредсказуемый: на ваши вопросы могут ответить не очень быстро или не ответить вообще, если проблема никого не заинтересует.  По этой причине выигрышно смотрятся библиотеки от крупных компаний-разработчиков. У них есть техподдержка и постоянная команда разработки, поэтому больше шансов решить проблему оперативно. Правки от крупных разработчиков поступают в продакшн по графику, закрепленному в релизной политике, а ответы на запросы дают своевременно. В разделе Pulse на GitHub можно ознакомиться со статистикой репозитория по количеству Pull Request и коммитов за определенный период времени. Он находится на вкладке Insights каждого репозитория. Рассмотрим статистику по выбранным библиотекам. Material-UI Semantic-UI yandex-ui  arui-feather (Альфа Банк)  Korus-UI (СберКорус) Популярность библиотеки принято оценивать по звездам на GitHub и количеству скачиваний npm-пакета. Показатели легко проверить и измерить, они свидетельствуют о доверии разработчиков и наличии сообщества у библиотеки. Это упрощает ее использование и поиск решений для возникающих проблем.  Однако стоит помнить, что популярность — это также результат хорошей маркетинговой стратегии и SEO-оптимизации, которые могут обеспечить библиотеке первые места в выдаче поисковика. Поэтому следует изучить обсуждения в блогах и на форумах, например, на Stackoverflow, Medium, DEV. Обсуждения находятся в разделе issues проекта.  К сожалению, проанализировать и формально оценить всю доступную информацию из источников в рамках статьи невозможно, поэтому ограничимся количественными показателями. Для более реалистичной оценки качества библиотеки оценим соотношение положительных отзывов и количество скачиваний.  Звезды Скачивания за последний год Соотношение количества звезд и скачиваний за последний год,  %  Material-UI 63 400 6 372 353 0,99 Semantic-UI 48 800 541 299 9 Semantic-UI-React 11 900 8 620 967 0,14 @yandex/ui 212 15 902 1,33 arui-feather (Альфа Банк) 559 26 744 2  Формы используются почти во всех приложениях. Это основной способ взаимодействия с пользователем. Даже если вы делаете простой лендинг, на нем скорее, всего будет, форма обратной связи. В сложном приложении могут быть десятки различных форм, начиная с формы авторизации.  При взаимодействии с пользователем возникают разные проблемы: от ввода невалидных данных до попыток внедрения вредоносного кода. Поэтому золотым стандартом является валидация введенных данных до того, как они будут отправлены на сервер.  Валидация может быть простой, например, на непустое значение (сделать поле обязательным). Или более сложной (кросс-валидация), когда данные в одном поле формы учитываются при проверке значений в других полях. Сравним работу с формами в различных библиотеках на конкретном примере. Задача: создать базовую форму авторизации с двумя полями для ввода логина и пароля и кнопкой отправки формы. Поля мы хотим сделать обязательными, чтобы незаполненное поле подсвечивалось, а текст ошибки отображался как при потере фокуса, так и после нажатия на кнопку «Отправить». Korus-UI  Material-UI  Semantic-UI-React  arui-feather  yandex-ui  Как видно из примеров, в Korus-UI задача создания формы с валидацией решается парой дополнительных атрибутов, тогда как в остальных библиотеках требуется достаточно много кода и проверок.  В Material-UI и yandex-ui нет компонента формы, в Semantic-UI-React и arui-feather компонент формы является простой оберткой тега <form> и не предоставляет никакой дополнительной функциональности. Встроенная валидация полей отсутствует во всех рассмотренных библиотеках, кроме Korus-UI. Для реализации более сложной логики понадобится еще одна библиотека. Подведем итог сравнительного анализа пяти библиотек React-компонентов.  Korus-UI (СберКорус) Material-UI Semantic-UI-React arui-feather (Альфа Банк) yandex-ui Документация Storybook + – – – + Примеры можно редактировать прямо в документации + – + + – Поддержка Количество Pull Request за последний месяц 70 241 2 0 0 Лицензия  MIT license MIT license MIT license Mozilla Public License 2.0 Mozilla Public License 2.0 Покрытие тестами Процент покрытия > 50% + + – + Не удалось выяснить E2E тесты + – – – – Поддержка браузеров и платформ  Chrome 85.0.4183.121 >= 49 Last 2 v. Last 2 v. Last 2 v. Firefox 81.0.1 >= 52 Last 2 v. Last 2 v. >= 23 Edge 85.0.564.44 >=14 12+ Last 2 v.  IE 11 11 11+ 11+ 11+ Safari 14 >= 10 Last 2 v. Last 2 v.  Opera     Last 2 v. >= 12.1 Yandex     Last 2 v. ? Android     4.4+ 5+ >= 4 iOS Safari   7+ Last 2 v. >= 5.1 Кастомизируемость Возможность подключения кастомной темы + + + – + Расширяемость  + + + – – Типизация  Typescript Typescript Typescript Typescript Typescript Популярность Соотношение звезд на GitHub и количества скачиваний за последний год, % – 0,99 0,14 2 1,33 Компонентный состав Есть компонент для работы с формами + – + + – Наличие встроенной валидации + – – – – В этой таблице приведены только универсальные критерии для оценки качества инструментов. Кроме них, на выбор библиотеки значительно влияют субъективные факторы и конкретные требования проекта. Далее я расскажу, на какие факторы ориентировались мы в СберКорусе, и как было принято решение о создании своей библиотеки. Может возникнуть вопрос: зачем нужна еще одна библиотека? На рынке уже существует большое количество библиотек компонентов React на любой вкус. Мы решили создать свою библиотеку, потому что ни одно из существующих решений не удовлетворяло нас полностью по компонентному составу, возможностям расширения и кастомизации. Не устраивали также возможности настройки форм и валидации данных — функции, которые нужны буквально в каждом проекте. Были и объективные причины: недостаточное покрытие тестами кодовой базы, низкая активность в репозиториях библиотек. При разработке коммерческих проектов отсутствие своевременной поддержки со стороны команды библиотеки может стать досадной причиной срывов дедлайнов.  С учетом всех факторов в компании было принято решение создать свою библиотеку React-компонентов, которая упростила бы разработку фронтенда на всех будущих проектах. Кроме того, при большом количестве крупных заказов возникает острая необходимость в едином стеке технологий и универсальных инструментах для всех проектов.  Ясно, что такие инструменты должны соответствовать высоким стандартам качества, предоставлять гибкие возможности по расширяемости и кастомизируемости. На разработку библиотеки Korus-UI ушло 1,5 года. В процессе создания мы ориентировались на лучшие практики разработки opensource-библиотек.  Формы и валидация В Korus-UI подход к построению форм принципиально иной: поля и кнопка отправки формы связываются атрибутом form, в который передается строка с названием формы. Так элементы одной формы могут находиться в разных контейнерах, подключаться динамически, никакие общие обертки им не нужны. При этом создается объект формы, к которому можно получить доступ в обработчиках событий или с помощью метода  L.form(). Есть возможность передать кнопке массив из названий форм, чтобы валидировать и отправлять несколько форм одним кликом. У библиотеки Korus-UI удобный обработчик onValidationFail, который позволяет получить объект формы, не прошедшей валидацию. А еще есть приятный бонус — прокрутки к невалидным полям. Валидация в Korus-UI — это отдельный компонент. Его основные фичи: Валидация поля функцией или RegExp Готовые валидаторы Один или несколько валидаторов для каждого поля со своими сообщениями Настраиваемые сообщения (текст и внешний вид) Задание валидности поля извне через атрибут isValid Валидация компонентов в состоянии unmounted Валидация полей по потере фокуса, сабмите формы и по событию в приложении Прокрутка к невалидным полям при сабмите формы Валидация нескольких форм одной кнопкой Вспомогательные функции для валидации переданных значений Единообразный API Все компоненты поддерживают атрибуты, начинающиеся с нижнего подчеркивания _. Такие атрибуты будут преобразованы в имена css-классов: Атрибут className также поддерживается. В каждый компонент можно передать атрибут theme, который содержит набор css-классов для элементов компонента. Все компоненты поддерживают атрибуты с суффиксом Render (см. раздел расширяемость). Поведение и структура события расширены, соблюдается единый стандарт для всех компонентов: Названия атрибутов с булевыми значениями начинаются с: is: isOpen, isValid, isRequired, isDisabled has: hasCloseButton should: shouldCorrectValue Все компоненты поддерживают атрибут ref. Korus-UI расширяет механизм ref, принятый в React. Сейчас библиотека используется в основном только в проектах СберКоруса, у нее пока не сформировалось свое сообщество. Так что вы не сможете получить информацию из блогов или на форумах, но всегда можете создать issue или обратиться к разработчикам библиотеки напрямую и быстро получить обратную связь. Еще можно отметить отсутствие поддержки мобильных платформ iOS и Android. Сейчас библиотека гарантирует поддержку только последних версий популярных браузеров. Подробная информация приведена в сравнительной таблице выше. Мы подробно рассмотрели основные критерии выбора библиотеки React-компонентов и проанализировали библиотеки Material-UI, Semantic-UI-React, arui-feather (Альфа Банк), yandex-ui, Korus-UI (СберКорус), опираясь на критерии качества.  Вот коротко то, что нужно учесть при выборе библиотеки:  Собственные нужды и требования Кастомизируемость Расширяемость Типизацию Покрытие тестами Наличие техподдержки Документацию Отзывы и активность сообщества библиотеки С учетом всех требований мы разработали собственную библиотеку Korus-UI, которая имеет все шансы стать достойным конкурентом существующим на рынке инструментам. Библиотека активно развивается, количество проектов, использующих Korus-UI в компании постоянно растет. В ближайшее время мы добавим новые компоненты. Также в планах расширение тестового покрытия, перевод на английский язык документации и актуализация Storybook. Библиотека  Korus-UI выложена в opensource и доступна на GitHub. Это первый шаг для нашей компании в opensource, и мы уверены, что не последний:) Отдельно хочу выразить благодарность команде разработчиков СберКоруса, отцу и идейному вдохновителю библиотеки Артёму Повольских. Если вам интересно, как устроена фронтенд-разработка в СберКорусе, читайте статью Артёма. Делитесь в комментариях своим опытом использования библиотек компонентов. Интересно обсудить, с какими преимуществами и недостатками вы сталкивались на личном опыте и какого функционала вам не хватает в процессе работы.